updated
authorEnrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
Mon, 18 Oct 2004 16:08:07 +0000 (16:08 +0000)
committerEnrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
Mon, 18 Oct 2004 16:08:07 +0000 (16:08 +0000)
git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@1729 94cd875c-1c1d-0410-91d2-eb244daf1a30

util-vserver/kernel/context.h
util-vserver/kernel/cvirt.h
util-vserver/kernel/inode.h
util-vserver/kernel/legacy.h
util-vserver/kernel/limit.h
util-vserver/kernel/namespace.h
util-vserver/kernel/network.h
util-vserver/kernel/sched.h
util-vserver/kernel/signal.h
util-vserver/kernel/switch.h
util-vserver/kernel/xid.h

index a51a035..94692ba 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/list.h>
 #include <linux/spinlock.h>
+#include <linux/rcupdate.h>
 
 #define _VX_INFO_DEF_
 #include "cvirt.h"
 #undef _VX_INFO_DEF_
 
 struct vx_info {
-       struct list_head vx_list;               /* linked list of contexts */
+       struct hlist_node vx_hlist;             /* linked list of contexts */
+       struct rcu_head vx_rcu;                 /* the rcu head */
        xid_t vx_id;                            /* context id */
-       atomic_t vx_refcount;                   /* refcount */
+       atomic_t vx_usecnt;                     /* usage count */
+       atomic_t vx_refcnt;                     /* reference count */
        struct vx_info *vx_parent;              /* parent context */
+       int vx_state;                           /* context state */
 
        struct namespace *vx_namespace;         /* private namespace */
        struct fs_struct *vx_fs;                /* private namespace fs */
-       uint64_t vx_flags;                      /* VX_INFO_xxx */
+       uint64_t vx_flags;                      /* context flags */
        uint64_t vx_bcaps;                      /* bounding caps (system) */
        uint64_t vx_ccaps;                      /* context caps (vserver) */
 
        pid_t vx_initpid;                       /* PID of fake init process */
 
-       struct _vx_cvirt cvirt;                 /* virtual/bias stuff */
+       spinlock_t vx_lock;
+       wait_queue_head_t vx_exit;              /* context exit waitqueue */
+
        struct _vx_limit limit;                 /* vserver limits */
        struct _vx_sched sched;                 /* vserver scheduler */
+       struct _vx_cvirt cvirt;                 /* virtual/bias stuff */
+       struct _vx_cacct cacct;                 /* context accounting */
 
        char vx_name[65];                       /* vserver name */
 };
 
+/* status flags */
 
-extern spinlock_t vxlist_lock;
-extern struct list_head vx_infos;
+#define VXS_HASHED     0x0001
+#define VXS_PAUSED     0x0010
+#define VXS_ONHOLD     0x0020
+#define VXS_SHUTDOWN   0x0100
+#define VXS_DEFUNCT    0x1000
+#define VXS_RELEASED   0x8000
 
+/* check conditions */
 
 #define VX_ADMIN       0x0001
 #define VX_WATCH       0x0002
@@ -62,11 +76,16 @@ extern struct list_head vx_infos;
 #define VX_ATR_MASK    0x0F00
 
 
-void free_vx_info(struct vx_info *);
+struct rcu_head;
+
+// extern void rcu_free_vx_info(struct rcu_head *);
+extern void unhash_vx_info(struct vx_info *);
+
+extern struct vx_info *locate_vx_info(int);
+extern struct vx_info *locate_or_create_vx_info(int);
 
-extern struct vx_info *find_vx_info(int);
-extern struct vx_info *find_or_create_vx_info(int);
-extern int vx_info_id_valid(int);
+extern int get_xid_list(int, unsigned int *, int);
+extern int vx_info_is_hashed(xid_t);
 
 extern int vx_migrate_task(struct task_struct *, struct vx_info *);
 
@@ -87,10 +106,10 @@ extern int vc_task_xid(uint32_t, void __user *);
 #define VCMD_vx_info           VC_CMD(VINFO, 5, 0)
 #define VCMD_nx_info           VC_CMD(VINFO, 6, 0)
 
-struct  vcmd_vx_info_v0 {
+struct vcmd_vx_info_v0 {
        uint32_t xid;
        uint32_t initpid;
-       /* more to come */      
+       /* more to come */
 };
 
 #ifdef __KERNEL__
@@ -110,7 +129,7 @@ extern int vc_ctx_migrate(uint32_t, void __user *);
 #define VCMD_get_cflags                VC_CMD(FLAGS, 1, 0)
 #define VCMD_set_cflags                VC_CMD(FLAGS, 2, 0)
 
-struct  vcmd_ctx_flags_v0 {
+struct vcmd_ctx_flags_v0 {
        uint64_t flagword;
        uint64_t mask;
 };
@@ -138,6 +157,7 @@ extern int vc_set_cflags(uint32_t, void __user *);
 #define VXF_VIRT_MEM           0x00010000
 #define VXF_VIRT_UPTIME                0x00020000
 #define VXF_VIRT_CPU           0x00040000
+#define VXF_VIRT_LOAD          0x00080000
 
 #define VXF_HIDE_MOUNT         0x01000000
 #define VXF_HIDE_NETIF         0x02000000
@@ -145,13 +165,15 @@ extern int vc_set_cflags(uint32_t, void __user *);
 #define VXF_STATE_SETUP                (1ULL<<32)
 #define VXF_STATE_INIT         (1ULL<<33)
 
+#define VXF_FORK_RSS           (1ULL<<48)
+#define VXF_PROLIFIC           (1ULL<<49)
 
 #define VXF_ONE_TIME           (0x0003ULL<<32)
 
 #define VCMD_get_ccaps         VC_CMD(FLAGS, 3, 0)
 #define VCMD_set_ccaps         VC_CMD(FLAGS, 4, 0)
 
-struct  vcmd_ctx_caps_v0 {
+struct vcmd_ctx_caps_v0 {
        uint64_t bcaps;
        uint64_t ccaps;
        uint64_t cmask;
@@ -166,7 +188,7 @@ extern int vc_set_ccaps(uint32_t, void __user *);
 #define VXC_SET_UTSNAME                0x00000001
 #define VXC_SET_RLIMIT         0x00000002
 
-#define VXC_ICMP_PING          0x00000100
+#define VXC_RAW_ICMP           0x00000100
 
 #define VXC_SECURE_MOUNT       0x00010000
 
index a8a242e..1f83546 100644 (file)
@@ -1,44 +1,58 @@
+/* _VX_CVIRT_H defined below */
+
 #if    defined(__KERNEL__) && defined(_VX_INFO_DEF_)
 
 #include <linux/utsname.h>
 #include <linux/rwsem.h>
 #include <linux/jiffies.h>
 #include <linux/time.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
 #include <asm/atomic.h>
 
 /* context sub struct */
 
+struct _vx_cvirt {
+       int max_threads;                /* maximum allowed threads */
+       atomic_t nr_threads;            /* number of current threads */
+       atomic_t nr_running;            /* number of running threads */
+
+       atomic_t nr_onhold;             /* processes on hold */
+       uint32_t onhold_last;           /* jiffies when put on hold */
+
+       struct timespec bias_idle;
+       uint64_t bias_jiffies;          /* context creation point */
+
+       struct new_utsname utsname;
+
+       spinlock_t load_lock;           /* lock for the load averages */
+       uint32_t load_last;             /* last time load was cacled */
+       uint32_t load[3];               /* load averages 1,5,15 */
+
+       struct cpu_usage_stat cpustat[NR_CPUS];
+};
+
 struct sock_acc {
        atomic_t count;
        atomic_t total;
 };
 
-struct _vx_cvirt {
-       int nr_threads;
-       int nr_running;
-       int max_threads;
+struct _vx_cacct {
        unsigned long total_forks;
 
-       unsigned int bias_cswtch;
-       struct timespec bias_idle;
-       struct timespec bias_tp;
-       uint64_t bias_jiffies;
-
-       struct new_utsname utsname;
-
        struct sock_acc sock[5][3];
 };
 
 
-static inline long vx_sock_count(struct _vx_cvirt *cvirt, int type, int pos)
+static inline long vx_sock_count(struct _vx_cacct *cacct, int type, int pos)
 {
-       return atomic_read(&cvirt->sock[type][pos].count);
+       return atomic_read(&cacct->sock[type][pos].count);
 }
 
 
-static inline long vx_sock_total(struct _vx_cvirt *cvirt, int type, int pos)
+static inline long vx_sock_total(struct _vx_cacct *cacct, int type, int pos)
 {
-       return atomic_read(&cvirt->sock[type][pos].total);
+       return atomic_read(&cacct->sock[type][pos].total);
 }
 
 
@@ -46,30 +60,103 @@ extern uint64_t vx_idle_jiffies(void);
 
 static inline void vx_info_init_cvirt(struct _vx_cvirt *cvirt)
 {
-       int i,j;
        uint64_t idle_jiffies = vx_idle_jiffies();
 
-       cvirt->nr_threads = 1;
-       // new->virt.bias_cswtch = kstat.context_swtch;
        cvirt->bias_jiffies = get_jiffies_64();
-
        jiffies_to_timespec(idle_jiffies, &cvirt->bias_idle);
-       do_posix_clock_monotonic_gettime(&cvirt->bias_tp);
+       atomic_set(&cvirt->nr_threads, 0);
+       atomic_set(&cvirt->nr_running, 0);
+       atomic_set(&cvirt->nr_onhold, 0);
 
        down_read(&uts_sem);
        cvirt->utsname = system_utsname;
        up_read(&uts_sem);
 
+       spin_lock_init(&cvirt->load_lock);
+       cvirt->load_last = jiffies;
+       cvirt->load[0] = 0;
+       cvirt->load[1] = 0;
+       cvirt->load[2] = 0;
+}
+
+static inline void vx_info_exit_cvirt(struct _vx_cvirt *cvirt)
+{
+#ifdef CONFIG_VSERVER_DEBUG
+       int value;
+
+       if ((value = atomic_read(&cvirt->nr_threads)))
+               printk("!!! cvirt: %p[nr_threads] = %d on exit.\n",
+                       cvirt, value);
+       if ((value = atomic_read(&cvirt->nr_running)))
+               printk("!!! cvirt: %p[nr_running] = %d on exit.\n",
+                       cvirt, value);
+#endif
+       return;
+}
+
+static inline void vx_info_init_cacct(struct _vx_cacct *cacct)
+{
+       int i,j;
+
        for (i=0; i<5; i++) {
                for (j=0; j<3; j++) {
-                       atomic_set(&cvirt->sock[i][j].count, 0);
-                       atomic_set(&cvirt->sock[i][j].total, 0);
+                       atomic_set(&cacct->sock[i][j].count, 0);
+                       atomic_set(&cacct->sock[i][j].total, 0);
                }
        }
 }
 
+static inline void vx_info_exit_cacct(struct _vx_cacct *cacct)
+{
+       return;
+}
+
+#define LOAD_INT(x) ((x) >> FSHIFT)
+#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
+
+
 static inline int vx_info_proc_cvirt(struct _vx_cvirt *cvirt, char *buffer)
 {
+       int length = 0;
+       int a, b, c;
+
+       length += sprintf(buffer + length,
+               "BiasJiffies:\t%lld\n", (long long int)cvirt->bias_jiffies);
+       length += sprintf(buffer + length,
+               "SysName:\t%.*s\n"
+               "NodeName:\t%.*s\n"
+               "Release:\t%.*s\n"
+               "Version:\t%.*s\n"
+               "Machine:\t%.*s\n"
+               "DomainName:\t%.*s\n"
+               ,__NEW_UTS_LEN, cvirt->utsname.sysname
+               ,__NEW_UTS_LEN, cvirt->utsname.nodename
+               ,__NEW_UTS_LEN, cvirt->utsname.release
+               ,__NEW_UTS_LEN, cvirt->utsname.version
+               ,__NEW_UTS_LEN, cvirt->utsname.machine
+               ,__NEW_UTS_LEN, cvirt->utsname.domainname
+               );
+
+       a = cvirt->load[0] + (FIXED_1/200);
+       b = cvirt->load[1] + (FIXED_1/200);
+       c = cvirt->load[2] + (FIXED_1/200);
+       length += sprintf(buffer + length,
+               "nr_threads:\t%d\n"
+               "nr_running:\t%d\n"
+               "nr_onhold:\t%d\n"
+               "loadavg:\t%d.%02d %d.%02d %d.%02d\n"
+               ,atomic_read(&cvirt->nr_threads)
+               ,atomic_read(&cvirt->nr_running)
+               ,atomic_read(&cvirt->nr_onhold)
+               ,LOAD_INT(a), LOAD_FRAC(a)
+               ,LOAD_INT(b), LOAD_FRAC(b)
+               ,LOAD_INT(c), LOAD_FRAC(c)
+               );
+       return length;
+}
+
+static inline int vx_info_proc_cacct(struct _vx_cacct *cacct, char *buffer)
+{
        int i,j, length = 0;
        static char *type[] = { "UNSPEC", "UNIX", "INET", "INET6", "OTHER" };
 
@@ -79,12 +166,14 @@ static inline int vx_info_proc_cvirt(struct _vx_cvirt *cvirt, char *buffer)
                for (j=0; j<3; j++) {
                        length += sprintf(buffer + length,
                                "\t%12lu/%-12lu"
-                               ,vx_sock_count(cvirt, i, j)
-                               ,vx_sock_total(cvirt, i, j)
+                               ,vx_sock_count(cacct, i, j)
+                               ,vx_sock_total(cacct, i, j)
                                );
-               }       
+               }
                buffer[length++] = '\n';
        }
+       length += sprintf(buffer + length,
+               "forks:\t%lu\n", cacct->total_forks);
        return length;
 }
 
@@ -101,7 +190,12 @@ static inline int vx_info_proc_cvirt(struct _vx_cvirt *cvirt, char *buffer)
 
 struct timespec;
 
-void vx_vsi_uptime(struct timespec *uptime, struct timespec *idle);
+void vx_vsi_uptime(struct timespec *, struct timespec *);
+
+struct vx_info;
+
+void vx_update_load(struct vx_info *);
+
 
 #endif /* __KERNEL__ */
 
index aa8852f..b8a5e78 100644 (file)
@@ -11,7 +11,7 @@
 #define VCMD_get_iattr         VC_CMD(INODE, 1, 1)
 #define VCMD_set_iattr         VC_CMD(INODE, 2, 1)
 
-struct  vcmd_ctx_iattr_v0 {
+struct vcmd_ctx_iattr_v0 {
        /* device handle in id */
        uint64_t ino;
        uint32_t xid;
@@ -19,7 +19,7 @@ struct  vcmd_ctx_iattr_v0 {
        uint32_t mask;
 };
 
-struct  vcmd_ctx_iattr_v1 {
+struct vcmd_ctx_iattr_v1 {
        const char __user *name;
        uint32_t xid;
        uint32_t flags;
@@ -36,10 +36,10 @@ struct  vcmd_ctx_iattr_v1 {
 
 #define IATTR_BARRIER  0x00010000
 #define IATTR_IUNLINK  0x00020000
-#define IATTR_IMMUTABLE        0x00040000
+#define IATTR_IMMUTABLE 0x00040000
 
 
-#ifdef CONFIG_PROC_SECURE
+#ifdef CONFIG_VSERVER_PROC_SECURE
 #define IATTR_PROC_DEFAULT     ( IATTR_ADMIN | IATTR_HIDE )
 #define IATTR_PROC_SYMLINK     ( IATTR_ADMIN )
 #else
@@ -49,7 +49,7 @@ struct  vcmd_ctx_iattr_v1 {
 
 #ifdef __KERNEL__
 
-#define vx_hide_check(c,m)      (((m) & IATTR_HIDE) ? vx_check(c,m) : 1)
+#define vx_hide_check(c,m)     (((m) & IATTR_HIDE) ? vx_check(c,m) : 1)
 
 extern int vc_get_iattr_v0(uint32_t, void __user *);
 extern int vc_set_iattr_v0(uint32_t, void __user *);
index 1372c0f..877bfb8 100644 (file)
 
 /*  compatibiliy vserver arguments */
 
-struct  vcmd_new_s_context_v1 {
+struct vcmd_new_s_context_v1 {
        uint32_t remove_cap;
        uint32_t flags;
 };
 
-struct  vcmd_set_ipv4root_v3 {
+struct vcmd_set_ipv4root_v3 {
        /* number of pairs in id */
        uint32_t broadcast;
        struct {
@@ -40,7 +40,7 @@ struct  vcmd_set_ipv4root_v3 {
                                        /* of the context */
 #define VX_INFO_NAMESPACE      128     /* save private namespace */
 
-       
+
 #define NB_S_CONTEXT   16
 
 #define NB_IPV4ROOT    16
index 74e02cd..d9e1eea 100644 (file)
@@ -1,3 +1,5 @@
+/* _VX_LIMIT_H defined below */
+
 #if    defined(__KERNEL__) && defined(_VX_INFO_DEF_)
 
 #include <asm/atomic.h>
@@ -5,46 +7,87 @@
 
 /* context sub struct */
 
-#define NUM_RLIMITS    16
+#define NUM_LIMITS     20
+
+#define VLIMIT_NSOCK   16
 
-#define VLIMIT_SOCK    16
 
+extern const char *vlimit_name[NUM_LIMITS];
 
 struct _vx_limit {
        atomic_t ticks;
 
-       unsigned long rlim[NUM_RLIMITS];        /* Per context limit */
-       atomic_t res[NUM_RLIMITS];              /* Current value */
+       unsigned long rlim[NUM_LIMITS];         /* Context limit */
+       unsigned long rmax[NUM_LIMITS];         /* Context maximum */
+       atomic_t rcur[NUM_LIMITS];              /* Current value */
+       atomic_t lhit[NUM_LIMITS];              /* Limit hits */
 };
 
 static inline void vx_info_init_limit(struct _vx_limit *limit)
 {
        int lim;
 
-       for (lim=0; lim<NUM_RLIMITS; lim++) {
+       for (lim=0; lim<NUM_LIMITS; lim++) {
                limit->rlim[lim] = RLIM_INFINITY;
-               atomic_set(&limit->res[lim], 0);
+               limit->rmax[lim] = 0;
+               atomic_set(&limit->rcur[lim], 0);
+               atomic_set(&limit->lhit[lim], 0);
+       }
+}
+
+static inline void vx_info_exit_limit(struct _vx_limit *limit)
+{
+#ifdef CONFIG_VSERVER_DEBUG
+       unsigned long value;
+       unsigned int lim;
+
+       for (lim=0; lim<NUM_LIMITS; lim++) {
+               value = atomic_read(&limit->rcur[lim]);
+               if (value)
+                       printk("!!! limit: %p[%s,%d] = %ld on exit.\n",
+                               limit, vlimit_name[lim], lim, value);
+       }
+#endif
+}
+
+static inline void vx_limit_fixup(struct _vx_limit *limit)
+{
+       unsigned long value;
+       unsigned int lim;
+
+       for (lim=0; lim<NUM_LIMITS; lim++) {
+               value = atomic_read(&limit->rcur[lim]);
+               if (value > limit->rmax[lim])
+                       limit->rmax[lim] = value;
+               if (limit->rmax[lim] > limit->rlim[lim])
+                       limit->rmax[lim] = limit->rlim[lim];
        }
 }
 
+#define VX_LIMIT_FMT   ":\t%10d\t%10ld\t%10ld\t%6d\n"
+
+#define VX_LIMIT_ARG(r)                                \
+               ,atomic_read(&limit->rcur[r])   \
+               ,limit->rmax[r]                 \
+               ,limit->rlim[r]                 \
+               ,atomic_read(&limit->lhit[r])
+
 static inline int vx_info_proc_limit(struct _vx_limit *limit, char *buffer)
 {
+       vx_limit_fixup(limit);
        return sprintf(buffer,
-               "PROC:\t%8d/%ld\n"
-               "VM:\t%8d/%ld\n"
-               "VML:\t%8d/%ld\n"               
-               "RSS:\t%8d/%ld\n"
-               "FILES:\t%8d/%ld\n"
-               ,atomic_read(&limit->res[RLIMIT_NPROC])
-               ,limit->rlim[RLIMIT_NPROC]
-               ,atomic_read(&limit->res[RLIMIT_AS])
-               ,limit->rlim[RLIMIT_AS]
-               ,atomic_read(&limit->res[RLIMIT_MEMLOCK])
-               ,limit->rlim[RLIMIT_MEMLOCK]
-               ,atomic_read(&limit->res[RLIMIT_RSS])
-               ,limit->rlim[RLIMIT_RSS]
-               ,atomic_read(&limit->res[RLIMIT_NOFILE])
-               ,limit->rlim[RLIMIT_NOFILE]
+               "PROC"  VX_LIMIT_FMT
+               "VM"    VX_LIMIT_FMT
+               "VML"   VX_LIMIT_FMT
+               "RSS"   VX_LIMIT_FMT
+               "FILES" VX_LIMIT_FMT
+               "SOCK"  VX_LIMIT_FMT
+               VX_LIMIT_ARG(RLIMIT_NPROC)
+               VX_LIMIT_ARG(RLIMIT_AS)
+               VX_LIMIT_ARG(RLIMIT_MEMLOCK)
+               VX_LIMIT_ARG(RLIMIT_RSS)
+               VX_LIMIT_ARG(RLIMIT_NOFILE)
+               VX_LIMIT_ARG(VLIMIT_NSOCK)
                );
 }
 
@@ -54,20 +97,22 @@ static inline int vx_info_proc_limit(struct _vx_limit *limit, char *buffer)
 
 #include "switch.h"
 
+#define VXD_RLIMIT(r,l)                (VXD_CBIT(limit, (l)) && ((r) == (l)))
+
 /*  rlimit vserver commands */
 
 #define VCMD_get_rlimit                VC_CMD(RLIMIT, 1, 0)
 #define VCMD_set_rlimit                VC_CMD(RLIMIT, 2, 0)
 #define VCMD_get_rlimit_mask   VC_CMD(RLIMIT, 3, 0)
 
-struct  vcmd_ctx_rlimit_v0 {
+struct vcmd_ctx_rlimit_v0 {
        uint32_t id;
        uint64_t minimum;
        uint64_t softlimit;
        uint64_t maximum;
 };
 
-struct  vcmd_ctx_rlimit_mask_v0 {
+struct vcmd_ctx_rlimit_mask_v0 {
        uint32_t minimum;
        uint32_t softlimit;
        uint32_t maximum;
@@ -95,3 +140,5 @@ void vx_vsi_swapinfo(struct sysinfo *);
 
 #endif /* _VX_LIMIT_H */
 #endif
+
+
index 140fc79..08167a1 100644 (file)
@@ -3,13 +3,13 @@
 
 #include <linux/types.h>
 
-       
+
 /* virtual host info names */
 
 #define VCMD_vx_set_vhi_name   VC_CMD(VHOST, 1, 0)
 #define VCMD_vx_get_vhi_name   VC_CMD(VHOST, 2, 0)
 
-struct  vcmd_vx_vhi_name_v0 {
+struct vcmd_vx_vhi_name_v0 {
        uint32_t field;
        char name[65];
 };
@@ -44,6 +44,9 @@ extern int vc_get_vhi_name(uint32_t, void __user *);
 struct vx_info;
 struct namespace;
 struct fs_struct;
+struct vfsmount;
+
+extern int vx_check_vfsmount(struct vx_info *, struct vfsmount *);
 
 extern int vx_set_namespace(struct vx_info *, struct namespace *, struct fs_struct *);
 
index b3c39b0..e77866b 100644 (file)
@@ -3,7 +3,7 @@
 
 #define MAX_N_CONTEXT  65535   /* Arbitrary limit */
 
-#define IP_DYNAMIC_ID  ((uint32_t)-1)          /* id for dynamic context */
+#define NX_DYNAMIC_ID  ((uint32_t)-1)          /* id for dynamic context */
 
 #define NB_IPV4ROOT    16
 
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/utsname.h>
+#include <linux/rcupdate.h>
 #include <asm/resource.h>
 #include <asm/atomic.h>
 
 
 struct nx_info {
-       struct list_head nx_list;       /* linked list of nxinfos */
+       struct hlist_node nx_hlist;     /* linked list of nxinfos */
+       struct rcu_head nx_rcu;         /* the rcu head */
        nid_t nx_id;                    /* vnet id */
-       atomic_t nx_refcount;
+       atomic_t nx_usecnt;             /* usage count */
+       atomic_t nx_refcnt;             /* reference count */
 
        uint64_t nx_flags;              /* network flag word */
        uint64_t nx_ncaps;              /* network capabilities */
@@ -38,15 +41,18 @@ struct nx_info {
 };
 
 
-extern spinlock_t nxlist_lock;
-extern struct list_head nx_infos;
+struct rcu_head;
 
+extern void rcu_free_nx_info(struct rcu_head *);
+extern void unhash_nx_info(struct nx_info *);
 
-void free_nx_info(struct nx_info *);
-struct nx_info *create_nx_info(void);
+extern struct nx_info *locate_nx_info(int);
+extern struct nx_info *locate_or_create_nx_info(int);
 
-extern struct nx_info *find_nx_info(int);
-extern int nx_info_id_valid(int);
+extern int get_nid_list(int, unsigned int *, int);
+extern int nx_info_is_hashed(nid_t);
+
+extern int nx_migrate_task(struct task_struct *, struct nx_info *);
 
 struct in_ifaddr;
 struct net_device;
@@ -54,6 +60,10 @@ struct net_device;
 int ifa_in_nx_info(struct in_ifaddr *, struct nx_info *);
 int dev_in_nx_info(struct net_device *, struct nx_info *);
 
+struct sock;
+
+int nx_addr_conflict(struct nx_info *, uint32_t, struct sock *);
+
 
 #endif /* __KERNEL__ */
 
@@ -70,9 +80,9 @@ extern int vc_task_nid(uint32_t, void __user *);
 
 #define VCMD_nx_info           VC_CMD(VINFO, 6, 0)
 
-struct  vcmd_nx_info_v0 {
+struct vcmd_nx_info_v0 {
        uint32_t nid;
-       /* more to come */      
+       /* more to come */
 };
 
 #ifdef __KERNEL__
@@ -86,15 +96,15 @@ extern int vc_nx_info(uint32_t, void __user *);
 #define VCMD_net_add           VC_CMD(NETALT, 1, 0)
 #define VCMD_net_remove                VC_CMD(NETALT, 2, 0)
 
-struct  vcmd_net_nx_v0 {
+struct vcmd_net_nx_v0 {
        uint16_t type;
        uint16_t count;
        uint32_t ip[4];
        uint32_t mask[4];
-       /* more to come */      
+       /* more to come */
 };
 
-//     IPN_TYPE_IPV4   
+//     IPN_TYPE_IPV4
 
 
 #ifdef __KERNEL__
@@ -106,7 +116,7 @@ extern int vc_net_migrate(uint32_t, void __user *);
 #define VCMD_get_nflags                VC_CMD(FLAGS, 5, 0)
 #define VCMD_set_nflags                VC_CMD(FLAGS, 6, 0)
 
-struct  vcmd_net_flags_v0 {
+struct vcmd_net_flags_v0 {
        uint64_t flagword;
        uint64_t mask;
 };
@@ -125,7 +135,7 @@ extern int vc_set_nflags(uint32_t, void __user *);
 #define VCMD_get_ncaps         VC_CMD(FLAGS, 7, 0)
 #define VCMD_set_ncaps         VC_CMD(FLAGS, 8, 0)
 
-struct  vcmd_net_caps_v0 {
+struct vcmd_net_caps_v0 {
        uint64_t ncaps;
        uint64_t cmask;
 };
index 9db06e5..f7ac947 100644 (file)
@@ -1,57 +1,97 @@
+/* _VX_SCHED_H defined below */
+
 #if    defined(__KERNEL__) && defined(_VX_INFO_DEF_)
 
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
+#include <linux/cpumask.h>
 #include <asm/atomic.h>
 #include <asm/param.h>
-#include <asm/cpumask.h>
+
+struct _vx_ticks {
+       uint64_t user_ticks;            /* token tick events */
+       uint64_t sys_ticks;             /* token tick events */
+       uint64_t hold_ticks;            /* token ticks paused */
+       uint64_t unused[5];             /* cacheline ? */
+};
 
 /* context sub struct */
 
 struct _vx_sched {
-       spinlock_t tokens_lock; /* lock for this structure */
+       atomic_t tokens;                /* number of CPU tokens */
+       spinlock_t tokens_lock;         /* lock for token bucket */
 
-       int fill_rate;          /* Fill rate: add X tokens... */
-       int interval;           /* Divisor:   per Y jiffies   */
-       atomic_t tokens;        /* number of CPU tokens in this context */
-       int tokens_min;         /* Limit:     minimum for unhold */
-       int tokens_max;         /* Limit:     no more than N tokens */
-       uint32_t jiffies;       /* add an integral multiple of Y to this */
+       int fill_rate;                  /* Fill rate: add X tokens... */
+       int interval;                   /* Divisor:   per Y jiffies   */
+       int tokens_min;                 /* Limit:     minimum for unhold */
+       int tokens_max;                 /* Limit:     no more than N tokens */
+       uint32_t jiffies;               /* last time accounted */
 
-       uint64_t ticks;         /* token tick events */
-       cpumask_t cpus_allowed; /* cpu mask for context */
+       int priority_bias;              /* bias offset for priority */
+       cpumask_t cpus_allowed;         /* cpu mask for context */
+
+       struct _vx_ticks cpu[NR_CPUS];
 };
 
 static inline void vx_info_init_sched(struct _vx_sched *sched)
 {
-        /* scheduling; hard code starting values as constants */
-        sched->fill_rate       = 1;
-        sched->interval                = 4;
-        sched->tokens_min      = HZ >> 4;
-        sched->tokens_max      = HZ >> 1;
-        sched->jiffies         = jiffies;
-        sched->tokens_lock     = SPIN_LOCK_UNLOCKED;
-
-        atomic_set(&sched->tokens, HZ >> 2);
+       int i;
+
+       /* scheduling; hard code starting values as constants */
+       sched->fill_rate        = 1;
+       sched->interval         = 4;
+       sched->tokens_min       = HZ >> 4;
+       sched->tokens_max       = HZ >> 1;
+       sched->jiffies          = jiffies;
+       sched->tokens_lock      = SPIN_LOCK_UNLOCKED;
+
+       atomic_set(&sched->tokens, HZ >> 2);
        sched->cpus_allowed     = CPU_MASK_ALL;
+       sched->priority_bias    = 0;
+
+       for_each_cpu(i) {
+               sched->cpu[i].user_ticks        = 0;
+               sched->cpu[i].sys_ticks         = 0;
+               sched->cpu[i].hold_ticks        = 0;
+       }
+}
+
+static inline void vx_info_exit_sched(struct _vx_sched *sched)
+{
+       return;
 }
 
 static inline int vx_info_proc_sched(struct _vx_sched *sched, char *buffer)
 {
-       return sprintf(buffer,
-               "Ticks:\t%16lld\n"
+       int length = 0;
+       int i;
+
+       length += sprintf(buffer,
                "Token:\t\t%8d\n"
                "FillRate:\t%8d\n"
-               "Interval:\t%8d\n"              
+               "Interval:\t%8d\n"
                "TokensMin:\t%8d\n"
                "TokensMax:\t%8d\n"
-               ,sched->ticks
+               "PrioBias:\t%8d\n"
                ,atomic_read(&sched->tokens)
                ,sched->fill_rate
                ,sched->interval
                ,sched->tokens_min
                ,sched->tokens_max
+               ,sched->priority_bias
                );
+
+       for_each_online_cpu(i) {
+               length += sprintf(buffer + length,
+                       "cpu %d: %lld %lld %lld\n"
+                       ,i
+                       ,sched->cpu[i].user_ticks
+                       ,sched->cpu[i].sys_ticks
+                       ,sched->cpu[i].hold_ticks
+                       );
+       }
+
+       return length;
 }
 
 
@@ -63,9 +103,10 @@ static inline int vx_info_proc_sched(struct _vx_sched *sched, char *buffer)
 
 /*  sched vserver commands */
 
-#define VCMD_set_sched         VC_CMD(SCHED, 1, 2)
+#define VCMD_set_sched_v2      VC_CMD(SCHED, 1, 2)
+#define VCMD_set_sched         VC_CMD(SCHED, 1, 3)
 
-struct  vcmd_set_sched_v2 {
+struct vcmd_set_sched_v2 {
        int32_t fill_rate;
        int32_t interval;
        int32_t tokens;
@@ -74,34 +115,38 @@ struct  vcmd_set_sched_v2 {
        uint64_t cpu_mask;
 };
 
-struct  vcmd_set_sched_v3 {
-        uint32_t set_mask;
-        int32_t fill_rate;
-        int32_t interval;
-        int32_t tokens;
-        int32_t tokens_min;
-        int32_t tokens_max;
-        int32_t priority_bias;
+struct vcmd_set_sched_v3 {
+       uint32_t set_mask;
+       int32_t fill_rate;
+       int32_t interval;
+       int32_t tokens;
+       int32_t tokens_min;
+       int32_t tokens_max;
+       int32_t priority_bias;
 };
 
-#define VXSM_FILL_RATE          0x0001
-#define VXSM_INTERVAL           0x0002
-#define VXSM_TOKENS             0x0010
-#define VXSM_TOKENS_MIN         0x0020
-#define VXSM_TOKENS_MAX         0x0030
-#define VXSM_PRIO_BIAS          0x0100
 
+#define VXSM_FILL_RATE         0x0001
+#define VXSM_INTERVAL          0x0002
+#define VXSM_TOKENS            0x0010
+#define VXSM_TOKENS_MIN                0x0020
+#define VXSM_TOKENS_MAX                0x0040
+#define VXSM_PRIO_BIAS         0x0100
 
 #define SCHED_KEEP             (-2)
 
 #ifdef __KERNEL__
 
 extern int vc_set_sched_v1(uint32_t, void __user *);
+extern int vc_set_sched_v2(uint32_t, void __user *);
 extern int vc_set_sched(uint32_t, void __user *);
 
 
 #define VAVAVOOM_RATIO         50
 
+#define MAX_PRIO_BIAS          20
+#define MIN_PRIO_BIAS          -20
+
 #include "context.h"
 
 
@@ -127,25 +172,49 @@ static inline int vx_need_resched(struct task_struct *p)
 {
 #ifdef CONFIG_VSERVER_HARDCPU
        struct vx_info *vxi = p->vx_info;
+#endif
+       int slice = --p->time_slice;
 
+#ifdef CONFIG_VSERVER_HARDCPU
        if (vxi) {
                int tokens;
 
-               p->time_slice--;
-               if (atomic_read(&vxi->vx_refcount) < 1)
-                       printk("need_resched: p=%p, s=%ld, ref=%d, id=%d/%d\n",
-                               p, p->state, atomic_read(&vxi->vx_refcount),
-                               vxi->vx_id, p->xid);
                if ((tokens = vx_tokens_avail(vxi)) > 0)
                        vx_consume_token(vxi);
-               return ((p->time_slice == 0) || (tokens < 1));
+               /* for tokens > 0, one token was consumed */
+               if (tokens < 2)
+                       return 1;
        }
 #endif
-       p->time_slice--;
-       return (p->time_slice == 0);
+       return (slice == 0);
 }
 
 
+static inline void vx_onhold_inc(struct vx_info *vxi)
+{
+       int onhold = atomic_read(&vxi->cvirt.nr_onhold);
+
+       atomic_inc(&vxi->cvirt.nr_onhold);
+       if (!onhold)
+               vxi->cvirt.onhold_last = jiffies;
+}
+
+static inline void __vx_onhold_update(struct vx_info *vxi)
+{
+       int cpu = smp_processor_id();
+       uint32_t now = jiffies;
+       uint32_t delta = now - vxi->cvirt.onhold_last;
+
+       vxi->cvirt.onhold_last = now;
+       vxi->sched.cpu[cpu].hold_ticks += delta;
+}
+
+static inline void vx_onhold_dec(struct vx_info *vxi)
+{
+       if (atomic_dec_and_test(&vxi->cvirt.nr_onhold))
+               __vx_onhold_update(vxi);
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* _VX_SCHED_H */
index 3911127..7d0d430 100644 (file)
@@ -6,14 +6,22 @@
 /*  context signalling */
 
 #define VCMD_ctx_kill          VC_CMD(PROCTRL, 1, 0)
+#define VCMD_wait_exit         VC_CMD(EVENT, 99, 0)
 
-struct  vcmd_ctx_kill_v0 {
+struct vcmd_ctx_kill_v0 {
        int32_t pid;
        int32_t sig;
 };
 
+struct vcmd_wait_exit_v0 {
+       int32_t a;
+       int32_t b;
+};
+
 #ifdef __KERNEL__
+
 extern int vc_ctx_kill(uint32_t, void __user *);
+extern int vc_wait_exit(uint32_t, void __user *);
 
 #endif /* __KERNEL__ */
 #endif /* _VX_SIGNAL_H */
index 5fef690..5855b05 100644 (file)
 
 /*
 
-  Syscall Matrix V2.6
+  Syscall Matrix V2.8
 
-         |VERSION|CREATE |MODIFY |MIGRATE|CONTROL|EXPERIM| |SPECIAL|SPECIAL|
-         |STATS  |DESTROY|ALTER  |CHANGE |LIMIT  |TEST   | |       |       |
-         |INFO   |SETUP  |       |MOVE   |       |       | |       |       |
+        |VERSION|CREATE |MODIFY |MIGRATE|CONTROL|EXPERIM| |SPECIAL|SPECIAL|
+        |STATS  |DESTROY|ALTER  |CHANGE |LIMIT  |TEST   | |       |       |
+        |INFO   |SETUP  |       |MOVE   |       |       | |       |       |
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   SYSTEM |VERSION|VSETUP |VHOST  |       |       |       | |DEVICES|       |
   HOST   |     00|     01|     02|     03|     04|     05| |     06|     07|
   PROCESS|     08|     09|     10|     11|     12|     13| |     14|     15|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   MEMORY |       |       |       |       |       |       | |SWAP   |       |
-         |     16|     17|     18|     19|     20|     21| |     22|     23|
+        |     16|     17|     18|     19|     20|     21| |     22|     23|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   NETWORK|       |VNET   |NETALT |NETMIG |NETCTL |       | |SERIAL |       |
-         |     24|     25|     26|     27|     28|     29| |     30|     31|
+        |     24|     25|     26|     27|     28|     29| |     30|     31|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
-  DISK   |       |       |       |       |       |       | |INODE  |       |
+  DISK   |       |       |       |       |DLIMIT |       | |INODE  |       |
   VFS    |     32|     33|     34|     35|     36|     37| |     38|     39|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   OTHER  |       |       |       |       |       |       | |VINFO  |       |
-         |     40|     41|     42|     43|     44|     45| |     46|     47|
+        |     40|     41|     42|     43|     44|     45| |     46|     47|
   =======+=======+=======+=======+=======+=======+=======+ +=======+=======+
-  SPECIAL|       |       |       |       |FLAGS  |       | |       |       |
-         |     48|     49|     50|     51|     52|     53| |     54|     55|
+  SPECIAL|EVENT  |       |       |       |FLAGS  |       | |       |       |
+        |     48|     49|     50|     51|     52|     53| |     54|     55|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
   SPECIAL|       |       |       |       |RLIMIT |SYSCALL| |       |COMPAT |
-         |     56|     57|     58|     59|     60|TEST 61| |     62|     63|
+        |     56|     57|     58|     59|     60|TEST 61| |     62|     63|
   -------+-------+-------+-------+-------+-------+-------+ +-------+-------+
 
 */
@@ -49,7 +49,7 @@
 
 #define VC_CAT_VSETUP          1
 #define VC_CAT_VHOST           2
-       
+
 #define VC_CAT_VPROC           9
 #define VC_CAT_PROCALT         10
 #define VC_CAT_PROCMIG         11
 #define VC_CAT_NETMIG          27
 #define VC_CAT_NETCTRL         28
 
+#define VC_CAT_DLIMIT          36
 #define VC_CAT_INODE           38
 
 #define VC_CAT_VINFO           46
+#define VC_CAT_EVENT           48
 
 #define VC_CAT_FLAGS           52
 #define VC_CAT_RLIMIT          60
 
 #define VC_CAT_SYSTEST         61
 #define VC_CAT_COMPAT          63
-       
+
 /*  interface version */
 
-#define VCI_VERSION            0x00010016
+#define VCI_VERSION            0x00010022
 
 
 /*  query version */
@@ -86,7 +88,6 @@
 
 #include <linux/errno.h>
 
-#define ENOTSUP                -EOPNOTSUPP
 
 #else  /* __KERNEL__ */
 #define __user
index ba52c25..23908fd 100644 (file)
@@ -1,15 +1,21 @@
-#ifndef _LINUX_XID_H_
-#define _LINUX_XID_H_
+#ifndef _VX_XID_H
+#define _VX_XID_H
+
+
+#define XID_TAG(in)    (!(in) || \
+       (((struct inode *)in)->i_sb && \
+       (((struct inode *)in)->i_sb->s_flags & MS_TAGXID)))
+
 
 #ifdef CONFIG_INOXID_NONE
 
 #define MAX_UID                0xFFFFFFFF
 #define MAX_GID                0xFFFFFFFF
 
-#define INOXID_XID(uid, gid, xid)      (0)
+#define INOXID_XID(tag, uid, gid, xid) (0)
 
-#define XIDINO_UID(uid, xid)           (uid)
-#define XIDINO_GID(gid, xid)           (gid)
+#define XIDINO_UID(tag, uid, xid)      (uid)
+#define XIDINO_GID(tag, gid, xid)      (gid)
 
 #endif
 
 #define MAX_UID                0xFFFFFFFF
 #define MAX_GID                0x0000FFFF
 
-#define INOXID_XID(uid, gid, xid)      (((gid) >> 16) & 0xFFFF)
-
-#define XIDINO_UID(uid, xid)           (uid)
-#define XIDINO_GID(gid, xid)           (((gid) & 0xFFFF) | ((xid) << 16))
+#define INOXID_XID(tag, uid, gid, xid) \
+       ((tag) ? (((gid) >> 16) & 0xFFFF) : 0)
 
+#define XIDINO_UID(tag, uid, xid)      (uid)
+#define XIDINO_GID(tag, gid, xid)      \
+       ((tag) ? (((gid) & 0xFFFF) | ((xid) << 16)) : (gid))
 
 #endif
 
 
-#ifdef CONFIG_INOXID_GID24
+#ifdef CONFIG_INOXID_UGID24
 
 #define MAX_UID                0x00FFFFFF
 #define MAX_GID                0x00FFFFFF
 
-#define INOXID_XID(uid, gid, xid)      ((((uid) >> 16) & 0xFF00) | (((gid) >> 24) & 0xFF))
+#define INOXID_XID(tag, uid, gid, xid) \
+       ((tag) ? ((((uid) >> 16) & 0xFF00) | (((gid) >> 24) & 0xFF)) : 0)
 
-#define XIDINO_UID(uid, xid)           (((uid) & 0xFFFFFF) | (((xid) & 0xFF00) << 16))
-#define XIDINO_GID(gid, xid)           (((gid) & 0xFFFFFF) | (((xid) & 0x00FF) << 24))
+#define XIDINO_UID(tag, uid, xid)      \
+       ((tag) ? (((uid) & 0xFFFFFF) | (((xid) & 0xFF00) << 16)) : (uid))
+#define XIDINO_GID(tag, gid, xid)      \
+       ((tag) ? (((gid) & 0xFFFFFF) | (((xid) & 0x00FF) << 24)) : (gid))
 
 #endif
 
 
-#ifdef CONFIG_INOXID_GID32
+#ifdef CONFIG_INOXID_UID16
+
+#define MAX_UID                0x0000FFFF
+#define MAX_GID                0xFFFFFFFF
+
+#define INOXID_XID(tag, uid, gid, xid) \
+       ((tag) ? ((uid) >> 16) & 0xFFFF) : 0)
+
+#define XIDINO_UID(tag, uid, xid)      \
+       ((tag) ? (((uid) & 0xFFFF) | ((xid) << 16)) : (uid))
+#define XIDINO_GID(tag, gid, xid)      (gid)
+
+#endif
+
+
+#ifdef CONFIG_INOXID_INTERN
 
 #define MAX_UID                0xFFFFFFFF
 #define MAX_GID                0xFFFFFFFF
 
-#define INOXID_XID(uid, gid, xid)      (xid)
+#define INOXID_XID(tag, uid, gid, xid) \
+       ((tag) ? (xid) : 0)
 
-#define XIDINO_UID(uid, xid)           (uid)
-#define XIDINO_GID(gid, xid)           (gid)
+#define XIDINO_UID(tag, uid, xid)      (uid)
+#define XIDINO_GID(tag, gid, xid)      (gid)
 
 #endif
 
 #define MAX_UID                0xFFFFFFFF
 #define MAX_GID                0xFFFFFFFF
 
-#define INOXID_XID(uid, gid, xid)      (0)
+#define INOXID_XID(tag, uid, gid, xid) (0)
 
-#define XIDINO_UID(uid, xid)           (uid)
-#define XIDINO_GID(gid, xid)           (gid)
+#define XIDINO_UID(tag, uid, xid)      (uid)
+#define XIDINO_GID(tag, gid, xid)      (gid)
 
 #endif
 
 
-#define INOXID_UID(uid, gid)           ((uid) & MAX_UID)
-#define INOXID_GID(uid, gid)           ((gid) & MAX_GID)
+#define INOXID_UID(tag, uid, gid)      \
+       ((tag) ? ((uid) & MAX_UID) : (uid))
+#define INOXID_GID(tag, uid, gid)      \
+       ((tag) ? ((gid) & MAX_GID) : (gid))
+
 
 static inline uid_t vx_map_uid(uid_t uid)
 {
@@ -85,10 +114,10 @@ static inline gid_t vx_map_gid(gid_t gid)
 }
 
 
-#ifdef CONFIG_VSERVER_LEGACY           
+#ifdef CONFIG_VSERVER_LEGACY
 #define FIOC_GETXID    _IOR('x', 1, long)
 #define FIOC_SETXID    _IOW('x', 2, long)
 #define FIOC_SETXIDJ   _IOW('x', 3, long)
 #endif
 
-#endif /* _LINUX_XID_H_ */
+#endif /* _VX_XID_H */