vshost-util-vserver

Build script and sources for util-vserver.
git clone https://ccx.te2000.cz/git/vshost-util-vserver
Log | Files | Refs

vsched.c (10449B)


      1 // $Id$    --*- c -*--
      2 
      3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
      4 // Copyright (C) 2006 Daniel Hokka Zakrisson <daniel@hozac.com>
      5 //  
      6 // This program is free software; you can redistribute it and/or modify
      7 // it under the terms of the GNU General Public License as published by
      8 // the Free Software Foundation; version 2 of the License.
      9 //  
     10 // This program is distributed in the hope that it will be useful,
     11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13 // GNU General Public License for more details.
     14 //  
     15 // You should have received a copy of the GNU General Public License
     16 // along with this program; if not, write to the Free Software
     17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
     18 
     19 
     20 #ifdef HAVE_CONFIG_H
     21 #  include <config.h>
     22 #endif
     23 
     24 #include "util.h"
     25 #include "vserver.h"
     26 
     27 #include <errno.h>
     28 #include <unistd.h>
     29 #include <getopt.h>
     30 #include <libgen.h>
     31 #include <dirent.h>
     32 #include <fcntl.h>
     33 #include <sys/stat.h>
     34 #include <stddef.h>
     35 
     36 #define ENSC_WRAPPERS_PREFIX	"vsched: "
     37 #define ENSC_WRAPPERS_VSERVER	1
     38 #define ENSC_WRAPPERS_UNISTD	1
     39 #define ENSC_WRAPPERS_FCNTL	1
     40 #define ENSC_WRAPPERS_DIRENT	1
     41 #define ENSC_WRAPPERS_STAT	1
     42 #include <wrappers.h>
     43 
     44 #define CMD_HELP		0x1000
     45 #define CMD_VERSION		0x1001
     46 #define CMD_XID			0x4000
     47 #define CMD_FRATE		0x4001
     48 #define CMD_INTERVAL		0x4002
     49 #define CMD_TOKENS		0x4003
     50 #define CMD_TOK_MIN		0x4004
     51 #define CMD_TOK_MAX		0x4005
     52 #define CMD_CPU_MASK		0x4006
     53 #define CMD_PRIO_BIAS		0x4007
     54 #define CMD_FRATE2		0x4008
     55 #define CMD_INTERVAL2		0x4009
     56 #define CMD_CPUID		0x400a
     57 #define CMD_BUCKETID		0x400b
     58 #define CMD_FORCE		0x400c
     59 #define CMD_IDLE_TIME		0x400d
     60 #define CMD_DIR			0x400e
     61 #define CMD_MISSING		0x400f
     62 
     63 int			wrapper_exit_code = 255;
     64 
     65 struct option const
     66 CMDLINE_OPTIONS[] = {
     67   { "help",     no_argument,  0, CMD_HELP },
     68   { "version",  no_argument,  0, CMD_VERSION },
     69   { "ctx",           required_argument, 0, CMD_XID },
     70   { "xid",           required_argument, 0, CMD_XID },
     71   { "fill-rate",     required_argument, 0, CMD_FRATE },
     72   { "interval",      required_argument, 0, CMD_INTERVAL },
     73   { "tokens",        required_argument, 0, CMD_TOKENS },
     74   { "tokens_min",    required_argument, 0, CMD_TOK_MIN },
     75   { "tokens-min",    required_argument, 0, CMD_TOK_MIN },
     76   { "tokens_max",    required_argument, 0, CMD_TOK_MAX },
     77   { "tokens-max",    required_argument, 0, CMD_TOK_MAX },
     78   { "prio_bias",     required_argument, 0, CMD_PRIO_BIAS },
     79   { "prio-bias",     required_argument, 0, CMD_PRIO_BIAS },
     80   { "priority_bias", required_argument, 0, CMD_PRIO_BIAS },
     81   { "priority-bias", required_argument, 0, CMD_PRIO_BIAS },
     82   { "cpu_mask",      required_argument, 0, CMD_CPU_MASK },
     83   { "fill-rate2",    required_argument, 0, CMD_FRATE2 },
     84   { "interval2",     required_argument, 0, CMD_INTERVAL2 },
     85   { "cpu-id",        required_argument, 0, CMD_CPUID },
     86   { "bucket-id",     required_argument, 0, CMD_BUCKETID },
     87   { "force",         no_argument,       0, CMD_FORCE },
     88   { "idle-time",     no_argument,       0, CMD_IDLE_TIME },
     89   { "dir",           required_argument, 0, CMD_DIR },
     90   { "missingok",     no_argument,       0, CMD_MISSING },
     91   {0,0,0,0}
     92 };
     93 
     94 struct sched_opt {
     95   const char * const	name;
     96   uint_least32_t	mask;
     97   size_t		offset;
     98 };
     99 #define FOPT(NAME,MASK,FIELD)	{ #NAME, MASK, offsetof(struct vc_set_sched, FIELD) }
    100 static struct sched_opt FILE_OPTIONS[] = {
    101   FOPT(fill-rate,	VC_VXSM_FILL_RATE,			fill_rate),
    102   FOPT(interval,	VC_VXSM_INTERVAL,			interval),
    103   FOPT(tokens,		VC_VXSM_TOKENS,				tokens),
    104   FOPT(tokens-min,	VC_VXSM_TOKENS_MIN,			tokens_min),
    105   FOPT(tokens-max,	VC_VXSM_TOKENS_MAX,			tokens_max),
    106   FOPT(prio-bias,	VC_VXSM_PRIO_BIAS,			priority_bias),
    107   FOPT(priority-bias,	VC_VXSM_PRIO_BIAS,			priority_bias),
    108   FOPT(fill-rate2,	VC_VXSM_FILL_RATE2|VC_VXSM_IDLE_TIME,	fill_rate2),
    109   FOPT(interval2,	VC_VXSM_INTERVAL2|VC_VXSM_IDLE_TIME,	interval2),
    110   FOPT(cpu-id,		VC_VXSM_CPU_ID,				cpu_id),
    111   FOPT(bucket-id,	VC_VXSM_BUCKET_ID,			bucket_id),
    112   FOPT(idle-time,	VC_VXSM_IDLE_TIME,			set_mask),
    113   {0,0,0}
    114 };
    115 
    116 static void
    117 showHelp(int fd, char const *cmd, int res)
    118 {
    119   VSERVER_DECLARE_CMD(cmd);
    120 
    121   WRITE_MSG(fd, "Usage:\n  ");
    122   WRITE_STR(fd, cmd);
    123   WRITE_MSG(fd,
    124 	    " [--xid <xid>] <sched options>* [--dir <dir>] [--] [<command> <args>*]\n"
    125 	    "\n"
    126 	    "Options:\n"
    127 	    "    --fill-rate <rate>\n"
    128 	    "    --interval <interval>\n"
    129 	    "    --tokens <tokens>\n"
    130 	    "    --tokens-min <tokens>\n"
    131 	    "    --tokens-max <tokens>\n"
    132 	    "    --prio-bias <bias>\n"
    133 	    "    --fill-rate2 <rate>\n"
    134 	    "    --interval2 <interval>\n"
    135 	    "    --cpu-id <CPU id>\n"
    136 	    "    --bucket-id <bucket id>\n"
    137 	    "    --idle-time    ...  set the idle time flag; this is required for\n"
    138 	    "                        all updates to the scheduler to keep it enabled\n"
    139 	    "    --force        ...  force update of all per-CPU schedulers now\n"
    140 	    "    --dir <dir>    ...  read settings from <dir>\n"
    141 	    "    --missingok    ...  do not fail when <dir> does not exist\n"
    142 	    "\nPlease report bugs to " PACKAGE_BUGREPORT "\n");
    143 
    144   exit(res);
    145 }
    146 
    147 static void
    148 showVersion()
    149 {
    150   WRITE_MSG(1,
    151 	    "vsched " VERSION " -- modifies scheduling parameters\n"
    152 	    "This program is part of " PACKAGE_STRING "\n\n"
    153 	    "Copyright (C) 2003,2004 Enrico Scholz\n"
    154 	    "Copyright (C) 2006 Daniel Hokka Zakrisson\n"
    155 	    VERSION_COPYRIGHT_DISCLAIMER);
    156   exit(0);
    157 }
    158 
    159 static void do_dir_entry(struct vc_set_sched *sched, const char *name)
    160 {
    161   struct sched_opt *opt;
    162 
    163   for (opt = FILE_OPTIONS; opt->name != 0; opt++) {
    164     if (strcmp(name, opt->name) == 0)
    165       break;
    166   }
    167   if (opt->name == 0)
    168     return;
    169 
    170   if (opt->offset != offsetof(struct vc_set_sched, set_mask)) {
    171     int fd;
    172     char buf[128], *newline;
    173     signed long val;
    174     ssize_t len;
    175 
    176     fd = Eopen(name, O_RDONLY, 0);
    177     len = Eread(fd, buf, sizeof(buf)-1);
    178     Eclose(fd);
    179     buf[len] = '\0';
    180     if ((newline=strchr(buf, '\n')) != NULL)
    181       *newline = '\0';
    182 
    183     if (!isNumber(buf, &val, true)) {
    184       WRITE_MSG(2, ENSC_WRAPPERS_PREFIX);
    185       WRITE_STR(2, name);
    186       WRITE_MSG(2, ": is not an integer\n");
    187       exit(1);
    188     }
    189 
    190     *(int_least32_t *)(((char *)sched)+opt->offset) = (int_least32_t) val;
    191   }
    192 
    193   sched->set_mask |= opt->mask;
    194 }
    195 
    196 static void do_dir(xid_t xid, struct vc_set_sched *sched, const char *dir, int missing_ok, int per_cpu)
    197 {
    198   DIR			*dp;
    199   struct dirent		*de;
    200   int			cur_fd = Eopen(".", O_RDONLY, 0);
    201   struct stat		st;
    202 
    203   if (chdir(dir)!=-1) {
    204     dp = Eopendir(".");
    205     while ((de = Ereaddir(dp)) != NULL) {
    206       if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
    207 	continue;
    208       Estat(de->d_name, &st);
    209       if (S_ISDIR(st.st_mode))
    210 	continue;
    211       do_dir_entry(sched, de->d_name);
    212     }
    213 
    214     /* set the values now */
    215     if (vc_set_sched(xid, sched) == -1) {
    216       perror(ENSC_WRAPPERS_PREFIX "vc_set_sched()");
    217       exit(1);
    218     }
    219 
    220     if (!per_cpu) {
    221       struct vc_set_sched per_cpu_sched;
    222 
    223       rewinddir(dp);
    224       while ((de = Ereaddir(dp)) != NULL) {
    225 	if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
    226 	  continue;
    227 	Estat(de->d_name, &st);
    228 	if (S_ISDIR(st.st_mode)) {
    229 	  per_cpu_sched.set_mask = sched->set_mask & (VC_VXSM_IDLE_TIME|VC_VXSM_FORCE);
    230 	  do_dir(xid, &per_cpu_sched, de->d_name, 0, 1);
    231 	}
    232       }
    233     }
    234 
    235     Eclosedir(dp);
    236   }
    237   else if (!missing_ok) {
    238     perror(ENSC_WRAPPERS_PREFIX "chdir()");
    239     exit(wrapper_exit_code);
    240   }
    241 
    242   Efchdir(cur_fd);
    243 }
    244 
    245 #define SETVAL(ATTR,MASK) \
    246   if (!isNumber(optarg, &tmp, false)) { \
    247     WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "non-integer value specified for '--" #ATTR "'\n"); \
    248     exit(wrapper_exit_code); \
    249   } \
    250   else { \
    251     sched.ATTR      = tmp; \
    252     sched.set_mask |= MASK; \
    253   }
    254 
    255 int main(int argc, char *argv[])
    256 {
    257   xid_t			xid   = VC_NOCTX;
    258   signed long		tmp;
    259   struct vc_set_sched	sched = {
    260     .set_mask = 0
    261   };
    262   const char		*dir = NULL;
    263   int			missing_ok = 0;
    264   
    265   while (1) {
    266     int		c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0);
    267     if (c==-1) break;
    268 
    269     switch (c) {
    270       case CMD_HELP	:  showHelp(1, argv[0], 0);
    271       case CMD_VERSION	:  showVersion();
    272       case CMD_XID	:  xid = Evc_xidopt2xid(optarg,true);         break;
    273       case CMD_FRATE	:  SETVAL(fill_rate,     VC_VXSM_FILL_RATE);  break;
    274       case CMD_INTERVAL	:  SETVAL(interval,      VC_VXSM_INTERVAL);   break;
    275       case CMD_TOKENS	:  SETVAL(tokens,        VC_VXSM_TOKENS);     break;
    276       case CMD_TOK_MIN	:  SETVAL(tokens_min,    VC_VXSM_TOKENS_MIN); break;
    277       case CMD_TOK_MAX	:  SETVAL(tokens_max,    VC_VXSM_TOKENS_MAX); break;
    278       case CMD_PRIO_BIAS:  SETVAL(priority_bias, VC_VXSM_PRIO_BIAS);  break;
    279       case CMD_CPU_MASK	:
    280 	WRITE_MSG(2, "vsched: WARNING: the '--cpu_mask' parameter is deprecated and will not have any effect\n");
    281 	break;
    282       case CMD_FRATE2	:  SETVAL(fill_rate2,    VC_VXSM_FILL_RATE2); break;
    283       case CMD_INTERVAL2:  SETVAL(interval2,     VC_VXSM_INTERVAL2);  break;
    284       case CMD_CPUID	:  SETVAL(cpu_id,        VC_VXSM_CPU_ID);     break;
    285       case CMD_BUCKETID	:  SETVAL(bucket_id,     VC_VXSM_BUCKET_ID);  break;
    286       case CMD_DIR	:  dir = optarg;                              break;
    287       case CMD_MISSING	:  missing_ok = 1;                            break;
    288       case CMD_FORCE	:  sched.set_mask |= VC_VXSM_FORCE;           break;
    289       case CMD_IDLE_TIME:  sched.set_mask |= VC_VXSM_IDLE_TIME;       break;
    290       default		:
    291 	WRITE_MSG(2, "Try '");
    292 	WRITE_STR(2, argv[0]);
    293 	WRITE_MSG(2, " --help' for more information.\n");
    294 	return EXIT_FAILURE;
    295 	break;
    296     }
    297   }
    298 
    299   if (xid==VC_NOCTX && optind==argc) {
    300     WRITE_MSG(2, "Without a program, '--xid' must be used; try '--help' for more information\n");
    301     exit(wrapper_exit_code);
    302   }
    303 
    304   if (sched.set_mask==0 && dir==NULL && optind==argc) {
    305     WRITE_MSG(2, "Neither an option nor a program was specified; try '--help' for more information\n");
    306     exit(wrapper_exit_code);
    307   }
    308 
    309   if (xid==VC_NOCTX)
    310     xid = Evc_get_task_xid(0);
    311 
    312   if (dir) {
    313     do_dir(xid, &sched, dir, missing_ok, 0);
    314   }
    315   else {
    316     if (sched.set_mask!=0 && sched.set_mask!=VC_VXSM_FORCE &&
    317         vc_set_sched(xid, &sched)==-1) {
    318       perror("vc_set_sched()");
    319       exit(255);
    320     }
    321   }
    322 
    323   if (optind<argc)
    324     EexecvpD(argv[optind],argv+optind);
    325 
    326   return EXIT_SUCCESS;
    327 }