From 6471cae28b5b32ff2d425b3d103a4ceac7550125 Mon Sep 17 00:00:00 2001 From: Marc Fiuczynski Date: Thu, 10 May 2007 15:22:08 +0000 Subject: [PATCH] generalized setting and getting of vserver limits --- lib/planetlab.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++-- lib/planetlab.h | 35 +++++++- 2 files changed, 260 insertions(+), 8 deletions(-) diff --git a/lib/planetlab.c b/lib/planetlab.c index 4d85fb9..8bef6dc 100644 --- a/lib/planetlab.c +++ b/lib/planetlab.c @@ -31,20 +31,24 @@ POSSIBILITY OF SUCH DAMAGE. */ +#include +#include +#include #include #include -#include +#include #include +#include #include #include "config.h" -#include "planetlab.h" #include "sched_cmd.h" #include "virtual.h" #include "vserver.h" +#include "planetlab.h" static int -create_context(xid_t ctx, uint32_t flags, uint64_t bcaps) +create_context(xid_t ctx, uint32_t flags, uint64_t bcaps, struct sliver_resources *slr) { struct vc_ctx_caps vc_caps; @@ -65,8 +69,7 @@ create_context(xid_t ctx, uint32_t flags, uint64_t bcaps) if (vc_set_ccaps(ctx, &vc_caps)) return -1; - /* set default scheduling parameters */ - pl_setsched(ctx, 1, 0); + pl_set_limits(ctx, slr); return 0; } @@ -88,7 +91,7 @@ pl_setup_done(xid_t ctx) #define RETRY_LIMIT 10 int -pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps) +pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps, struct sliver_resources *slr) { int retry_count = 0; @@ -102,7 +105,7 @@ pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps) return -1; /* context doesn't exist - create it */ - if (create_context(ctx, flags, bcaps)) + if (create_context(ctx, flags, bcaps,slr)) { if (errno == EEXIST) /* another process beat us in a race */ @@ -183,3 +186,219 @@ pl_setsched(xid_t ctx, uint32_t cpu_share, uint32_t cpu_sched_flags) return 0; } + +struct pl_resources { + char *name; + unsigned long long *limit; +}; + +#define WHITESPACE(buffer,index,len) \ + while(isspace((int)buffer[index])) \ + if (index < len) index++; else goto out; + +#define VSERVERCONF "/etc/vservers/" +void +pl_get_limits(char *context, struct sliver_resources *slr) +{ + FILE *fb; + size_t len = strlen(VSERVERCONF) + strlen(context) + strlen(".conf") + NULLBYTE_SIZE; + char *conf = (char *)malloc(len); + struct pl_resources *r; + struct pl_resources sliver_list[] = { + {"CPULIMIT", &slr->vs_cpu}, + {"CPUSHARE", &slr->vs_cpu}, + {"CPUGUARANTEED", &slr->vs_cpuguaranteed}, + + {"TASKLIMIT", &slr->vs_nproc.hard}, /* backwards compatible */ + {"VS_NPROC_HARD", &slr->vs_nproc.hard}, + {"VS_NPROC_SOFT", &slr->vs_nproc.soft}, + {"VS_NPROC_MINIMUM", &slr->vs_nproc.min}, + + {"MEMLIMIT", &slr->vs_rss.hard}, /* backwards compatible */ + {"VS_RSS_HARD", &slr->vs_rss.hard}, + {"VS_RSS_SOFT", &slr->vs_rss.soft}, + {"VS_RSS_MINIMUM", &slr->vs_rss.min}, + + {"VS_AS_HARD", &slr->vs_as.hard}, + {"VS_AS_SOFT", &slr->vs_as.soft}, + {"VS_AS_MINIMUM", &slr->vs_as.min}, + + {"VS_OPENFD_HARD", &slr->vs_openfd.hard}, + {"VS_OPENFD_SOFT", &slr->vs_openfd.soft}, + {"VS_OPENFD_MINIMUM", &slr->vs_openfd.min}, + + {"VS_WHITELISTED", &slr->vs_whitelisted}, + {0,0} + }; + + sprintf(conf, "%s%s.conf", VSERVERCONF, context); + + slr->vs_cpu = VC_LIM_KEEP; + slr->vs_cpuguaranteed = 0; + + slr->vs_rss.hard = VC_LIM_KEEP; + slr->vs_rss.soft = VC_LIM_KEEP; + slr->vs_rss.min = VC_LIM_KEEP; + + slr->vs_as.hard = VC_LIM_KEEP; + slr->vs_as.soft = VC_LIM_KEEP; + slr->vs_as.min = VC_LIM_KEEP; + + + slr->vs_nproc.hard = VC_LIM_KEEP; + slr->vs_nproc.soft = VC_LIM_KEEP; + slr->vs_nproc.min = VC_LIM_KEEP; + + slr->vs_openfd.hard = VC_LIM_KEEP; + slr->vs_openfd.soft = VC_LIM_KEEP; + slr->vs_openfd.min = VC_LIM_KEEP; + + slr->vs_whitelisted = 1; + + /* open the conf file for reading */ + fb = fopen(conf,"r"); + if (fb != NULL) { + size_t index; + char *buffer = malloc(1000); + char *p; + + /* the conf file exist */ + while((p=fgets(buffer,1000-1,fb))!=NULL) { + index = 0; + len = strnlen(buffer,1000); + WHITESPACE(buffer,index,len); + if (buffer[index] == '#') + continue; + + for (r=&sliver_list[0]; r->name; r++) + if ((p=strstr(&buffer[index],r->name))!=NULL) { + /* adjust index into buffer */ + index+= (p-&buffer[index])+strlen(r->name); + + /* skip over whitespace */ + WHITESPACE(buffer,index,len); + + /* expecting to see = sign */ + if (buffer[index++]!='=') goto out; + + /* skip over whitespace */ + WHITESPACE(buffer,index,len); + + /* expecting to see a digit for number */ + if (!isdigit((int)buffer[index])) goto out; + + *r->limit = atoi(&buffer[index]); + if (0) /* for debugging only */ + fprintf(stderr,"pl_get_limits found %s=%ld\n", + r->name,*r->limit); + break; + } + } + out: + fclose(fb); + free(buffer); + } else { + fprintf(stderr,"cannot open %s\n",conf); + } + free(conf); +} + +void +pl_set_limits(xid_t ctx, struct sliver_resources *slr) +{ + struct rlimit olim; /* current limit values */ + struct rlimit nlim; /* new limit values */ + + if (slr != 0) { + /* set memory limits */ + getrlimit(RLIMIT_RSS,&olim); + if (0) /* for debugging only */ + fprintf(stderr,"rss cur = %ld, max = %ld, vs_rss min = %ld\n",olim.rlim_cur,olim.rlim_max,slr->vs_rss.min); + if ((slr->vs_rss.min != VC_LIM_KEEP) && (slr->vs_rss.min > olim.rlim_cur)) { + nlim.rlim_cur = slr->vs_rss.min; + if (slr->vs_rss.min > olim.rlim_max) { + nlim.rlim_max = slr->vs_rss.min; + } else { + nlim.rlim_max = olim.rlim_max; + } + setrlimit(RLIMIT_RSS, &nlim); + } + if (vc_set_rlimit(ctx, RLIMIT_RSS, &slr->vs_rss)) + { + PERROR("pl_setrlimit(%u, RLIMIT_RSS)", ctx); + exit(1); + } + + /* set address space limits */ + getrlimit(RLIMIT_AS,&olim); + if (0) /* for debugging only */ + fprintf(stderr,"as cur = %ld, max = %ld, vs_as min = %ld\n",olim.rlim_cur,olim.rlim_max,slr->vs_as.min); + if ((slr->vs_as.min != VC_LIM_KEEP) && (slr->vs_as.min > olim.rlim_cur)) { + nlim.rlim_cur = slr->vs_as.min; + if (slr->vs_as.min > olim.rlim_max) { + nlim.rlim_max = slr->vs_as.min; + } else { + nlim.rlim_max = olim.rlim_max; + } + setrlimit(RLIMIT_AS, &nlim); + } + if (vc_set_rlimit(ctx, RLIMIT_AS, &slr->vs_as)) + { + PERROR("pl_setrlimit(%u, RLIMIT_AS)", ctx); + exit(1); + } + + /* set nrpoc limit */ + getrlimit(RLIMIT_NPROC,&olim); + if (0) /* for debugging only */ + fprintf(stderr,"nproc cur = %ld, max = %ld, vs_nproc min = %ld\n",olim.rlim_cur,olim.rlim_max,slr->vs_nproc.min); + if ((slr->vs_nproc.min != VC_LIM_KEEP) && (slr->vs_nproc.min > olim.rlim_cur)) { + nlim.rlim_cur = slr->vs_nproc.min; + if (slr->vs_nproc.min > olim.rlim_max) { + nlim.rlim_max = slr->vs_nproc.min; + } else { + nlim.rlim_max = olim.rlim_max; + } + setrlimit(RLIMIT_NPROC, &nlim); + } + if (vc_set_rlimit(ctx, RLIMIT_NPROC, &slr->vs_nproc)) + { + PERROR("pl_setrlimit(%u, RLIMIT_NPROC)", ctx); + exit(1); + } + + /* set openfd limit */ + getrlimit(RLIMIT_NOFILE,&olim); + if (0) /* for debugging only */ + fprintf(stderr,"NOFILE cur = %ld, max = %ld, vs_openfd min = %ld\n",olim.rlim_cur,olim.rlim_max,slr->vs_openfd.min); + if ((slr->vs_openfd.min != VC_LIM_KEEP) && (slr->vs_openfd.min > olim.rlim_cur)) { + nlim.rlim_cur = slr->vs_openfd.min; + if (slr->vs_openfd.min > olim.rlim_max) { + nlim.rlim_max = slr->vs_openfd.min; + } else { + nlim.rlim_max = olim.rlim_max; + } + setrlimit(RLIMIT_NOFILE, &nlim); + if (vc_set_rlimit(ctx, RLIMIT_NOFILE, &slr->vs_openfd)) + { + PERROR("pl_setrlimit(%u, RLIMIT_NOFILE)", ctx); + exit(1); + } + } +#ifndef VLIMIT_OPENFD +#warning VLIMIT_OPENFD should be defined from standard header +#define VLIMIT_OPENFD 17 +#endif + if (vc_set_rlimit(ctx, VLIMIT_OPENFD, &slr->vs_openfd)) + { + PERROR("pl_setrlimit(%u, VLIMIT_OPENFD)", ctx); + exit(1); + } + } + + if (pl_setsched(ctx, slr ? slr->vs_cpu : 1, slr ? (slr->vs_cpuguaranteed & VS_SCHED_CPU_GUARANTEED) : 0 ) < 0) + { + PERROR("pl_setsched(&u)", ctx); + exit(1); + } +} diff --git a/lib/planetlab.h b/lib/planetlab.h index e4d6ae4..fe346aa 100644 --- a/lib/planetlab.h +++ b/lib/planetlab.h @@ -36,8 +36,18 @@ POSSIBILITY OF SUCH DAMAGE. #define VC_VXF_SCHED_FLAGS (VC_VXF_SCHED_HARD | VC_VXF_SCHED_SHARE) +struct sliver_resources { + unsigned long long vs_cpu; + unsigned long long vs_cpuguaranteed; + struct vc_rlimit vs_rss; + struct vc_rlimit vs_as; + struct vc_rlimit vs_nproc; + struct vc_rlimit vs_openfd; + unsigned int vs_whitelisted; +}; + int -pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps); +pl_chcontext(xid_t ctx, uint32_t flags, uint64_t bcaps, struct sliver_resources *slr); int pl_setup_done(xid_t ctx); @@ -48,4 +58,27 @@ pl_setsched(xid_t ctx, uint32_t cpu_share, uint32_t cpu_sched_flags); /* scheduler flags */ #define VS_SCHED_CPU_GUARANTEED 1 +/* Null byte made explicit */ +#define NULLBYTE_SIZE 1 + +void pl_get_limits(char *, struct sliver_resources *); +void pl_set_limits(xid_t, struct sliver_resources *); + +static int +_PERROR(const char *format, char *file, int line, int _errno, ...) +{ + va_list ap; + + va_start(ap, _errno); + fprintf(stderr, "%s:%d: ", file, line); + vfprintf(stderr, format, ap); + if (_errno) + fprintf(stderr, ": %s (%d)", strerror(_errno), _errno); + fputs("\n", stderr); + fflush(stderr); + + return _errno; +} + +#define PERROR(format, args...) _PERROR(format, __FILE__, __LINE__, errno, ## args) #endif -- 2.43.0