diff options
Diffstat (limited to 'ipc/util.c')
-rw-r--r-- | ipc/util.c | 83 |
1 files changed, 57 insertions, 26 deletions
diff --git a/ipc/util.c b/ipc/util.c index a9b7a227b8d..08a647965b9 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -150,7 +150,7 @@ void free_ipc_ns(struct kref *kref) * ipc_init - initialise IPC subsystem * * The various system5 IPC resources (semaphores, messages and shared - * memory are initialised + * memory) are initialised */ static int __init ipc_init(void) @@ -205,10 +205,9 @@ void __ipc_init ipc_init_ids(struct ipc_ids* ids, int size) } #ifdef CONFIG_PROC_FS -static struct file_operations sysvipc_proc_fops; +static const struct file_operations sysvipc_proc_fops; /** - * ipc_init_proc_interface - Create a proc interface for sysipc types - * using a seq_file interface. + * ipc_init_proc_interface - Create a proc interface for sysipc types using a seq_file interface. * @path: Path in procfs * @header: Banner to be printed at the beginning of the file. * @ids: ipc id table to iterate. @@ -417,7 +416,7 @@ void* ipc_alloc(int size) * @ptr: pointer returned by ipc_alloc * @size: size of block * - * Free a block created with ipc_alloc. The caller must know the size + * Free a block created with ipc_alloc(). The caller must know the size * used in the allocation call. */ @@ -524,7 +523,7 @@ static void ipc_do_vfree(struct work_struct *work) * @head: RCU callback structure for queued work * * Since RCU callback function is called in bh, - * we need to defer the vfree to schedule_work + * we need to defer the vfree to schedule_work(). */ static void ipc_schedule_free(struct rcu_head *head) { @@ -541,7 +540,7 @@ static void ipc_schedule_free(struct rcu_head *head) * ipc_immediate_free - free ipc + rcu space * @head: RCU callback structure that contains pointer to be freed * - * Free from the RCU callback context + * Free from the RCU callback context. */ static void ipc_immediate_free(struct rcu_head *head) { @@ -603,8 +602,8 @@ int ipcperms (struct kern_ipc_perm *ipcp, short flag) * @in: kernel permissions * @out: new style IPC permissions * - * Turn the kernel object 'in' into a set of permissions descriptions - * for returning to userspace (out). + * Turn the kernel object @in into a set of permissions descriptions + * for returning to userspace (@out). */ @@ -624,8 +623,8 @@ void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out) * @in: new style IPC permissions * @out: old style IPC permissions * - * Turn the new style permissions object in into a compatibility - * object and store it into the 'out' pointer. + * Turn the new style permissions object @in into a compatibility + * object and store it into the @out pointer. */ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out) @@ -722,7 +721,7 @@ int ipc_checkid(struct ipc_ids* ids, struct kern_ipc_perm* ipcp, int uid) * @cmd: pointer to command * * Return IPC_64 for new style IPC and IPC_OLD for old style IPC. - * The cmd value is turned from an encoding command and version into + * The @cmd value is turned from an encoding command and version into * just the command code. */ @@ -739,14 +738,20 @@ int ipc_parse_version (int *cmd) #endif /* __ARCH_WANT_IPC_PARSE_VERSION */ #ifdef CONFIG_PROC_FS +struct ipc_proc_iter { + struct ipc_namespace *ns; + struct ipc_proc_iface *iface; +}; + static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos) { - struct ipc_proc_iface *iface = s->private; + struct ipc_proc_iter *iter = s->private; + struct ipc_proc_iface *iface = iter->iface; struct kern_ipc_perm *ipc = it; loff_t p; struct ipc_ids *ids; - ids = current->nsproxy->ipc_ns->ids[iface->ids]; + ids = iter->ns->ids[iface->ids]; /* If we had an ipc id locked before, unlock it */ if (ipc && ipc != SEQ_START_TOKEN) @@ -773,12 +778,13 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos) */ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos) { - struct ipc_proc_iface *iface = s->private; + struct ipc_proc_iter *iter = s->private; + struct ipc_proc_iface *iface = iter->iface; struct kern_ipc_perm *ipc; loff_t p; struct ipc_ids *ids; - ids = current->nsproxy->ipc_ns->ids[iface->ids]; + ids = iter->ns->ids[iface->ids]; /* * Take the lock - this will be released by the corresponding @@ -807,21 +813,23 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos) static void sysvipc_proc_stop(struct seq_file *s, void *it) { struct kern_ipc_perm *ipc = it; - struct ipc_proc_iface *iface = s->private; + struct ipc_proc_iter *iter = s->private; + struct ipc_proc_iface *iface = iter->iface; struct ipc_ids *ids; /* If we had a locked segment, release it */ if (ipc && ipc != SEQ_START_TOKEN) ipc_unlock(ipc); - ids = current->nsproxy->ipc_ns->ids[iface->ids]; + ids = iter->ns->ids[iface->ids]; /* Release the lock we took in start() */ mutex_unlock(&ids->mutex); } static int sysvipc_proc_show(struct seq_file *s, void *it) { - struct ipc_proc_iface *iface = s->private; + struct ipc_proc_iter *iter = s->private; + struct ipc_proc_iface *iface = iter->iface; if (it == SEQ_START_TOKEN) return seq_puts(s, iface->header); @@ -836,22 +844,45 @@ static struct seq_operations sysvipc_proc_seqops = { .show = sysvipc_proc_show, }; -static int sysvipc_proc_open(struct inode *inode, struct file *file) { +static int sysvipc_proc_open(struct inode *inode, struct file *file) +{ int ret; struct seq_file *seq; + struct ipc_proc_iter *iter; + + ret = -ENOMEM; + iter = kmalloc(sizeof(*iter), GFP_KERNEL); + if (!iter) + goto out; ret = seq_open(file, &sysvipc_proc_seqops); - if (!ret) { - seq = file->private_data; - seq->private = PDE(inode)->data; - } + if (ret) + goto out_kfree; + + seq = file->private_data; + seq->private = iter; + + iter->iface = PDE(inode)->data; + iter->ns = get_ipc_ns(current->nsproxy->ipc_ns); +out: return ret; +out_kfree: + kfree(iter); + goto out; +} + +static int sysvipc_proc_release(struct inode *inode, struct file *file) +{ + struct seq_file *seq = file->private_data; + struct ipc_proc_iter *iter = seq->private; + put_ipc_ns(iter->ns); + return seq_release_private(inode, file); } -static struct file_operations sysvipc_proc_fops = { +static const struct file_operations sysvipc_proc_fops = { .open = sysvipc_proc_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = sysvipc_proc_release, }; #endif /* CONFIG_PROC_FS */ |