Home » Mailing lists » Devel » [RFC][PATCH] VPIDs: Virtualization of PIDs (OpenVZ approach)
[RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case [message #1158 is a reply to message #1153] |
Thu, 02 February 2006 16:30   |
Kirill Korotaev
Messages: 137 Registered: January 2006
|
Senior Member |
|
|
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
--- ./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->
...
|
|
|
 |
|
[RFC][PATCH] VPIDs: Virtualization of PIDs (OpenVZ approach)
|
 |
|
[RFC][PATCH 1/7] VPIDs: add VPID config option
By: dev on Thu, 02 February 2006 16:16
|
 |
|
[RFC][PATCH 2/7] VPIDs: pid/vpid conversions
By: dev on Thu, 02 February 2006 16:21
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
By: ebiederm on Wed, 08 February 2006 20:29
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
By: ebiederm on Thu, 09 February 2006 00:37
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
By: ebiederm on Thu, 09 February 2006 01:36
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
By: serue on Thu, 09 February 2006 02:51
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
By: ebiederm on Thu, 09 February 2006 19:22
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
By: dev on Mon, 20 February 2006 14:55
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
By: dev on Tue, 21 February 2006 16:17
|
 |
|
Re: [RFC][PATCH 2/7] VPIDs: pid/vpid conversions
|
 |
|
[RFC][PATCH 3/7] VPIDs: fork modifications
By: dev on Thu, 02 February 2006 16:24
|
 |
|
Re: [RFC][PATCH 3/7] VPIDs: fork modifications
|
 |
|
[RFC][PATCH 4/7] VPIDs: vpid macros in non-VPID case
|
 |
|
[RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
By: serue on Thu, 02 February 2006 19:29
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
By: serue on Mon, 06 February 2006 14:51
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
By: serue on Mon, 06 February 2006 16:24
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
By: dev on Tue, 07 February 2006 11:42
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
By: dev on Fri, 03 February 2006 14:03
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
Re: [RFC][PATCH 5/7] VPIDs: vpid/pid conversion in VPID enabled case
|
 |
|
[RFC][PATCH 6/7] VPIDs: small proc VPID export
|
 |
|
[RFC][PATCH 7/7] VPIDs: required VPS interface for VPIDs
|
 |
|
Re: [RFC][PATCH] VPIDs: Virtualization of PIDs (OpenVZ approach)
|
 |
|
Re: [RFC][PATCH] VPIDs: Virtualization of PIDs (OpenVZ approach)
|
 |
|
Re: [RFC][PATCH] VPIDs: Virtualization of PIDs (OpenVZ approach)
|
Goto Forum:
Current Time: Sat Aug 30 12:16:38 GMT 2025
Total time taken to generate the page: 0.08005 seconds
|