diff options
author | brooks <brooks@FreeBSD.org> | 2008-07-25 19:58:14 +0000 |
---|---|---|
committer | brooks <brooks@FreeBSD.org> | 2008-07-25 19:58:14 +0000 |
commit | 8330af909ca941f7f0083761fdafe90a332e74de (patch) | |
tree | 62fd98a560aa70ad64312a864e5064cbfbef32da | |
parent | fb5f9ab862007c3c81c74a45467be20efed0b373 (diff) | |
download | FreeBSD-src-8330af909ca941f7f0083761fdafe90a332e74de.zip FreeBSD-src-8330af909ca941f7f0083761fdafe90a332e74de.tar.gz |
Add support for a new login capability, cpumask which allows login
sessions to be pinned to cpus by login class.
-rw-r--r-- | lib/libutil/login.conf.5 | 9 | ||||
-rw-r--r-- | lib/libutil/login_cap.h | 3 | ||||
-rw-r--r-- | lib/libutil/login_class.3 | 14 | ||||
-rw-r--r-- | lib/libutil/login_class.c | 107 |
4 files changed, 132 insertions, 1 deletions
diff --git a/lib/libutil/login.conf.5 b/lib/libutil/login.conf.5 index b4c96f2..863aa06 100644 --- a/lib/libutil/login.conf.5 +++ b/lib/libutil/login.conf.5 @@ -203,6 +203,15 @@ The maximum and current limits may be specified individually by appending a .It Sy "Name Type Notes Description .It "charset string Set $MM_CHARSET environment variable to the specified value. +.It "cpumask string List of cpus to bind the user to. +The syntax is the same as for the +.Fl l +argument of +.Xr cpuset 1 or the word +.Ql default . +If set to +.Ql default +no action is taken. .It "hushlogin bool false Same as having a ~/.hushlogin file. .It "ignorenologin bool false Login not prevented by nologin. .It "ftp-chroot bool false Limit FTP access with diff --git a/lib/libutil/login_cap.h b/lib/libutil/login_cap.h index a7cb4c6..c98e7fd 100644 --- a/lib/libutil/login_cap.h +++ b/lib/libutil/login_cap.h @@ -48,7 +48,8 @@ #define LOGIN_SETUSER 0x0040 /* set user (via setuid) */ #define LOGIN_SETENV 0x0080 /* set user environment */ #define LOGIN_SETMAC 0x0100 /* set user default MAC label */ -#define LOGIN_SETALL 0x01ff /* set everything */ +#define LOGIN_SETCPUMASK 0x0200 /* set user cpumask */ +#define LOGIN_SETALL 0x03ff /* set everything */ #define BI_AUTH "authorize" /* accepted authentication */ #define BI_REJECT "reject" /* rejected authentication */ diff --git a/lib/libutil/login_class.3 b/lib/libutil/login_class.3 index ca5b2ce..c91f9a9 100644 --- a/lib/libutil/login_class.3 +++ b/lib/libutil/login_class.3 @@ -155,6 +155,18 @@ capability "setenv=var1 val1,var2 val2..,varN valN". Set the MAC label for the current process to the label specified in system login class database. .Pp +.It LOGIN_SETCPUMASK +Create a new +.Xr cpuset 2 +and set the cpu affinity to the specified mask. +The string may contain a comma separated list of numbers and/or number +ranges as handled by the +.Xr cpuset 1 +utility or the case-insensitive string +.Ql default . +If the string is +.Ql default +no action will be taken. .It LOGIN_SETALL Enables all of the above settings. .El @@ -186,6 +198,8 @@ or resources, a message is reported to .Xr syslog 3 , with LOG_ERR priority and directed to the currently active facility. .Sh SEE ALSO +.Xr cpuset 1 , +.Xr cpuset 2 , .Xr setgid 2 , .Xr setlogin 2 , .Xr setuid 2 , diff --git a/lib/libutil/login_class.c b/lib/libutil/login_class.c index 39f114f..c18d46a 100644 --- a/lib/libutil/login_class.c +++ b/lib/libutil/login_class.c @@ -26,9 +26,11 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> +#include <sys/param.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/resource.h> +#include <sys/cpuset.h> #include <sys/mac.h> #include <sys/rtprio.h> #include <errno.h> @@ -239,6 +241,108 @@ setclassenvironment(login_cap_t *lc, const struct passwd * pwd, int paths) } +static int +list2cpuset(const char *list, cpuset_t *mask) +{ + enum { NONE, NUM, DASH } state; + int lastnum; + int curnum; + const char *l; + + state = NONE; + curnum = lastnum = 0; + for (l = list; *l != '\0';) { + if (isdigit(*l)) { + curnum = atoi(l); + if (curnum > CPU_SETSIZE) + errx(EXIT_FAILURE, + "Only %d cpus supported", CPU_SETSIZE); + while (isdigit(*l)) + l++; + switch (state) { + case NONE: + lastnum = curnum; + state = NUM; + break; + case DASH: + for (; lastnum <= curnum; lastnum++) + CPU_SET(lastnum, mask); + state = NONE; + break; + case NUM: + default: + return (0); + } + continue; + } + switch (*l) { + case ',': + switch (state) { + case NONE: + break; + case NUM: + CPU_SET(curnum, mask); + state = NONE; + break; + case DASH: + return (0); + break; + } + break; + case '-': + if (state != NUM) + return (0); + state = DASH; + break; + default: + return (0); + } + l++; + } + switch (state) { + case NONE: + break; + case NUM: + CPU_SET(curnum, mask); + break; + case DASH: + return (0); + } + return 1; +} + + +void +setclasscpumask(login_cap_t *lc) +{ + const char *maskstr; + cpuset_t maskset; + cpusetid_t setid; + + maskstr = login_getcapstr(lc, "cpumask", NULL, NULL); + CPU_ZERO(&maskset); + if (maskstr == NULL) + return; + if (strcasecmp("default", maskstr) == 0) + return; + if (!list2cpuset(maskstr, &maskset)) { + syslog(LOG_WARNING, + "list2cpuset(%s) invalid mask specification", maskstr); + return; + } + + if (cpuset(&setid) != 0) { + syslog(LOG_ERR, "cpuset(): %s", strerror(errno)); + return; + } + + if (cpuset_setaffinity(CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, + sizeof(maskset), &maskset) != 0) + syslog(LOG_ERR, "cpuset_setaffinity(%s): %s", maskstr, + strerror(errno)); +} + + /* * setclasscontext() * @@ -289,6 +393,9 @@ setlogincontext(login_cap_t *lc, const struct passwd *pwd, /* Set environment */ if (flags & LOGIN_SETENV) setclassenvironment(lc, pwd, 0); + /* Set cpu affinity */ + if (flags & LOGIN_SETCPUMASK) + setclasscpumask(lc); } return mymask; } |