summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-10-09 00:00:47 +0000
commitd6434e1042f3b0a6dfe1b1f615af369486f9b1fa (patch)
treee2be02f33984c48ec019c654051d27964e42c441 /ipc
parent609d1e803baf519487233b765eb487f9ec227a18 (diff)
Merge with 2.3.19.
Diffstat (limited to 'ipc')
-rw-r--r--ipc/msg.c40
-rw-r--r--ipc/sem.c6
-rw-r--r--ipc/shm.c128
-rw-r--r--ipc/util.c22
4 files changed, 113 insertions, 83 deletions
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 <dragos@iname.com>
+ * BIGMEM support, Andrea Arcangeli <andrea@suse.de>
*/
#include <linux/config.h>
@@ -15,7 +16,9 @@
#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/vmalloc.h>
+#include <linux/pagemap.h>
#include <linux/proc_fs.h>
+#include <linux/bigmem.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -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,20 +622,14 @@ 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);
return 0;
@@ -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;
}