From 6bbeb3e9837789f7813f1a38d39ac2e4df3a570b Mon Sep 17 00:00:00 2001 From: Steve Muir Date: Thu, 9 Mar 2006 22:35:30 +0000 Subject: [PATCH] Remove any notions of rspecs from util-vserver --- lib/planetlab.c | 71 +++++++++++++++++++------------------ lib/planetlab.h | 18 ++++------ python/vserverimpl.c | 84 +++++++++++++++----------------------------- src/vsh.c | 36 +++++++++++++++---- 4 files changed, 101 insertions(+), 108 deletions(-) diff --git a/lib/planetlab.c b/lib/planetlab.c index 879cb5d..fbed1eb 100644 --- a/lib/planetlab.c +++ b/lib/planetlab.c @@ -44,15 +44,15 @@ POSSIBILITY OF SUCH DAMAGE. #include "vserver.h" static int -create_context(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec) +create_context(xid_t ctx, uint32_t flags, uint64_t bcaps) { struct vc_ctx_caps vc_caps; - struct vc_ctx_flags vc_flags; - struct vc_rlimit vc_rlimit; /* * Create context info - this sets the STATE_SETUP and STATE_INIT flags. * Don't ever clear the STATE_INIT flag, that makes us the init task. + * + * XXX - the kernel code allows initial flags to be passed as an arg. */ if (vc_ctx_create(ctx) == VC_NOCTX) return -1; @@ -65,43 +65,44 @@ create_context(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec) if (vc_set_ccaps(ctx, &vc_caps)) return -1; - /* set scheduler parameters */ - if (pl_setsched(ctx, rspec->cpu_share, rspec->cpu_sched_flags)) - return -1; + /* set default scheduling parameters */ + pl_setsched(ctx, 32, 0); - /* set resource limits */ - vc_rlimit.min = VC_LIM_KEEP; - vc_rlimit.soft = VC_LIM_KEEP; - vc_rlimit.hard = rspec->mem_limit; - if (vc_set_rlimit(ctx, RLIMIT_RSS, &vc_rlimit)) - return -1; + return 0; +} - /* assume min and soft unchanged by set_rlimit */ - vc_rlimit.hard = rspec->task_limit; - if (vc_set_rlimit(ctx, RLIMIT_NPROC, &vc_rlimit)) - return -1; +int +pl_setup_done(xid_t ctx) +{ + struct vc_ctx_flags vc_flags; - /* set flags, unset SETUP flag - this allows other processes to migrate */ - vc_flags.mask = VC_VXF_STATE_SETUP | VC_VXF_SCHED_FLAGS; - flags = 0; /* XXX - ignore flags parameter */ - vc_flags.flagword = flags | rspec->cpu_sched_flags; /* SETUP cleared */ + /* unset SETUP flag - this allows other processes to migrate */ + vc_flags.mask = VC_VXF_STATE_SETUP; + vc_flags.flagword = 0; if (vc_set_cflags(ctx, &vc_flags)) return -1; return 0; } +#define RETRY_LIMIT 10 + int -pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec) +pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps) { + int retry_count = 0; + for (;;) { struct vc_ctx_flags vc_flags; if (vc_get_cflags(ctx, &vc_flags)) { + if (errno != ESRCH) + return -1; + /* context doesn't exist - create it */ - if (create_context(ctx, flags, bcaps, rspec)) + if (create_context(ctx, flags, bcaps)) { if (errno == EEXIST) /* another process beat us in a race */ @@ -113,13 +114,18 @@ pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec) } /* created context and migrated to it i.e., we're done */ - break; + return 1; } /* check the SETUP flag */ if (vc_flags.flagword & VC_VXF_STATE_SETUP) { /* context is still being setup - wait a while then retry */ + if (retry_count++ >= RETRY_LIMIT) + { + errno = EBUSY; + return -1; + } sleep(1); continue; } @@ -144,18 +150,12 @@ do \ } \ while (0) - int pl_setsched(xid_t ctx, uint32_t cpu_share, uint32_t cpu_sched_flags) { struct vc_set_sched vc_sched; struct vc_ctx_flags vc_flags; - - if (cpu_sched_flags & ~VC_VXF_SCHED_FLAGS) - { - errno = EINVAL; - return -1; - } + uint32_t new_flags; vc_sched.set_mask = (VC_VXSM_FILL_RATE | VC_VXSM_INTERVAL | VC_VXSM_TOKENS | VC_VXSM_TOKENS_MIN | VC_VXSM_TOKENS_MAX); @@ -170,11 +170,14 @@ pl_setsched(xid_t ctx, uint32_t cpu_share, uint32_t cpu_sched_flags) /* get current flag values */ VC_SYSCALL(vc_get_cflags(ctx, &vc_flags)); - /* the only flag which ever changes is the SCHED_SHARE bit */ - if ((vc_flags.flagword ^ cpu_sched_flags) & VC_VXF_SCHED_SHARE) + /* guaranteed CPU corresponds to SCHED_SHARE flag being cleared */ + new_flags = (cpu_sched_flags & VS_SCHED_CPU_GUARANTEED + ? 0 + : VC_VXF_SCHED_SHARE); + if ((vc_flags.flagword & VC_VXF_SCHED_SHARE) != new_flags) { - vc_flags.mask = VC_VXF_SCHED_SHARE; - vc_flags.flagword = cpu_sched_flags & VC_VXF_SCHED_FLAGS; + vc_flags.mask = VC_VXF_SCHED_FLAGS; + vc_flags.flagword = new_flags | VC_VXF_SCHED_HARD; VC_SYSCALL(vc_set_cflags(ctx, &vc_flags)); } diff --git a/lib/planetlab.h b/lib/planetlab.h index 07bbbdb..e4d6ae4 100644 --- a/lib/planetlab.h +++ b/lib/planetlab.h @@ -34,22 +34,18 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef _LIB_PLANETLAB_H_ #define _LIB_PLANETLAB_H_ -/* - * context create - */ -typedef struct { - uint32_t cpu_share; - uint32_t cpu_sched_flags; - uint64_t mem_limit; - uint64_t task_limit; -} rspec_t; - #define VC_VXF_SCHED_FLAGS (VC_VXF_SCHED_HARD | VC_VXF_SCHED_SHARE) int -pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps, const rspec_t *rspec); +pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps); + +int +pl_setup_done(xid_t ctx); int pl_setsched(xid_t ctx, uint32_t cpu_share, uint32_t cpu_sched_flags); +/* scheduler flags */ +#define VS_SCHED_CPU_GUARANTEED 1 + #endif diff --git a/python/vserverimpl.c b/python/vserverimpl.c index fbb94f5..d5f018d 100644 --- a/python/vserverimpl.c +++ b/python/vserverimpl.c @@ -46,69 +46,35 @@ POSSIBILITY OF SUCH DAMAGE. #define NONE ({ Py_INCREF(Py_None); Py_None; }) -static int -get_rspec(PyObject *resources, rspec_t *rspec) -{ - int result = -1; - PyObject *cpu_share; - PyObject *sched_flags = NULL; - - if (!PyMapping_Check(resources)) - { - PyErr_SetString(PyExc_TypeError, "invalid rspec"); - return -1; - } - - /* get CPU share */ - if (!(cpu_share = PyMapping_GetItemString(resources, "nm_cpu_share"))) - return -1; - if (!PyInt_Check(cpu_share)) - { - PyErr_SetString(PyExc_TypeError, "nm_cpu_share not an integer"); - goto out; - } - rspec->cpu_share = PyInt_AS_LONG(cpu_share); - - /* check whether this share should be guaranteed */ - rspec->cpu_sched_flags = VC_VXF_SCHED_FLAGS; - result = 0; - if ((sched_flags = PyMapping_GetItemString(resources, "nm_sched_flags"))) - { - const char *flagstr; - - if (!(flagstr = PyString_AsString(sched_flags))) - result = -1; - else if (!strcmp(flagstr, "guaranteed")) - rspec->cpu_sched_flags &= ~VC_VXF_SCHED_SHARE; - Py_DECREF(sched_flags); - } - else - /* not an error if nm_sched_flags is missing */ - PyErr_Clear(); - - out: - Py_DECREF(cpu_share); - - return result; -} - /* * context create */ static PyObject * vserver_chcontext(PyObject *self, PyObject *args) { + int result; xid_t ctx; uint32_t flags = 0; uint32_t bcaps = ~vc_get_insecurebcaps(); - rspec_t rspec = { 32, VC_VXF_SCHED_FLAGS, -1, -1 }; - PyObject *resources; - if (!PyArg_ParseTuple(args, "IO|K", &ctx, &resources, &flags) || - get_rspec(resources, &rspec)) + if (!PyArg_ParseTuple(args, "I|K", &ctx, &flags)) + return NULL; + + if ((result = pl_chcontext(ctx, flags, bcaps)) < 0) + return PyErr_SetFromErrno(PyExc_OSError); + + return PyBool_FromLong(result); +} + +static PyObject * +vserver_setup_done(PyObject *self, PyObject *args) +{ + xid_t ctx; + + if (!PyArg_ParseTuple(args, "I", &ctx)) return NULL; - if (pl_chcontext(ctx, flags, bcaps, &rspec)) + if (pl_setup_done(ctx) < 0) return PyErr_SetFromErrno(PyExc_OSError); return NONE; @@ -167,15 +133,14 @@ static PyObject * vserver_setsched(PyObject *self, PyObject *args) { xid_t ctx; - rspec_t rspec = { 32, VC_VXF_SCHED_FLAGS, -1, -1 }; - PyObject *resources; + uint32_t cpu_share; + uint32_t cpu_sched_flags = VC_VXF_SCHED_FLAGS; - if (!PyArg_ParseTuple(args, "IO", &ctx, &resources) || - get_rspec(resources, &rspec)) + if (!PyArg_ParseTuple(args, "II|I", &ctx, &cpu_share, &cpu_sched_flags)) return NULL; /* ESRCH indicates that there are no processes in the context */ - if (pl_setsched(ctx, rspec.cpu_share, rspec.cpu_sched_flags) && + if (pl_setsched(ctx, cpu_share, cpu_sched_flags) && errno != ESRCH) return PyErr_SetFromErrno(PyExc_OSError); @@ -283,6 +248,8 @@ vserver_killall(PyObject *self, PyObject *args) static PyMethodDef methods[] = { { "chcontext", vserver_chcontext, METH_VARARGS, "chcontext to vserver with provided flags" }, + { "setup_done", vserver_setup_done, METH_VARARGS, + "Release vserver setup lock" }, { "setsched", vserver_setsched, METH_VARARGS, "Change vserver scheduling attributes for given vserver context" }, { "setdlimit", vserver_set_dlimit, METH_VARARGS, @@ -316,4 +283,9 @@ initvserverimpl(void) /* export limit-related constants */ PyModule_AddIntConstant(mod, "DLIMIT_KEEP", (int)CDLIM_KEEP); PyModule_AddIntConstant(mod, "DLIMIT_INF", (int)CDLIM_INFINITY); + + /* scheduler flags */ + PyModule_AddIntConstant(mod, + "VS_SCHED_CPU_GUARANTEED", + VS_SCHED_CPU_GUARANTEED); } diff --git a/src/vsh.c b/src/vsh.c index 5908b20..7d28bf4 100644 --- a/src/vsh.c +++ b/src/vsh.c @@ -281,7 +281,7 @@ static int sandbox_processes(xid_t ctx, char *context) exit(1); } #else - rspec_t rspec; + int ctx_is_new; unsigned long long cpu = VC_LIM_KEEP; unsigned long long mem = VC_LIM_KEEP; unsigned long long task = VC_LIM_KEEP; @@ -304,16 +304,38 @@ static int sandbox_processes(xid_t ctx, char *context) (void) (sandbox_chroot(ctx)); - rspec.cpu_share = cpu; - rspec.cpu_sched_flags = (VC_VXF_SCHED_HARD | - (cpuguaranteed ? 0 : VC_VXF_SCHED_SHARE)); - rspec.mem_limit = mem; - rspec.task_limit = task; - if (pl_chcontext(ctx, 0, ~vc_get_insecurebcaps(), &rspec)) + if ((ctx_is_new = pl_chcontext(ctx, 0, ~vc_get_insecurebcaps())) < 0) { PERROR("pl_chcontext(%u)", ctx); exit(1); } + if (ctx_is_new) + { + /* set resources */ + struct vc_rlimit limits; + + limits.min = VC_LIM_KEEP; + limits.soft = VC_LIM_KEEP; + limits.hard = mem; + if (vc_set_rlimit(ctx, RLIMIT_RSS, &limits)) + { + PERROR("pl_setrlimit(%u, RLIMIT_RSS)", ctx); + exit(1); + } + limits.hard = task; + if (vc_set_rlimit(ctx, RLIMIT_NPROC, &limits)) + { + PERROR("pl_setrlimit(%u, RLIMIT_NPROC)", ctx); + exit(1); + } + cpuguaranteed &= VS_SCHED_CPU_GUARANTEED; + if (pl_setsched(ctx, cpu, cpuguaranteed) < 0) + { + PERROR("pl_setsched(&u)", ctx); + exit(1); + } + pl_setup_done(ctx); + } #endif return 0; } -- 2.43.0