summaryrefslogtreecommitdiffstats
path: root/ipc/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/util.c')
-rw-r--r--ipc/util.c83
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 */