All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kirill Korotaev <dev@openvz.org>
To: Kirill Korotaev <dev@openvz.org>
Cc: serue@us.ibm.com, arjan@infradead.org, frankeh@watson.ibm.com,
	clg@fr.ibm.com, haveblue@us.ibm.com, mrmacman_g4@mac.com,
	alan@lxorguk.ukuu.org.uk,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>,
	devel@openvz.org
Subject: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
Date: Thu, 02 Feb 2006 19:30:16 +0300	[thread overview]
Message-ID: <43E23398.7090608@openvz.org> (raw)
In-Reply-To: <43E22B2D.1040607@openvz.org>

[-- Attachment #1: Type: text/plain, Size: 1356 bytes --]

This is the main patch which contains all vpid-to-pid conversions
and auxilliary stuff. Virtual pids are distinguished from real ones
by the VPID_BIT bit set. Conversion from vpid to pid and vice versa
is performed in two ways: fast way, when vpid and it's according pid
differ only in VPID_BIT bit set ("linear" case), and more complex way,
when pid may correspond to any vpid ("sparse" case) - in this case we
use a hash-table based mapping.

Note that this patch implies that we have a public vps_info_t pointer
type to represent VPS (otherwise it is useless) so that it can be used
in any virtualisation solution. Virtualization solution should have the 
following "interface":
1. vps_info_t has member int id;
2. vps_info_t has member struct task_struct *init_task;
3. the following macros/functions are defined:
a. inside_vps() - returns true if current task is now
inside VPS;
b. task_inside_vps(task_t *) - returns true if task
belongs to VPS;
c. current_vps() - returns vps_info_t for current VPS;
d. task_vps(task_t *) - returns vps_info_t that task
belongs to;
e. set_sparce_vpid(vps_info_t) - switches VPS into state
when "sparce" conversion is used;
f. sparse_vpid(vps_info_t) - returns true if vps is in
"sparce" state and false if it is in "linear";
g. get_vps_tasks_num(vps_info_t) - returns the number of
tasks that belong to VPS.

Kirill

[-- Attachment #2: diff-vpids-virt --]
[-- Type: text/plain, Size: 15004 bytes --]

--- ./include/linux/pid.h.vpid_virt	2006-02-02 14:32:41.162807472 +0300
+++ ./include/linux/pid.h	2006-02-02 14:33:17.963212960 +0300
@@ -10,11 +10,17 @@ enum pid_type
 	PIDTYPE_MAX
 };
 
+#define VPID_BIT	10
+#define VPID_DIV	(1 << VPID_BIT)
+
 struct pid
 {
 	/* Try to keep pid_chain in the same cacheline as nr for find_pid */
 	int nr;
 	struct hlist_node pid_chain;
+#ifdef CONFIG_VIRTUAL_PIDS
+	int vnr;
+#endif
 	/* list of pids with the same nr, only one of them is in the hash */
 	struct list_head pid_list;
 };
@@ -30,6 +36,52 @@ struct pid
 #define comb_pid_to_vpid(pid)		(pid)
 #define alloc_vpid(pid, vpid)		(pid)
 #define free_vpid(vpid)			do { } while (0)
+#else /* CONFIG_VIRTUAL_PIDS */
+#define __is_virtual_pid(pid)		((pid) & VPID_DIV)
+#define is_virtual_pid(pid)		(__is_virtual_pid(pid) || \
+		(((pid) == 1) && inside_vps()))
+
+extern int vpid_to_pid(int pid);
+extern int __vpid_to_pid(int pid);
+extern pid_t pid_type_to_vpid(int type, pid_t pid);
+extern pid_t __pid_type_to_vpid(int type, pid_t pid);
+
+static inline int comb_vpid_to_pid(int vpid)
+{
+	int pid = vpid;
+
+	if (vpid > 0) {
+		pid = vpid_to_pid(vpid);
+		if (unlikely(pid < 0))
+			return 0;
+	} else if (vpid < 0) {
+		pid = vpid_to_pid(-vpid);
+		if (unlikely(pid < 0))
+			return 0;
+		pid = -pid;
+	}
+	return pid;
+}
+
+static inline int comb_pid_to_vpid(int pid)
+{
+	int vpid = pid;
+
+	if (pid > 0) {
+		vpid = pid_type_to_vpid(PIDTYPE_PID, pid);
+		if (unlikely(vpid < 0))
+			return 0;
+	} else if (pid < 0) {
+		vpid = pid_type_to_vpid(PIDTYPE_PGID, -pid);
+		if (unlikely(vpid < 0))
+			return 0;
+		vpid = -vpid;
+	}
+	return vpid;
+}
+
+extern int alloc_vpid(int pid, int vpid);
+extern void free_vpid(int vpid);
 #endif
 
 #define pid_task(elem, type) \
--- ./include/linux/sched.h.vpid_virt	2006-02-02 14:32:41.164807168 +0300
+++ ./include/linux/sched.h	2006-02-02 14:58:53.129832160 +0300
@@ -1327,6 +1327,80 @@ static inline pid_t get_task_ppid(struct
 		return 0;
 	return (p->pid > 1 ? p->group_leader->real_parent->tgid : 0);
 }
+#else
+static inline pid_t virt_pid(struct task_struct *tsk)
+{
+	return tsk->pids[PIDTYPE_PID].vnr;
+}
+
+static inline pid_t virt_tgid(struct task_struct *tsk)
+{
+	return tsk->pids[PIDTYPE_TGID].vnr;
+}
+
+static inline pid_t virt_pgid(struct task_struct *tsk)
+{
+	return tsk->pids[PIDTYPE_PGID].vnr;
+}
+
+static inline pid_t virt_sid(struct task_struct *tsk)
+{
+	return tsk->pids[PIDTYPE_SID].vnr;
+}
+
+static inline pid_t get_task_pid_ve(struct task_struct *tsk,
+		struct task_struct *ve_tsk)
+{
+	return task_inside_vps(ve_tsk) ? virt_pid(tsk) : tsk->pid;
+}
+
+static inline pid_t get_task_pid(struct task_struct *tsk)
+{
+	return inside_vps() ? virt_pid(tsk) : tsk->pid;
+}
+
+static inline pid_t get_task_tgid(struct task_struct *tsk)
+{
+	return inside_vps() ? virt_tgid(tsk) : tsk->pid;
+}
+
+static inline pid_t get_task_pgid(struct task_struct *tsk)
+{
+	return inside_vps() ? virt_pgid(tsk) : tsk->signal->pgrp;
+}
+
+static inline pid_t get_task_sid(struct task_struct *tsk)
+{
+	return inside_vps() ? virt_sid(tsk) : tsk->signal->session;
+}
+
+static inline int set_virt_pid(struct task_struct *tsk, pid_t pid)
+{
+	tsk->pids[PIDTYPE_PID].vnr = pid;
+	return pid;
+}
+
+static inline void set_virt_tgid(struct task_struct *tsk, pid_t pid)
+{
+	tsk->pids[PIDTYPE_TGID].vnr = pid;
+}
+
+static inline void set_virt_pgid(struct task_struct *tsk, pid_t pid)
+{
+	tsk->pids[PIDTYPE_PGID].vnr = pid;
+}
+
+static inline void set_virt_sid(struct task_struct *tsk, pid_t pid)
+{
+	tsk->pids[PIDTYPE_SID].vnr = pid;
+}
+
+static inline pid_t get_task_ppid(struct task_struct *p)
+{
+	if (!pid_alive(p))
+		return 0;
+	return (get_task_pid(p) > 1) ? get_task_pid(p->real_parent) : 0;
+}
 #endif
 
 /* set thread flags in other task's structures
--- ./kernel/pid.c.vpid_virt	2006-02-02 14:15:35.165782728 +0300
+++ ./kernel/pid.c	2006-02-02 14:58:34.632644160 +0300
@@ -27,6 +27,14 @@
 #include <linux/bootmem.h>
 #include <linux/hash.h>
 
+#ifdef CONFIG_VIRTUAL_PIDS
+static void __free_vpid(int vpid, struct task_struct *ve_tsk);
+#define PIDMAP_NRFREE	(BITS_PER_PAGE / 2)
+#else
+#define __free_vpid(vpid, tsk)	do { } while (0)
+#define PIDMAP_NRFREE	BITS_PER_PAGE
+#endif
+
 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
 static struct hlist_head *pid_hash[PIDTYPE_MAX];
 static int pidhash_shift;
@@ -58,7 +66,7 @@ typedef struct pidmap {
 } pidmap_t;
 
 static pidmap_t pidmap_array[PIDMAP_ENTRIES] =
-	 { [ 0 ... PIDMAP_ENTRIES-1 ] = { ATOMIC_INIT(BITS_PER_PAGE), NULL } };
+	 { [ 0 ... PIDMAP_ENTRIES-1 ] = { ATOMIC_INIT(PIDMAP_NRFREE), NULL } };
 
 static  __cacheline_aligned_in_smp DEFINE_SPINLOCK(pidmap_lock);
 
@@ -67,6 +75,7 @@ fastcall void free_pidmap(int pid)
 	pidmap_t *map = pidmap_array + pid / BITS_PER_PAGE;
 	int offset = pid & BITS_PER_PAGE_MASK;
 
+	BUG_ON(__is_virtual_pid(pid) || pid == 1);
 	clear_bit(offset, map->page);
 	atomic_inc(&map->nr_free);
 }
@@ -77,6 +86,8 @@ int alloc_pidmap(void)
 	pidmap_t *map;
 
 	pid = last + 1;
+	if (__is_virtual_pid(pid))
+		pid += VPID_DIV;
 	if (pid >= pid_max)
 		pid = RESERVED_PIDS;
 	offset = pid & BITS_PER_PAGE_MASK;
@@ -107,6 +118,8 @@ int alloc_pidmap(void)
 				}
 				offset = find_next_offset(map, offset);
 				pid = mk_pid(map, offset);
+				if (__is_virtual_pid(pid))
+					pid += VPID_DIV;
 			/*
 			 * find_next_offset() found a bit, the pid from it
 			 * is in-bounds, and if we fell back to the last
@@ -127,6 +140,8 @@ int alloc_pidmap(void)
 				break;
 		}
 		pid = mk_pid(map, offset);
+		if (__is_virtual_pid(pid))
+			pid += VPID_DIV;
 	}
 	return -1;
 }
@@ -201,6 +216,7 @@ void fastcall detach_pid(task_t *task, e
 		if (tmp != type && find_pid(tmp, nr))
 			return;
 
+	__free_vpid(task->pids[type].vnr, task);
 	free_pidmap(nr);
 }
 
@@ -234,6 +250,9 @@ void switch_exec_pids(task_t *leader, ta
 
 	leader->pid = leader->tgid = thread->pid;
 	thread->pid = thread->tgid;
+	set_virt_tgid(leader, virt_pid(thread));
+	set_virt_pid(leader, virt_pid(thread));
+	set_virt_pid(thread, virt_tgid(thread));
 
 	attach_pid(thread, PIDTYPE_PID, thread->pid);
 	attach_pid(thread, PIDTYPE_TGID, thread->tgid);
@@ -247,6 +266,344 @@ void switch_exec_pids(task_t *leader, ta
 	attach_pid(leader, PIDTYPE_SID, leader->signal->session);
 }
 
+#ifdef CONFIG_VIRTUAL_PIDS
+/* Virtual PID bits.
+ *
+ * At the moment all internal structures in kernel store real global pid.
+ * The only place, where virtual PID is used, is at user frontend. We
+ * remap virtual pids obtained from user to global ones (vpid_to_pid) and
+ * map globals to virtuals before showing them to user (virt_pid_type).
+ *
+ * We hold virtual PIDs inside struct pid, so map global -> virtual is easy.
+ */
+
+pid_t __pid_type_to_vpid(int type, pid_t pid)
+{
+	struct pid * p;
+
+	if (unlikely(is_virtual_pid(pid)))
+		return -1;
+
+	read_lock(&tasklist_lock);
+	p = find_pid(type, pid);
+	if (p) {
+		pid = p->vnr;
+	} else {
+		pid = -1;
+	}
+	read_unlock(&tasklist_lock);
+	return pid;
+}
+
+pid_t pid_type_to_vpid(int type, pid_t pid)
+{
+	int vpid;
+
+	if (unlikely(pid <= 0))
+		return pid;
+
+	BUG_ON(is_virtual_pid(pid));
+
+	if (!inside_vps())
+		return pid;
+
+	vpid = __pid_type_to_vpid(type, pid);
+	if (unlikely(vpid == -1)) {
+		/* It is allowed: global pid can be used everywhere.
+		 * This can happen, when kernel remembers stray pids:
+		 * signal queues, locks etc.
+		 */
+		vpid = pid;
+	}
+	return vpid;
+}
+
+/* To map virtual pids to global we maintain special hash table.
+ *
+ * Mapping entries are allocated when a process with non-trivial
+ * mapping is forked, which is possible only after VE migrated.
+ * Mappings are destroyed, when a global pid is removed from global
+ * pidmap, which means we do not need to refcount mappings.
+ */
+
+static struct hlist_head *vpid_hash;
+
+struct vpid_mapping
+{
+	int     pid;
+	int     vpid;
+	int     vpsid;
+	struct hlist_node link;
+};
+
+static kmem_cache_t *vpid_mapping_cachep;
+
+static inline int vpid_hashfn(int vnr, int vpsid)
+{
+	return hash_long((unsigned long)(vnr + (vpsid << 16)), pidhash_shift);
+}
+
+struct vpid_mapping *__lookup_vpid_mapping(int vnr, int vpsid)
+{
+	struct hlist_node *elem;
+	struct vpid_mapping *map;
+
+	hlist_for_each_entry(map, elem,
+			&vpid_hash[vpid_hashfn(vnr, vpsid)], link) {
+		if (map->vpid == vnr && map->vpsid == vpsid)
+			return map;
+	}
+	return NULL;
+}
+
+/* __vpid_to_pid() is raw version of vpid_to_pid(). It is to be used
+ * only under tasklist_lock. In some places we must use only this version
+ * (f.e. __kill_pg_info is called under write lock!)
+ *
+ * Caller should pass virtual pid. This function returns an error, when
+ * seeing a global pid.
+ */
+int __vpid_to_pid(int pid)
+{
+	struct vpid_mapping *map;
+	vps_info_t vps;
+
+	if (unlikely(!is_virtual_pid(pid) || !inside_vps()))
+		return -1;
+
+	vps = current_vps();
+	if (!sparse_vpid(vps)) {
+		if (pid != 1)
+			return pid - VPID_DIV;
+		return vps->init_task->pid;
+	}
+
+	map = __lookup_vpid_mapping(pid, vps->id);
+	if (map)
+		return map->pid;
+	return -1;
+}
+
+int vpid_to_pid(int pid)
+{
+	/* User gave bad pid. It is his problem. */
+	if (unlikely(pid <= 0))
+		return pid;
+
+	if (!is_virtual_pid(pid))
+		return pid;
+
+	read_lock(&tasklist_lock);
+	pid = __vpid_to_pid(pid);
+	read_unlock(&tasklist_lock);
+	return pid;
+}
+
+/*
+ * In simple case we have trivial vpid-to-pid conversion rule:
+ * vpid == 1 -> vps->init_task->pid
+ * else         pid & ~VPID_DIV
+ *
+ * when things get more complex we need to allocate mappings...
+ */
+
+static int add_mapping(int pid, int vpid, int vpsid, struct hlist_head *cache)
+{
+	if (pid > 0 && vpid > 0 && !__lookup_vpid_mapping(vpid, vpsid)) {
+		struct vpid_mapping *m;
+
+		if (hlist_empty(cache)) {
+			m = kmem_cache_alloc(vpid_mapping_cachep, GFP_ATOMIC);
+			if (unlikely(m == NULL))
+				return -ENOMEM;
+		} else {
+			m = hlist_entry(cache->first, struct vpid_mapping,
+					link);
+			hlist_del(&m->link);
+		}
+		m->pid = pid;
+		m->vpid = vpid;
+		m->vpsid = vpsid;
+		hlist_add_head(&m->link,
+				&vpid_hash[vpid_hashfn(vpid, vpsid)]);
+	}
+	return 0;
+}
+
+static int switch_to_sparse_mapping(int pid, vps_info_t vps)
+{
+	struct hlist_head cache;
+	task_t *g, *t;
+	int pcount;
+	int err;
+
+	/* Transition happens under write_lock_irq, so we try to make
+	 * it more reliable and fast preallocating mapping entries.
+	 * pcounter may be not enough, we could have lots of orphaned
+	 * process groups and sessions, which also require mappings.
+	 */
+	INIT_HLIST_HEAD(&cache);
+	pcount = get_vps_tasks_num(vps);
+	err = -ENOMEM;
+	while (pcount > 0) {
+		struct vpid_mapping *m;
+		m = kmem_cache_alloc(vpid_mapping_cachep, GFP_KERNEL);
+		if (!m)
+			goto out;
+		hlist_add_head(&m->link, &cache);
+		pcount--;
+	}
+
+	write_lock_irq(&tasklist_lock);
+	err = 0;
+	if (sparse_vpid(vps))
+		goto out_sparse;
+
+	err = -ENOMEM;
+	do_each_thread(g, t) {
+		if (t->pid == pid)
+			continue;
+		if (add_mapping(t->pid, virt_pid(t), vps->id, &cache))
+			goto out_unlock;
+	} while_each_thread(g, t);
+
+	for_each_process(t) {
+		if (t->pid == pid)
+			continue;
+
+		if (add_mapping(t->tgid, virt_tgid(t), vps->id,
+					&cache))
+			goto out_unlock;
+		if (add_mapping(t->signal->pgrp, virt_pgid(t), vps->id,
+					&cache))
+			goto out_unlock;
+		if (add_mapping(t->signal->session, virt_sid(t), vps->id,
+					&cache))
+			goto out_unlock;
+	}
+	set_sparse_vpid(vps);
+	err = 0;
+
+out_unlock:
+	if (err) {
+		int i;
+
+		for (i=0; i<(1<<pidhash_shift); i++) {
+			struct hlist_node *elem, *next;
+			struct vpid_mapping *map;
+
+			hlist_for_each_entry_safe(map, elem, next, &vpid_hash[i], link) {
+				if (map->vpsid == vps->id) {
+					hlist_del(elem);
+					hlist_add_head(elem, &cache);
+				}
+			}
+		}
+	}
+out_sparse:
+	write_unlock_irq(&tasklist_lock);
+
+out:
+	while (!hlist_empty(&cache)) {
+		struct vpid_mapping *m;
+		m = hlist_entry(cache.first, struct vpid_mapping, link);
+		hlist_del(&m->link);
+		kmem_cache_free(vpid_mapping_cachep, m);
+	}
+	return err;
+}
+
+int alloc_vpid(int pid, int virt_pid)
+{
+	int result;
+	struct vpid_mapping *m;
+	vps_info_t vps;
+
+	if (!inside_vps())
+		return pid;
+
+	vps = current_vps();
+	if (!sparse_vpid(vps)) {
+		if (virt_pid == -1)
+			return pid + VPID_DIV;
+
+		if (virt_pid == 1 || virt_pid == pid + VPID_DIV)
+			return virt_pid;
+
+		if ((result = switch_to_sparse_mapping(pid, vps)) < 0)
+			return result;
+	}
+
+	m = kmem_cache_alloc(vpid_mapping_cachep, GFP_KERNEL);
+	if (!m)
+		return -ENOMEM;
+
+	m->pid = pid;
+	m->vpsid = vps->id;
+
+	result = (virt_pid == -1) ? pid + VPID_DIV : virt_pid;
+
+	write_lock_irq(&tasklist_lock);
+	if (unlikely(__lookup_vpid_mapping(result, m->vpsid))) {
+		if (virt_pid > 0) {
+			result = -EEXIST;
+			goto out;
+		}
+
+		/* No luck. Now we search for some not-existing vpid.
+		 * It is weak place. We do linear search. */
+		do {
+			result++;
+			if (!__is_virtual_pid(result))
+				result += VPID_DIV;
+			if (result >= pid_max)
+				result = RESERVED_PIDS + VPID_DIV;
+		} while (__lookup_vpid_mapping(result, m->vpsid) != NULL);
+
+		/* And set last_pid in hope future alloc_pidmap to avoid
+		 * collisions after future alloc_pidmap() */
+		last_pid = result - VPID_DIV;
+	}
+	if (result > 0) {
+		m->vpid = result;
+		hlist_add_head(&m->link,
+				&vpid_hash[vpid_hashfn(result, m->vpsid)]);
+	}
+out:
+	write_unlock_irq(&tasklist_lock);
+	if (result < 0)
+		kmem_cache_free(vpid_mapping_cachep, m);
+	return result;
+}
+
+static void __free_vpid(int vpid, struct task_struct *ve_tsk)
+{
+	struct vpid_mapping *m;
+	vps_info_t vps;
+
+	if (!__is_virtual_pid(vpid) && (vpid != 1 || !task_inside_vps(ve_tsk)))
+		return;
+
+	vps = task_vps(ve_tsk);
+	if (!sparse_vpid(vps))
+		return;
+
+	m = __lookup_vpid_mapping(vpid, vps->id);
+	BUG_ON(m == NULL);
+	hlist_del(&m->link);
+	kmem_cache_free(vpid_mapping_cachep, m);
+}
+EXPORT_SYMBOL(alloc_vpid);
+
+void free_vpid(int vpid)
+{
+	write_lock_irq(&tasklist_lock);
+	__free_vpid(vpid, current);
+	write_unlock_irq(&tasklist_lock);
+}
+
+#endif
+
 /*
  * The pid hash table is scaled according to the amount of memory in the
  * machine.  From a minimum of 16 slots up to 4096 slots at one gigabyte or
@@ -273,6 +630,14 @@ void __init pidhash_init(void)
 		for (j = 0; j < pidhash_size; j++)
 			INIT_HLIST_HEAD(&pid_hash[i][j]);
 	}
+
+#ifdef CONFIG_VIRTUAL_PIDS
+	vpid_hash = alloc_bootmem(pidhash_size * sizeof(struct hlist_head));
+	if (!vpid_hash)
+		panic("Could not alloc vpid_hash!\n");
+	for (j = 0; j < pidhash_size; j++)
+		INIT_HLIST_HEAD(&vpid_hash[j]);
+#endif
 }
 
 void __init pidmap_init(void)
@@ -289,4 +654,12 @@ void __init pidmap_init(void)
 
 	for (i = 0; i < PIDTYPE_MAX; i++)
 		attach_pid(current, i, 0);
+
+#ifdef CONFIG_VIRTUAL_PIDS
+	vpid_mapping_cachep =
+		kmem_cache_create("vpid_mapping",
+				sizeof(struct vpid_mapping),
+				__alignof__(struct vpid_mapping),
+				SLAB_PANIC, NULL, NULL);
+#endif
 }

  parent reply	other threads:[~2006-02-02 16:28 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-02-02 15:54 [RFC][PATCH] VPIDs: Virtualization of PIDs (OpenVZ approach) Kirill Korotaev
2006-02-02 16:16 ` [RFC][PATCH 1/7] VPIDs: add VPID config option Kirill Korotaev
2006-02-02 16:21 ` [RFC][PATCH 2/7] VPIDs: pid/vpid conversions Kirill Korotaev
2006-02-08 20:29   ` Eric W. Biederman
2006-02-08 23:53     ` Alexey Kuznetsov
2006-02-09  0:37       ` Eric W. Biederman
2006-02-09  1:11         ` Alexey Kuznetsov
2006-02-09  1:36           ` Eric W. Biederman
2006-02-09  2:51           ` Serge E. Hallyn
2006-02-09  9:55             ` Alexey Kuznetsov
2006-02-09 19:22               ` Eric W. Biederman
2006-02-20 14:57     ` Kirill Korotaev
2006-02-20 16:56       ` Herbert Poetzl
2006-02-21 16:19         ` Kirill Korotaev
2006-02-21 23:17           ` Herbert Poetzl
2006-02-02 16:24 ` [RFC][PATCH 3/7] VPIDs: fork modifications Kirill Korotaev
2006-02-02 20:08   ` Cedric Le Goater
2006-02-02 16:26 ` [RFC][PATCH 4/7] VPIDs: vpid macros in non-VPID case Kirill Korotaev
2006-02-02 16:30 ` Kirill Korotaev [this message]
2006-02-02 17:05   ` [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case Dave Hansen
2006-02-02 19:29     ` Serge E. Hallyn
2006-02-03 10:52     ` Alexey Kuznetsov
2006-02-03 12:48       ` Cedric Le Goater
2006-02-03 14:02         ` Alexey Kuznetsov
2006-02-03 16:25           ` Dave Hansen
2006-02-06 11:24             ` Alexey Kuznetsov
2006-02-03 17:05           ` Cedric Le Goater
2006-02-06  9:48             ` Alexey Kuznetsov
2006-02-06 14:51               ` Serge E. Hallyn
2006-02-06 15:51                 ` Alexey Kuznetsov
2006-02-06 16:24                   ` Serge E. Hallyn
2006-02-07  9:46                   ` Cedric Le Goater
2006-02-07 11:44                     ` Kirill Korotaev
2006-02-07 12:59                       ` Cedric Le Goater
2006-02-07  9:15               ` Cedric Le Goater
2006-02-03 14:05         ` Kirill Korotaev
2006-02-03 15:40           ` Cedric Le Goater
2006-02-03 16:28             ` Kirill Korotaev
2006-02-02 16:31 ` [RFC][PATCH 6/7] VPIDs: small proc VPID export Kirill Korotaev
2006-02-02 16:33 ` [RFC][PATCH 7/7] VPIDs: required VPS interface for VPIDs Kirill Korotaev
2006-02-03  3:01 ` [RFC][PATCH] VPIDs: Virtualization of PIDs (OpenVZ approach) Herbert Poetzl
2006-02-03 10:30   ` Kirill Korotaev
2006-02-03 12:45   ` Alexey Kuznetsov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=43E23398.7090608@openvz.org \
    --to=dev@openvz.org \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=arjan@infradead.org \
    --cc=clg@fr.ibm.com \
    --cc=devel@openvz.org \
    --cc=frankeh@watson.ibm.com \
    --cc=haveblue@us.ibm.com \
    --cc=kuznet@ms2.inr.ac.ru \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mrmacman_g4@mac.com \
    --cc=serue@us.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.