From 9ceb769f44b3325c76fc7e51912422f4b74f733d Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Mon, 18 Oct 2004 16:08:07 +0000 Subject: [PATCH] updated git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@1729 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- util-vserver/kernel/context.h | 52 +++++++++---- util-vserver/kernel/cvirt.h | 146 ++++++++++++++++++++++++++++------- util-vserver/kernel/inode.h | 10 +-- util-vserver/kernel/legacy.h | 6 +- util-vserver/kernel/limit.h | 93 +++++++++++++++++------ util-vserver/kernel/namespace.h | 7 +- util-vserver/kernel/network.h | 42 +++++++---- util-vserver/kernel/sched.h | 163 ++++++++++++++++++++++++++++------------ util-vserver/kernel/signal.h | 10 ++- util-vserver/kernel/switch.h | 31 ++++---- util-vserver/kernel/xid.h | 77 +++++++++++++------ 11 files changed, 460 insertions(+), 177 deletions(-) diff --git a/util-vserver/kernel/context.h b/util-vserver/kernel/context.h index a51a035..94692ba 100644 --- a/util-vserver/kernel/context.h +++ b/util-vserver/kernel/context.h @@ -12,6 +12,7 @@ #include #include +#include #define _VX_INFO_DEF_ #include "cvirt.h" @@ -20,30 +21,43 @@ #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 diff --git a/util-vserver/kernel/cvirt.h b/util-vserver/kernel/cvirt.h index a8a242e..1f83546 100644 --- a/util-vserver/kernel/cvirt.h +++ b/util-vserver/kernel/cvirt.h @@ -1,44 +1,58 @@ +/* _VX_CVIRT_H defined below */ + #if defined(__KERNEL__) && defined(_VX_INFO_DEF_) #include #include #include #include +#include +#include #include /* 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__ */ diff --git a/util-vserver/kernel/inode.h b/util-vserver/kernel/inode.h index aa8852f..b8a5e78 100644 --- a/util-vserver/kernel/inode.h +++ b/util-vserver/kernel/inode.h @@ -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 *); diff --git a/util-vserver/kernel/legacy.h b/util-vserver/kernel/legacy.h index 1372c0f..877bfb8 100644 --- a/util-vserver/kernel/legacy.h +++ b/util-vserver/kernel/legacy.h @@ -13,12 +13,12 @@ /* 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 diff --git a/util-vserver/kernel/limit.h b/util-vserver/kernel/limit.h index 74e02cd..d9e1eea 100644 --- a/util-vserver/kernel/limit.h +++ b/util-vserver/kernel/limit.h @@ -1,3 +1,5 @@ +/* _VX_LIMIT_H defined below */ + #if defined(__KERNEL__) && defined(_VX_INFO_DEF_) #include @@ -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; limrlim[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; limrcur[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; limrcur[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 + + diff --git a/util-vserver/kernel/namespace.h b/util-vserver/kernel/namespace.h index 140fc79..08167a1 100644 --- a/util-vserver/kernel/namespace.h +++ b/util-vserver/kernel/namespace.h @@ -3,13 +3,13 @@ #include - + /* 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 *); diff --git a/util-vserver/kernel/network.h b/util-vserver/kernel/network.h index b3c39b0..e77866b 100644 --- a/util-vserver/kernel/network.h +++ b/util-vserver/kernel/network.h @@ -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 @@ -12,14 +12,17 @@ #include #include #include +#include #include #include 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; }; diff --git a/util-vserver/kernel/sched.h b/util-vserver/kernel/sched.h index 9db06e5..f7ac947 100644 --- a/util-vserver/kernel/sched.h +++ b/util-vserver/kernel/sched.h @@ -1,57 +1,97 @@ +/* _VX_SCHED_H defined below */ + #if defined(__KERNEL__) && defined(_VX_INFO_DEF_) #include #include +#include #include #include -#include + +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 */ diff --git a/util-vserver/kernel/signal.h b/util-vserver/kernel/signal.h index 3911127..7d0d430 100644 --- a/util-vserver/kernel/signal.h +++ b/util-vserver/kernel/signal.h @@ -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 */ diff --git a/util-vserver/kernel/switch.h b/util-vserver/kernel/switch.h index 5fef690..5855b05 100644 --- a/util-vserver/kernel/switch.h +++ b/util-vserver/kernel/switch.h @@ -12,11 +12,11 @@ /* - 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| @@ -25,22 +25,22 @@ 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 @@ -62,19 +62,21 @@ #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 -#define ENOTSUP -EOPNOTSUPP #else /* __KERNEL__ */ #define __user diff --git a/util-vserver/kernel/xid.h b/util-vserver/kernel/xid.h index ba52c25..23908fd 100644 --- a/util-vserver/kernel/xid.h +++ b/util-vserver/kernel/xid.h @@ -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 @@ -19,37 +25,57 @@ #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 @@ -59,16 +85,19 @@ #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 */ -- 1.8.1.5