#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
#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 *);
#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__
#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;
};
#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
#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;
#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
+/* _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);
}
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" };
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;
}
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__ */
#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;
uint32_t mask;
};
-struct vcmd_ctx_iattr_v1 {
+struct vcmd_ctx_iattr_v1 {
const char __user *name;
uint32_t xid;
uint32_t flags;
#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
#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 *);
/* 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 {
/* of the context */
#define VX_INFO_NAMESPACE 128 /* save private namespace */
-
+
#define NB_S_CONTEXT 16
#define NB_IPV4ROOT 16
+/* _VX_LIMIT_H defined below */
+
#if defined(__KERNEL__) && defined(_VX_INFO_DEF_)
#include <asm/atomic.h>
/* 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)
);
}
#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;
#endif /* _VX_LIMIT_H */
#endif
+
+
#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];
};
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 *);
#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 */
};
-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;
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__ */
#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__
#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__
#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;
};
#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;
};
+/* _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;
}
/* 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;
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"
{
#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 */
/* 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 */
/*
- 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|
-------+-------+-------+-------+-------+-------+-------+ +-------+-------+
*/
#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 */
#include <linux/errno.h>
-#define ENOTSUP -EOPNOTSUPP
#else /* __KERNEL__ */
#define __user
-#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)
{
}
-#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 */