From d6434e1042f3b0a6dfe1b1f615af369486f9b1fa Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Sat, 9 Oct 1999 00:00:47 +0000 Subject: Merge with 2.3.19. --- ipc/msg.c | 40 ++++++++++--------- ipc/sem.c | 6 +-- ipc/shm.c | 128 +++++++++++++++++++++++++++++++++++++------------------------ ipc/util.c | 22 +++++------ 4 files changed, 113 insertions(+), 83 deletions(-) (limited to 'ipc') diff --git a/ipc/msg.c b/ipc/msg.c index 86e5a9f26..757d95a1b 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -30,7 +30,7 @@ static int findkey (key_t key); static int sysvipc_msg_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data); #endif -static struct msqid_ds *msgque[MSGMNI]; +static struct msqid_ds_kern *msgque[MSGMNI]; static int msgbytes = 0; static int msghdrs = 0; static unsigned short msg_seq = 0; @@ -46,7 +46,7 @@ void __init msg_init (void) #endif for (id = 0; id < MSGMNI; id++) - msgque[id] = (struct msqid_ds *) IPC_UNUSED; + msgque[id] = (struct msqid_ds_kern *) IPC_UNUSED; msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0; init_waitqueue_head(&msg_lock); #ifdef CONFIG_PROC_FS @@ -59,7 +59,7 @@ void __init msg_init (void) static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) { int id; - struct msqid_ds *msq; + struct msqid_ds_kern *msq; struct ipc_perm *ipcp; struct msg *msgh; long mtype; @@ -136,7 +136,7 @@ static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) { - struct msqid_ds *msq; + struct msqid_ds_kern *msq; struct ipc_perm *ipcp; struct msg *tmsg, *leastp = NULL; struct msg *nmsg = NULL; @@ -233,7 +233,7 @@ static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgty return -1; } -asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) +asmlinkage long sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) { int ret; @@ -243,8 +243,8 @@ asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msg return ret; } -asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, - long msgtyp, int msgflg) +asmlinkage long sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, + long msgtyp, int msgflg) { int ret; @@ -257,7 +257,7 @@ asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, static int findkey (key_t key) { int id; - struct msqid_ds *msq; + struct msqid_ds_kern *msq; for (id = 0; id <= max_msqid; id++) { while ((msq = msgque[id]) == IPC_NOID) @@ -273,20 +273,20 @@ static int findkey (key_t key) static int newque (key_t key, int msgflg) { int id; - struct msqid_ds *msq; + struct msqid_ds_kern *msq; struct ipc_perm *ipcp; for (id = 0; id < MSGMNI; id++) if (msgque[id] == IPC_UNUSED) { - msgque[id] = (struct msqid_ds *) IPC_NOID; + msgque[id] = (struct msqid_ds_kern *) IPC_NOID; goto found; } return -ENOSPC; found: - msq = (struct msqid_ds *) kmalloc (sizeof (*msq), GFP_KERNEL); + msq = (struct msqid_ds_kern *) kmalloc (sizeof (*msq), GFP_KERNEL); if (!msq) { - msgque[id] = (struct msqid_ds *) IPC_UNUSED; + msgque[id] = (struct msqid_ds_kern *) IPC_UNUSED; wake_up (&msg_lock); return -ENOMEM; } @@ -312,10 +312,10 @@ found: return (unsigned int) msq->msg_perm.seq * MSGMNI + id; } -asmlinkage int sys_msgget (key_t key, int msgflg) +asmlinkage long sys_msgget (key_t key, int msgflg) { int id, ret = -EPERM; - struct msqid_ds *msq; + struct msqid_ds_kern *msq; lock_kernel(); if (key == IPC_PRIVATE) @@ -342,7 +342,7 @@ asmlinkage int sys_msgget (key_t key, int msgflg) static void freeque (int id) { - struct msqid_ds *msq = msgque[id]; + struct msqid_ds_kern *msq = msgque[id]; struct msg *msgp, *msgh; msq->msg_perm.seq++; @@ -350,7 +350,7 @@ static void freeque (int id) msgbytes -= msq->msg_cbytes; if (id == max_msqid) while (max_msqid && (msgque[--max_msqid] == IPC_UNUSED)); - msgque[id] = (struct msqid_ds *) IPC_UNUSED; + msgque[id] = (struct msqid_ds_kern *) IPC_UNUSED; used_queues--; while (waitqueue_active(&msq->rwait) || waitqueue_active(&msq->wwait)) { wake_up (&msq->rwait); @@ -365,10 +365,10 @@ static void freeque (int id) kfree(msq); } -asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) +asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) { int id, err = -EINVAL; - struct msqid_ds *msq; + struct msqid_ds_kern *msq; struct msqid_ds tbuf; struct ipc_perm *ipcp; @@ -421,7 +421,9 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) tbuf.msg_rtime = msq->msg_rtime; tbuf.msg_ctime = msq->msg_ctime; tbuf.msg_cbytes = msq->msg_cbytes; + tbuf.msg_lcbytes = msq->msg_cbytes; tbuf.msg_qnum = msq->msg_qnum; + tbuf.msg_lqbytes = msq->msg_qbytes; tbuf.msg_qbytes = msq->msg_qbytes; tbuf.msg_lspid = msq->msg_lspid; tbuf.msg_lrpid = msq->msg_lrpid; @@ -462,8 +464,10 @@ asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) tbuf.msg_stime = msq->msg_stime; tbuf.msg_rtime = msq->msg_rtime; tbuf.msg_ctime = msq->msg_ctime; + tbuf.msg_lcbytes = msq->msg_cbytes; tbuf.msg_cbytes = msq->msg_cbytes; tbuf.msg_qnum = msq->msg_qnum; + tbuf.msg_lqbytes = msq->msg_qbytes; tbuf.msg_qbytes = msq->msg_qbytes; tbuf.msg_lspid = msq->msg_lspid; tbuf.msg_lrpid = msq->msg_lrpid; diff --git a/ipc/sem.c b/ipc/sem.c index 5a48748a2..3d8781146 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -157,7 +157,7 @@ found: return (unsigned int) sma->sem_perm.seq * SEMMNI + id; } -asmlinkage int sys_semget (key_t key, int nsems, int semflg) +asmlinkage long sys_semget (key_t key, int nsems, int semflg) { int id, err = -EINVAL; struct semid_ds *sma; @@ -394,7 +394,7 @@ static void freeary (int id) kfree(sma); } -asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg) +asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) { struct semid_ds *buf = NULL; struct semid_ds tbuf; @@ -615,7 +615,7 @@ out: return err; } -asmlinkage int sys_semop (int semid, struct sembuf *tsops, unsigned nsops) +asmlinkage long sys_semop (int semid, struct sembuf *tsops, unsigned nsops) { int id, size, error = -EINVAL; struct semid_ds *sma; diff --git a/ipc/shm.c b/ipc/shm.c index a02bc8ad1..94a8215af 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -6,6 +6,7 @@ * Fixed the shm swap deallocation (shm_unuse()), August 1998 Andrea Arcangeli. * * /proc/sysvipc/shm support (c) 1999 Dragos Acostachioaie + * BIGMEM support, Andrea Arcangeli */ #include @@ -15,7 +16,9 @@ #include #include #include +#include #include +#include #include #include @@ -143,7 +146,7 @@ found: int shmmax = SHMMAX; -asmlinkage int sys_shmget (key_t key, int size, int shmflg) +asmlinkage long sys_shmget (key_t key, int size, int shmflg) { struct shmid_kernel *shp; int err, id = 0; @@ -221,7 +224,7 @@ static void killseg (int id) return; } -asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) +asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) { struct shmid_ds tbuf; struct shmid_kernel *shp; @@ -369,7 +372,7 @@ out: * shmd->vm_next next attach for task * shmd->vm_next_share next attach for segment * shmd->vm_offset offset into segment - * shmd->vm_pte signature for this attach + * shmd->vm_private_data signature for this attach */ static struct vm_operations_struct shm_vm_ops = { @@ -427,7 +430,7 @@ static int shm_map (struct vm_area_struct *shmd) /* * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists. */ -asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) +asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) { struct shmid_kernel *shp; struct vm_area_struct *shmd; @@ -508,7 +511,7 @@ asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr) goto out; } - shmd->vm_pte = SWP_ENTRY(SHM_SWP_TYPE, id); + shmd->vm_private_data = shm_segs + id; shmd->vm_start = addr; shmd->vm_end = addr + shp->shm_npages * PAGE_SIZE; shmd->vm_mm = current->mm; @@ -544,16 +547,10 @@ out: /* This is called by fork, once for every shm attach. */ static void shm_open (struct vm_area_struct *shmd) { - unsigned int id; struct shmid_kernel *shp; lock_kernel(); - id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK; - shp = shm_segs[id]; - if (shp == IPC_UNUSED) { - printk("shm_open: unused id=%d PANIC\n", id); - return; - } + shp = *(struct shmid_kernel **) shmd->vm_private_data; insert_attach(shp,shmd); /* insert shmd into shp->attaches */ shp->u.shm_nattch++; shp->u.shm_atime = CURRENT_TIME; @@ -570,17 +567,17 @@ static void shm_open (struct vm_area_struct *shmd) static void shm_close (struct vm_area_struct *shmd) { struct shmid_kernel *shp; - int id; lock_kernel(); /* remove from the list of attaches of the shm segment */ - id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK; - shp = shm_segs[id]; + shp = *(struct shmid_kernel **) shmd->vm_private_data; remove_attach(shp,shmd); /* remove from shp->attaches */ shp->u.shm_lpid = current->pid; shp->u.shm_dtime = CURRENT_TIME; - if (--shp->u.shm_nattch <= 0 && shp->u.shm_perm.mode & SHM_DEST) + if (--shp->u.shm_nattch <= 0 && shp->u.shm_perm.mode & SHM_DEST) { + unsigned int id = (struct shmid_kernel **)shmd->vm_private_data - shm_segs; killseg (id); + } unlock_kernel(); } @@ -588,7 +585,7 @@ static void shm_close (struct vm_area_struct *shmd) * detach and kill segment if marked destroyed. * The work is done in shm_close. */ -asmlinkage int sys_shmdt (char *shmaddr) +asmlinkage long sys_shmdt (char *shmaddr) { struct vm_area_struct *shmd, *shmdnext; @@ -625,19 +622,13 @@ static unsigned long shm_nopage(struct vm_area_struct * shmd, unsigned long addr { pte_t pte; struct shmid_kernel *shp; - unsigned int id, idx; + unsigned int idx; + unsigned long page; + struct page * page_map; - id = SWP_OFFSET(shmd->vm_pte) & SHM_ID_MASK; + shp = *(struct shmid_kernel **) shmd->vm_private_data; idx = (address - shmd->vm_start + shmd->vm_offset) >> PAGE_SHIFT; -#ifdef DEBUG_SHM - if (id > max_shmid) { - printk ("shm_nopage: id=%d too big. proc mem corrupted\n", id); - return 0; - } -#endif - shp = shm_segs[id]; - #ifdef DEBUG_SHM if (shp == IPC_UNUSED || shp == IPC_NOID) { printk ("shm_nopage: id=%d invalid. Race.\n", id); @@ -649,26 +640,35 @@ static unsigned long shm_nopage(struct vm_area_struct * shmd, unsigned long addr } #endif + lock_kernel(); + again: pte = __pte(shp->shm_pages[idx]); if (!pte_present(pte)) { - unsigned long page = get_free_page(GFP_USER); - if (!page) { - oom(current); - return 0; - } - pte = __pte(shp->shm_pages[idx]); - if (pte_present(pte)) { - free_page (page); /* doesn't sleep */ - goto done; - } - if (!pte_none(pte)) { - rw_swap_page_nocache(READ, pte_val(pte), (char *)page); - pte = __pte(shp->shm_pages[idx]); - if (pte_present(pte)) { - free_page (page); /* doesn't sleep */ - goto done; + if (pte_none(pte)) { + page = __get_free_page(GFP_BIGUSER); + if (!page) + goto oom; + clear_bigpage(page); + if (pte_val(pte) != shp->shm_pages[idx]) + goto changed; + } else { + unsigned long entry = pte_val(pte); + + page_map = lookup_swap_cache(entry); + if (!page_map) { + swapin_readahead(entry); + page_map = read_swap_cache(entry); } - swap_free(pte_val(pte)); + pte = __pte(shp->shm_pages[idx]); + page = page_address(page_map); + if (pte_present(pte)) + goto present; + if (!page_map) + goto oom; + delete_from_swap_cache(page_map); + page_map = replace_with_bigmem(page_map); + page = page_address(page_map); + swap_free(entry); shm_swp--; } shm_rss++; @@ -678,9 +678,21 @@ static unsigned long shm_nopage(struct vm_area_struct * shmd, unsigned long addr --current->maj_flt; /* was incremented in do_no_page */ done: /* pte_val(pte) == shp->shm_pages[idx] */ - current->min_flt++; get_page(mem_map + MAP_NR(pte_page(pte))); + unlock_kernel(); + current->min_flt++; return pte_page(pte); + +changed: + free_page(page); + goto again; +present: + if (page_map) + free_page_and_swap_cache(page); + goto done; +oom: + unlock_kernel(); + return -1; } /* @@ -697,10 +709,13 @@ int shm_swap (int prio, int gfp_mask) unsigned long id, idx; int loop = 0; int counter; + struct page * page_map; + int ret = 0; + lock_kernel(); counter = shm_rss >> prio; if (!counter || !(swap_nr = get_swap_page())) - return 0; + goto out_unlock; check_id: shp = shm_segs[swap_id]; @@ -725,24 +740,35 @@ int shm_swap (int prio, int gfp_mask) page = __pte(shp->shm_pages[idx]); if (!pte_present(page)) goto check_table; - if ((gfp_mask & __GFP_DMA) && !PageDMA(&mem_map[MAP_NR(pte_page(page))])) + page_map = &mem_map[MAP_NR(pte_page(page))]; + if ((gfp_mask & __GFP_DMA) && !PageDMA(page_map)) + goto check_table; + if (!(gfp_mask & __GFP_BIGMEM) && PageBIGMEM(page_map)) goto check_table; swap_attempts++; if (--counter < 0) { /* failed */ failed: swap_free (swap_nr); - return 0; + goto out_unlock; } if (page_count(mem_map + MAP_NR(pte_page(page))) != 1) goto check_table; + if (!(page_map = prepare_bigmem_swapout(page_map))) + goto check_table; shp->shm_pages[idx] = swap_nr; - rw_swap_page_nocache (WRITE, swap_nr, (char *) pte_page(page)); - free_page(pte_page(page)); + swap_duplicate(swap_nr); + add_to_swap_cache(page_map, swap_nr); + rw_swap_page(WRITE, page_map, 0); + + __free_page(page_map); swap_successes++; shm_swp++; shm_rss--; - return 1; + ret = 1; + out_unlock: + unlock_kernel(); + return ret; } /* diff --git a/ipc/util.c b/ipc/util.c index 3fbd14833..c6423af6a 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -63,58 +63,58 @@ int shm_swap (int prio, int gfp_mask) return 0; } -asmlinkage int sys_semget (key_t key, int nsems, int semflg) +asmlinkage long sys_semget (key_t key, int nsems, int semflg) { return -ENOSYS; } -asmlinkage int sys_semop (int semid, struct sembuf *sops, unsigned nsops) +asmlinkage long sys_semop (int semid, struct sembuf *sops, unsigned nsops) { return -ENOSYS; } -asmlinkage int sys_semctl (int semid, int semnum, int cmd, union semun arg) +asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) { return -ENOSYS; } -asmlinkage int sys_msgget (key_t key, int msgflg) +asmlinkage long sys_msgget (key_t key, int msgflg) { return -ENOSYS; } -asmlinkage int sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) +asmlinkage long sys_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg) { return -ENOSYS; } -asmlinkage int sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, +asmlinkage long sys_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg) { return -ENOSYS; } -asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) +asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds *buf) { return -ENOSYS; } -asmlinkage int sys_shmget (key_t key, int size, int flag) +asmlinkage long sys_shmget (key_t key, int size, int flag) { return -ENOSYS; } -asmlinkage int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *addr) +asmlinkage long sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *addr) { return -ENOSYS; } -asmlinkage int sys_shmdt (char *shmaddr) +asmlinkage long sys_shmdt (char *shmaddr) { return -ENOSYS; } -asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) +asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) { return -ENOSYS; } -- cgit v1.2.3