Home » Mailing lists » Devel » [RFC][PATCH 0/16] Enable cloning of pid namespace
[RFC][PATCH 08/16] Define/use pid->upid_list list. [message #18617 is a reply to message #18609] |
Thu, 24 May 2007 01:11   |
Sukadev Bhattiprolu
Messages: 413 Registered: August 2006
|
Senior Member |
|
|
Subject: Define/use pid->upid_list list.
From: Sukadev Bhattiprolu <sukadev@us.ibm.com>
With multiple pid namespaces, a process would be known by several pid_t
values, one in each pid namespace. To represent this, we introduce a
'struct upid' which associates a single pid_t value with a single pid
namespace.
We then replace the pid->nr field in 'struct pid' with a list of struct upid'
entries (referred to as the pid->upid_list list). This list represents the
multiple pid_t values of the process, one in each namespace.
The struct upid also replaces 'struct pid' in the pid_hash table to enable us
to find processes given a pid_t from any namespace (i.e we find 'struct upid'
for a given pid_t and from the 'struct upid', we find the 'struct pid' of the
process)
We finally reimplement find_pid() and pid_to_nr() to use pid->upid_list
and remove unused fields from 'struct pid'.
Changelog:
2.6.21-mm2-pidns3:
- 'struct upid' used to be called 'struct pid_nr' and a list of these
were hanging off of 'struct pid'. So, we renamed 'struct pid_nr'
and now hold them in a statically sized array in 'struct pid' since
the number of 'struct upid's for a process is known at process-
creation time.
2.6.21-rc3-mm2:
- [Eric Biederman] Combine all logical changes into one patch
- [Eric Biederman] Implement __pid_nr(pid_ns, pid) for use in procfs.
(now called pid_to_nr_in_ns()).
- [Serge Hallyn]: Remove (!pid_nr) check in free_pid_nr()
Signed-off-by: Cedric Le Goater <clg@fr.ibm.com>
Signed-off-by: Sukadev Bhattiprolu <sukadev@us.ibm.com>
---
fs/proc/array.c | 30 ++++--
fs/proc/base.c | 9 +-
include/linux/init_task.h | 13 ++
include/linux/pid.h | 35 +++++--
include/linux/pid_namespace.h | 12 ++
kernel/fork.c | 2
kernel/pid.c | 187 +++++++++++++++++++++++++++++++++++-------
7 files changed, 232 insertions(+), 56 deletions(-)
Index: lx26-21-mm2/include/linux/pid.h
===================================================================
--- lx26-21-mm2.orig/include/linux/pid.h 2007-05-22 17:06:48.000000000 -0700
+++ lx26-21-mm2/include/linux/pid.h 2007-05-22 17:06:54.000000000 -0700
@@ -16,6 +16,25 @@ enum pid_type
PIDTYPE_MAX
};
+struct pid_namespace;
+
+/*
+ * A struct upid holds a process identifier (or pid->nr) for a given
+ * pid namespace.
+ *
+ * A list of 'struct upid' entries is stored in the struct pid. This list
+ * is used to get the process identifier associated with the pid
+ * namespace it is being seen from.
+ */
+struct upid
+{
+ /* Try to keep pid_chain in the same cacheline as nr for find_pid */
+ struct hlist_node pid_chain; /* link hash collisions on pid_hash */
+ int nr; /* user space pid number */
+ struct pid_namespace *pid_ns; /* pid namespace in which nr is valid */
+ struct pid *pid; /* back to task's unique kernel pid */
+};
+
/*
* What is struct pid?
*
@@ -48,11 +67,10 @@ enum pid_type
struct pid
{
atomic_t count;
- /* Try to keep pid_chain in the same cacheline as nr for find_pid */
- int nr;
- struct hlist_node pid_chain;
/* lists of tasks that use this pid */
struct hlist_head tasks[PIDTYPE_MAX];
+ int num_upids;
+ struct upid *upid_list;
struct rcu_head rcu;
};
@@ -100,16 +118,11 @@ extern struct pid *FASTCALL(find_pid(int
extern struct pid *find_get_pid(int nr);
extern struct pid *find_ge_pid(int nr);
-extern struct pid *alloc_pid(enum copy_process_type);
+extern struct pid *dup_struct_pid(enum copy_process_type);
extern void FASTCALL(free_pid(struct pid *pid));
-static inline pid_t pid_to_nr(struct pid *pid)
-{
- pid_t nr = 0;
- if (pid)
- nr = pid->nr;
- return nr;
-}
+extern pid_t pid_to_nr_in_ns(struct pid_namespace *ns, struct pid *pid);
+extern pid_t pid_to_nr(struct pid *pid);
#define do_each_pid_task(pid, type, task) \
do { \
Index: lx26-21-mm2/include/linux/init_task.h
===================================================================
--- lx26-21-mm2.orig/include/linux/init_task.h 2007-05-22 17:06:48.000000000 -0700
+++ lx26-21-mm2/include/linux/init_task.h 2007-05-22 17:06:54.000000000 -0700
@@ -89,16 +89,23 @@ extern struct nsproxy init_nsproxy;
extern struct group_info init_groups;
-#define INIT_STRUCT_PID { \
- .count = ATOMIC_INIT(1), \
- .nr = 0, \
+#define INIT_STRUCT_UPID { \
+ .nr = 0, \
/* Don't put this struct pid in pid_hash */ \
.pid_chain = { .next = NULL, .pprev = NULL }, \
+ .pid_ns = &init_pid_ns, \
+ .pid = &init_struct_pid, \
+}
+
+#define INIT_STRUCT_PID { \
+ .count = ATOMIC_INIT(1), \
.tasks = { \
{ .first = &init_task.pids[PIDTYPE_PID].node }, \
{ .first = &init_task.pids[PIDTYPE_PGID].node }, \
{ .first = &init_task.pids[PIDTYPE_SID].node }, \
}, \
+ .num_upids = 1, \
+ .upid_list = &init_struct_upid, \
.rcu = RCU_HEAD_INIT, \
}
Index: lx26-21-mm2/kernel/pid.c
===================================================================
--- lx26-21-mm2.orig/kernel/pid.c 2007-05-22 17:06:48.000000000 -0700
+++ lx26-21-mm2/kernel/pid.c 2007-05-22 17:06:54.000000000 -0700
@@ -33,6 +33,7 @@
static struct hlist_head *pid_hash;
static int pidhash_shift;
static struct kmem_cache *pid_cachep;
+struct upid init_struct_upid = INIT_STRUCT_UPID;
struct pid init_struct_pid = INIT_STRUCT_PID;
int pid_max = PID_MAX_DEFAULT;
@@ -195,13 +196,104 @@ static int next_pidmap(struct pid_namesp
return -1;
}
+static void clear_upid(struct upid *upid)
+{
+ /* We can be called with write_lock_irq(&tasklist_lock) held */
+ unsigned long flags;
+
+ free_pidmap(upid->pid_ns, upid->nr);
+
+ spin_lock_irqsave(&pidmap_lock, flags);
+ hlist_del_rcu(&upid->pid_chain);
+ spin_unlock_irqrestore(&pidmap_lock, flags);
+
+ put_pid_ns(upid->pid_ns);
+}
+
+static int init_upid(struct upid *upid, struct pid *pid,
+ struct pid_namespace *pid_ns)
+{
+ int nr;
+
+ nr = alloc_pidmap(pid_ns);
+ if (nr < 0)
+ return nr;
+
+ upid->pid_ns = pid_ns;
+ get_pid_ns(pid_ns);
+ upid->nr = nr;
+
+ /*
+ * The struct pid and list of struct upid_list represent a process
+ * with multiple pid_t values, one in each pid namespace. The list
+ * of pid_t values of a process, represented by pid->upid_list list,
+ * never changes during the life of the process. As such, struct
+ * pid and its upid_list list maybe viewed as a single object i.e
+ * they are created/destroyed together. So we do not need a
+ * reference to struct pid here.
+ */
+ upid->pid = pid;
+
+ INIT_HLIST_NODE(&upid->pid_chain);
+ spin_lock_irq(&pidmap_lock);
+ hlist_add_head_rcu(&upid->pid_chain, &pid_hash[pid_hashfn(nr)]);
+ spin_unlock_irq(&pidmap_lock);
+
+ return 0;
+}
+
+/*
+ * Return the pid_t by which the process @pid is known in the pid
+ * namespace @ns.
+ *
+ * Return 0 if:
+ * - @pid is NULL (eg: procfs calls this for task_pgrp(init_task)
+ * which is NULL).
+ *
+ * - process does not have pid_t in the namespace @ns (eg: parent
+ * process of a child reaper does not exist in the child namespace.
+ * A getppid() call by the child reaper results in 0).
+ */
+pid_t pid_to_nr_in_ns(struct pid_namespace *ns, struct pid *pid)
+{
+ int i;
+ struct upid *upid;
+
+ if (!pid)
+ return 0;
+
+ upid = &pid->upid_list[0];
+ for (i = 0; i < pid->num_upids; i++, upid++) {
+ if (upid->pid_ns == ns)
+ return upid->nr;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pid_to_nr_in_ns);
+
+/*
+ * Return the pid_t by which the process @pid is known in the active
+ * pid namespace of the caller.
+ *
+ * pid_to_nr() cannot be static inline if task_active_pid_ns() is
+ * inline as it would cause a circular dependency between pid.h
+ * and pid_namespace.h.
+ */
+pid_t pid_to_nr(struct pid *pid)
+{
+ return pid_to_nr_in_ns(task_active_pid_ns(current), pid);
+}
+EXPORT_SYMBOL_GPL(pid_to_nr);
+
fastcall void put_pid(struct pid *pid)
{
if (!pid)
return;
+
if ((atomic_read(&pid->count) == 1) ||
- atomic_dec_and_test(&pid->count))
+ atomic_dec_and_test(&pid->count)) {
kmem_cache_free(pid_cachep, pid);
+ }
}
EXPORT_SYMBOL_GPL(put_pid);
@@ -213,66 +305,95 @@ static void delayed_put_pid(struct rcu_h
fastcall void free_pid(struct pid *pid)
{
- /* We can be called with write_lock_irq(&tasklist_lock) held */
- unsigned long flags;
+ int i;
+ struct upid *upid = &pid->upid_list[0];
/* check this here to keep copy_process() cleaner */
if (unlikely(pid == &init_struct_pid))
return;
- spin_lock_irqsave(&pidmap_lock, flags);
- hlist_del_rcu(&pid->pid_chain);
- spin_unlock_irqrestore(&pidmap_lock, flags);
+ /* clear any upids that we actually initialized */
+ for (i = 0; i < pid->num_upids; i++, upid++) {
+ if (upid->pid_ns)
+ clear_upid(upid);
+ else
+ break;
+ }
- free_pidmap(&init_pid_ns, pid->nr);
call_rcu(&pid->rcu, delayed_put_pid);
}
-struct pid *alloc_pid(enum copy_process_type copy_src)
+static struct pid *alloc_struct_pid(int num_upids)
{
struct pid *pid;
enum pid_type type;
- int nr = -1;
-
- /* check this here to keep copy_process() cleaner */
- if (unlikely(copy_src == COPY_IDLE_PROCESS))
- return &init_struct_pid;
+ struct upid *upid_list;
+ void *pid_end;
+ /* for now we only support one pid namespace */
+ BUG_ON(num_upids != 1);
pid = kmem_cache_alloc(pid_cachep, GFP_KERNEL);
if (!pid)
- goto out;
+ return NULL;
- nr = alloc_pidmap(task_active_pid_ns(current));
- if (nr < 0)
- goto out_free;
+ pid_end = (void *)pid + sizeof(struct pid);
+ pid->upid_list = (struct upid *)pid_end;
atomic_set(&pid->count, 1);
- pid->nr = nr;
+ pid->num_upids = num_upids;
+
for (type = 0; type < PIDTYPE_MAX; ++type)
INIT_HLIST_HEAD(&pid->tasks[type]);
- spin_lock_irq(&am
...
|
|
|
 |
|
[RFC][PATCH 0/16] Enable cloning of pid namespace
|
 |
|
[RFC][PATCH 01/16] Define/use task_active_pid_ns() wrapper
|
 |
|
[RFC][PATCH 02/16] Rename pid_nr function
|
 |
|
[RFC][PATCH 03/16] Rename child_reaper function
|
 |
|
[RFC][PATCH 04/16] Use pid_to_nr() in process info functions
|
 |
|
Re: [RFC][PATCH 04/16] Use pid_to_nr() in process info functions
By: xemul on Thu, 24 May 2007 08:22
|
 |
|
Re: [RFC][PATCH 04/16] Use pid_to_nr() in process info functions
|
 |
|
[RFC][PATCH 05/16] Use task_pid() to find leader's pid
|
 |
|
[RFC][PATCH 06/16] Define is_global_init()
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
By: xemul on Thu, 24 May 2007 09:24
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
By: serue on Thu, 24 May 2007 15:27
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
By: xemul on Thu, 24 May 2007 08:28
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
By: xemul on Thu, 24 May 2007 08:29
|
 |
|
Re: [RFC][PATCH 06/16] Define is_global_init()
|
 |
|
[RFC][PATCH 07/16] Move alloc_pid call to copy_process
|
 |
|
Re: [RFC][PATCH 07/16] Move alloc_pid call to copy_process
|
 |
|
Re: [RFC][PATCH 07/16] Move alloc_pid call to copy_process
By: xemul on Thu, 24 May 2007 09:30
|
 |
|
Re: [RFC][PATCH 07/16] Move alloc_pid call to copy_process
|
 |
|
Re: [RFC][PATCH 07/16] Move alloc_pid call to copy_process
By: xemul on Thu, 24 May 2007 08:35
|
 |
|
Re: [RFC][PATCH 07/16] Move alloc_pid call to copy_process
|
 |
|
Re: [RFC][PATCH 07/16] Move alloc_pid call to copy_process
|
 |
|
[RFC][PATCH 08/16] Define/use pid->upid_list list.
|
 |
|
Re: [RFC][PATCH 08/16] Define/use pid->upid_list list.
|
 |
|
Re: [RFC][PATCH 08/16] Define/use pid->upid_list list.
By: xemul on Thu, 24 May 2007 08:57
|
 |
|
[RFC][PATCH 09/16] Use pid ns from pid->upid_list
|
 |
|
[RFC][PATCH 10/16] Define CLONE_NEWPID flag
|
 |
|
[RFC][PATCH 11/16] Enable cloning pid namespace
|
 |
|
Re: [RFC][PATCH 11/16] Enable cloning pid namespace
By: serue on Thu, 24 May 2007 14:59
|
 |
|
[RFC][PATCH 12/16] Terminate processes in a ns when reaper is exiting.
|
 |
|
[RFC][PATCH 13/16] Remove proc_mnt's use for killing inodes
|
 |
|
[RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
|
 |
|
Re: [RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
|
 |
|
Re: [RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
|
 |
|
Re: [RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
By: xemul on Thu, 24 May 2007 09:23
|
 |
|
Re: [RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
By: xemul on Thu, 24 May 2007 10:15
|
 |
|
Re: [RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
|
 |
|
Re: [RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
|
 |
|
Re: [RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
|
 |
|
Re: [RFC][PATCH 14/16] Introduce proc_mnt for pid_ns
|
 |
|
[RFC][PATCH 15/16] Enable signaling child reaper from parent ns.
|
 |
|
Re: [RFC][PATCH 15/16] Enable signaling child reaper from parent ns.
By: serue on Thu, 24 May 2007 15:59
|
 |
|
Re: [RFC][PATCH 15/16] Enable signaling child reaper from parent ns.
|
 |
|
Re: [RFC][PATCH 15/16] Enable signaling child reaper from parent ns.
By: serue on Fri, 25 May 2007 20:13
|
 |
|
Re: [RFC][PATCH 15/16] Enable signaling child reaper from parent ns.
|
 |
|
Re: [RFC][PATCH 15/16] Enable signaling child reaper from parent ns.
|
 |
|
[RFC][PATCH 16/16] Move inline functions to sched.h
|
 |
|
Re: [RFC][PATCH 0/16] Enable cloning of pid namespace
|
 |
|
Re: [RFC][PATCH 0/16] Enable cloning of pid namespace
By: xemul on Thu, 24 May 2007 09:31
|
 |
|
Re: [RFC][PATCH 0/16] Enable cloning of pid namespace
|
 |
|
Re: [RFC][PATCH 0/16] Enable cloning of pid namespace
|
 |
|
Re: [RFC][PATCH 0/16] Enable cloning of pid namespace
|
Goto Forum:
Current Time: Sun Sep 07 01:37:44 GMT 2025
Total time taken to generate the page: 0.11219 seconds
|