summaryrefslogtreecommitdiff
path: root/ipc
diff options
context:
space:
mode:
authorDave Jones <davej@redhat.com>2006-12-13 01:41:41 +0300
committerDave Jones <davej@redhat.com>2006-12-13 01:41:41 +0300
commitc4366889dda8110247be59ca41fddb82951a8c26 (patch)
tree705c1a996bed8fd48ce94ff33ec9fd00f9b94875 /ipc
parentdb2fb9db5735cc532fd4fc55e94b9a3c3750378e (diff)
parente1036502e5263851259d147771226161e5ccc85a (diff)
downloadlinux-c4366889dda8110247be59ca41fddb82951a8c26.tar.xz
Merge ../linus
Conflicts: drivers/cpufreq/cpufreq.c
Diffstat (limited to 'ipc')
-rw-r--r--ipc/compat.c23
-rw-r--r--ipc/mqueue.c22
-rw-r--r--ipc/msg.c47
-rw-r--r--ipc/sem.c4
-rw-r--r--ipc/shm.c17
-rw-r--r--ipc/util.c9
-rw-r--r--ipc/util.h12
7 files changed, 83 insertions, 51 deletions
diff --git a/ipc/compat.c b/ipc/compat.c
index 4d20cfd38f0a..fa18141539fb 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -115,7 +115,6 @@ struct compat_shm_info {
extern int sem_ctls[];
#define sc_semopm (sem_ctls[2])
-#define MAXBUF (64*1024)
static inline int compat_ipc_parse_version(int *cmd)
{
@@ -307,35 +306,30 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
{
- struct msgbuf __user *p;
struct compat_msgbuf __user *up = uptr;
long type;
if (first < 0)
return -EINVAL;
- if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf)))
+ if (second < 0)
return -EINVAL;
- p = compat_alloc_user_space(second + sizeof(struct msgbuf));
- if (get_user(type, &up->mtype) ||
- put_user(type, &p->mtype) ||
- copy_in_user(p->mtext, up->mtext, second))
+ if (get_user(type, &up->mtype))
return -EFAULT;
- return sys_msgsnd(first, p, second, third);
+ return do_msgsnd(first, type, up->mtext, second, third);
}
long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
int version, void __user *uptr)
{
- struct msgbuf __user *p;
struct compat_msgbuf __user *up;
long type;
int err;
if (first < 0)
return -EINVAL;
- if (second < 0 || (second >= MAXBUF - sizeof(struct msgbuf)))
+ if (second < 0)
return -EINVAL;
if (!version) {
@@ -349,14 +343,11 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
uptr = compat_ptr(ipck.msgp);
msgtyp = ipck.msgtyp;
}
- p = compat_alloc_user_space(second + sizeof(struct msgbuf));
- err = sys_msgrcv(first, p, second, msgtyp, third);
+ up = uptr;
+ err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third);
if (err < 0)
goto out;
- up = uptr;
- if (get_user(type, &p->mtype) ||
- put_user(type, &up->mtype) ||
- copy_in_user(up->mtext, p->mtext, err))
+ if (put_user(type, &up->mtype))
err = -EFAULT;
out:
return err;
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 7c274002c9f5..02717f71d8d0 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -90,7 +90,7 @@ static struct super_operations mqueue_super_ops;
static void remove_notification(struct mqueue_inode_info *info);
static spinlock_t mq_lock;
-static kmem_cache_t *mqueue_inode_cachep;
+static struct kmem_cache *mqueue_inode_cachep;
static struct vfsmount *mqueue_mnt;
static unsigned int queues_count;
@@ -211,7 +211,7 @@ static int mqueue_get_sb(struct file_system_type *fs_type,
return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt);
}
-static void init_once(void *foo, kmem_cache_t * cachep, unsigned long flags)
+static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags)
{
struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
@@ -224,7 +224,7 @@ static struct inode *mqueue_alloc_inode(struct super_block *sb)
{
struct mqueue_inode_info *ei;
- ei = kmem_cache_alloc(mqueue_inode_cachep, SLAB_KERNEL);
+ ei = kmem_cache_alloc(mqueue_inode_cachep, GFP_KERNEL);
if (!ei)
return NULL;
return &ei->vfs_inode;
@@ -322,7 +322,7 @@ static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
size_t count, loff_t * off)
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
char buffer[FILENT_SIZE];
size_t slen;
loff_t o;
@@ -354,13 +354,13 @@ static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
return -EFAULT;
*off = o + count;
- filp->f_dentry->d_inode->i_atime = filp->f_dentry->d_inode->i_ctime = CURRENT_TIME;
+ filp->f_path.dentry->d_inode->i_atime = filp->f_path.dentry->d_inode->i_ctime = CURRENT_TIME;
return count;
}
static int mqueue_flush_file(struct file *filp, fl_owner_t id)
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
spin_lock(&info->lock);
if (task_tgid(current) == info->notify_owner)
@@ -372,7 +372,7 @@ static int mqueue_flush_file(struct file *filp, fl_owner_t id)
static unsigned int mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab)
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_path.dentry->d_inode);
int retval = 0;
poll_wait(filp, &info->wait_q, poll_tab);
@@ -836,7 +836,7 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
if (unlikely(!filp))
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@ -919,7 +919,7 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
if (unlikely(!filp))
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@ -1056,7 +1056,7 @@ retry:
if (!filp)
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@ -1126,7 +1126,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
if (!filp)
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_path.dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
diff --git a/ipc/msg.c b/ipc/msg.c
index 5b213d952545..a388824740e7 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -52,7 +52,7 @@ struct msg_receiver {
long r_msgtype;
long r_maxsize;
- volatile struct msg_msg *r_msg;
+ struct msg_msg *volatile r_msg;
};
/* one msg_sender for each sleeping sender */
@@ -124,6 +124,7 @@ void msg_exit_ns(struct ipc_namespace *ns)
}
mutex_unlock(&msg_ids(ns).mutex);
+ ipc_fini_ids(ns->ids[IPC_MSG_IDS]);
kfree(ns->ids[IPC_MSG_IDS]);
ns->ids[IPC_MSG_IDS] = NULL;
}
@@ -625,12 +626,11 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
return 0;
}
-asmlinkage long
-sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
+long do_msgsnd(int msqid, long mtype, void __user *mtext,
+ size_t msgsz, int msgflg)
{
struct msg_queue *msq;
struct msg_msg *msg;
- long mtype;
int err;
struct ipc_namespace *ns;
@@ -638,12 +638,10 @@ sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
if (msgsz > ns->msg_ctlmax || (long) msgsz < 0 || msqid < 0)
return -EINVAL;
- if (get_user(mtype, &msgp->mtype))
- return -EFAULT;
if (mtype < 1)
return -EINVAL;
- msg = load_msg(msgp->mtext, msgsz);
+ msg = load_msg(mtext, msgsz);
if (IS_ERR(msg))
return PTR_ERR(msg);
@@ -722,6 +720,16 @@ out_free:
return err;
}
+asmlinkage long
+sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg)
+{
+ long mtype;
+
+ if (get_user(mtype, &msgp->mtype))
+ return -EFAULT;
+ return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
+}
+
static inline int convert_mode(long *msgtyp, int msgflg)
{
/*
@@ -741,8 +749,8 @@ static inline int convert_mode(long *msgtyp, int msgflg)
return SEARCH_EQUAL;
}
-asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
- long msgtyp, int msgflg)
+long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
+ size_t msgsz, long msgtyp, int msgflg)
{
struct msg_queue *msq;
struct msg_msg *msg;
@@ -888,15 +896,30 @@ out_unlock:
return PTR_ERR(msg);
msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz;
- if (put_user (msg->m_type, &msgp->mtype) ||
- store_msg(msgp->mtext, msg, msgsz)) {
+ *pmtype = msg->m_type;
+ if (store_msg(mtext, msg, msgsz))
msgsz = -EFAULT;
- }
+
free_msg(msg);
return msgsz;
}
+asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz,
+ long msgtyp, int msgflg)
+{
+ long err, mtype;
+
+ err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
+ if (err < 0)
+ goto out;
+
+ if (put_user(mtype, &msgp->mtype))
+ err = -EFAULT;
+out:
+ return err;
+}
+
#ifdef CONFIG_PROC_FS
static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
{
diff --git a/ipc/sem.c b/ipc/sem.c
index 0dafcc455f92..d3e12efd55cb 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -161,6 +161,7 @@ void sem_exit_ns(struct ipc_namespace *ns)
}
mutex_unlock(&sem_ids(ns).mutex);
+ ipc_fini_ids(ns->ids[IPC_SEM_IDS]);
kfree(ns->ids[IPC_SEM_IDS]);
ns->ids[IPC_SEM_IDS] = NULL;
}
@@ -1069,14 +1070,13 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
ipc_rcu_getref(sma);
sem_unlock(sma);
- new = (struct sem_undo *) kmalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
+ new = kzalloc(sizeof(struct sem_undo) + sizeof(short)*nsems, GFP_KERNEL);
if (!new) {
ipc_lock_by_ptr(&sma->sem_perm);
ipc_rcu_putref(sma);
sem_unlock(sma);
return ERR_PTR(-ENOMEM);
}
- memset(new, 0, sizeof(struct sem_undo) + sizeof(short)*nsems);
new->semadj = (short *) &new[1];
new->semid = semid;
diff --git a/ipc/shm.c b/ipc/shm.c
index bfbd317ec11c..6d16bb6de7d2 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -116,6 +116,7 @@ void shm_exit_ns(struct ipc_namespace *ns)
}
mutex_unlock(&shm_ids(ns).mutex);
+ ipc_fini_ids(ns->ids[IPC_SHM_IDS]);
kfree(ns->ids[IPC_SHM_IDS]);
ns->ids[IPC_SHM_IDS] = NULL;
}
@@ -167,7 +168,7 @@ static inline void shm_inc(struct ipc_namespace *ns, int id)
static void shm_open(struct vm_area_struct *shmd)
{
shm_inc(shm_file_ns(shmd->vm_file),
- shmd->vm_file->f_dentry->d_inode->i_ino);
+ shmd->vm_file->f_path.dentry->d_inode->i_ino);
}
/*
@@ -186,7 +187,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
if (!is_file_hugepages(shp->shm_file))
shmem_lock(shp->shm_file, 0, shp->mlock_user);
else
- user_shm_unlock(shp->shm_file->f_dentry->d_inode->i_size,
+ user_shm_unlock(shp->shm_file->f_path.dentry->d_inode->i_size,
shp->mlock_user);
fput (shp->shm_file);
security_shm_free(shp);
@@ -202,7 +203,7 @@ static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp)
static void shm_close (struct vm_area_struct *shmd)
{
struct file * file = shmd->vm_file;
- int id = file->f_dentry->d_inode->i_ino;
+ int id = file->f_path.dentry->d_inode->i_ino;
struct shmid_kernel *shp;
struct ipc_namespace *ns;
@@ -232,7 +233,7 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma)
vma->vm_ops = &shm_vm_ops;
if (!(vma->vm_flags & VM_WRITE))
vma->vm_flags &= ~VM_MAYWRITE;
- shm_inc(shm_file_ns(file), file->f_dentry->d_inode->i_ino);
+ shm_inc(shm_file_ns(file), file->f_path.dentry->d_inode->i_ino);
}
return ret;
@@ -329,7 +330,7 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size)
shp->shm_nattch = 0;
shp->id = shm_buildid(ns, id, shp->shm_perm.seq);
shp->shm_file = file;
- file->f_dentry->d_inode->i_ino = shp->id;
+ file->f_path.dentry->d_inode->i_ino = shp->id;
shm_file_ns(file) = get_ipc_ns(ns);
@@ -494,7 +495,7 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
if(!shp)
continue;
- inode = shp->shm_file->f_dentry->d_inode;
+ inode = shp->shm_file->f_path.dentry->d_inode;
if (is_file_hugepages(shp->shm_file)) {
struct address_space *mapping = inode->i_mapping;
@@ -842,7 +843,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
}
file = shp->shm_file;
- size = i_size_read(file->f_dentry->d_inode);
+ size = i_size_read(file->f_path.dentry->d_inode);
shp->shm_nattch++;
shm_unlock(shp);
@@ -947,7 +948,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
(vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) {
- size = vma->vm_file->f_dentry->d_inode->i_size;
+ size = vma->vm_file->f_path.dentry->d_inode->i_size;
do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
/*
* We discovered the size of the shm segment, so
diff --git a/ipc/util.c b/ipc/util.c
index 42479e4eec59..a9b7a227b8d4 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -301,7 +301,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
*/
rcu_assign_pointer(ids->entries, new);
- ipc_rcu_putref(old);
+ __ipc_fini_ids(ids, old);
return newsize;
}
@@ -514,6 +514,11 @@ void ipc_rcu_getref(void *ptr)
container_of(ptr, struct ipc_rcu_hdr, data)->refcount++;
}
+static void ipc_do_vfree(struct work_struct *work)
+{
+ vfree(container_of(work, struct ipc_rcu_sched, work));
+}
+
/**
* ipc_schedule_free - free ipc + rcu space
* @head: RCU callback structure for queued work
@@ -528,7 +533,7 @@ static void ipc_schedule_free(struct rcu_head *head)
struct ipc_rcu_sched *sched =
container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]);
- INIT_WORK(&sched->work, vfree, sched);
+ INIT_WORK(&sched->work, ipc_do_vfree);
schedule_work(&sched->work);
}
diff --git a/ipc/util.h b/ipc/util.h
index c8fd6b9d77b5..e3aa2c5c97dc 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -83,6 +83,18 @@ void* ipc_rcu_alloc(int size);
void ipc_rcu_getref(void *ptr);
void ipc_rcu_putref(void *ptr);
+static inline void __ipc_fini_ids(struct ipc_ids *ids,
+ struct ipc_id_ary *entries)
+{
+ if (entries != &ids->nullentry)
+ ipc_rcu_putref(entries);
+}
+
+static inline void ipc_fini_ids(struct ipc_ids *ids)
+{
+ __ipc_fini_ids(ids, ids->entries);
+}
+
struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id);
struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id);
void ipc_lock_by_ptr(struct kern_ipc_perm *ipcp);