cgroup-util.c revision 8c6db8336536916d0476ff8233e0abf40a2f6aab
/*-*- Mode: C; c-basic-offset: 8 -*-*/
/***
This file is part of systemd.
Copyright 2010 Lennart Poettering
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <libcgroup.h>
#include "cgroup-util.h"
#include "log.h"
#include "set.h"
#include "macro.h"
#include "util.h"
switch (error) {
case ECGROUPNOTCOMPILED:
case ECGROUPNOTMOUNTED:
case ECGROUPNOTEXIST:
case ECGROUPNOTCREATED:
return -ENOENT;
case ECGINVAL:
return -EINVAL;
case ECGROUPNOTALLOWED:
return -EPERM;
case ECGOTHER:
return -_errno;
}
return -EIO;
}
return NULL;
return NULL;
}
return cgroup;
}
Set *s;
int r, ret = 0;
/* This goes through the tasks list and kills them all. This
* is repeated until no further processes are added to the
* tasks list, to properly handle forking processes */
return -ENOMEM;
do {
done = true;
while (r == 0) {
goto next;
goto next;
/* If we haven't killed this process yet, kill
* it */
if (ret == 0)
}
killed = true;
done = false;
goto loop_exit;
next:
}
if (r == 0 || r == ECGEOF)
r = 0;
r = -ESRCH;
else
r = cg_translate_error(r, errno);
/* To avoid racing against processes which fork
* quicker than we can kill them we repeat this until
* no new pids need to be killed. */
} while (!done && r >= 0);
set_free(s);
if (ret < 0)
return ret;
if (r < 0)
return r;
return !!killed;
}
struct cgroup_file_info info;
bool killed = false;
while (r == 0) {
int k;
char *p;
goto next;
break;
}
free(p);
if (k < 0) {
if (ret == 0)
ret = k;
} else if (k > 0)
killed = true;
next:
}
if (ret == 0) {
if (r == 0 || r == ECGEOF)
else
}
return ret;
}
unsigned i;
/* This safely kills all processes; first it sends a SIGTERM,
* then checks 8 times after 50ms whether the group is
* now empty, and finally kills everything that is left with
* SIGKILL */
for (i = 0; i < 10; i++) {
int sig, r;
if (i <= 0)
else if (i >= 9)
else
sig = 0;
return r;
}
return 0;
}
int r, ret = 0;
return -ENOMEM;
do {
done = true;
while (r == 0) {
goto next;
if (ret == 0)
r = cg_translate_error(r, errno);
}
migrated = true;
done = false;
next:
}
if (r == 0 || r == ECGEOF)
r = 0;
r = -ESRCH;
else
r = cg_translate_error(r, errno);
} while (!done && r >= 0);
cgroup_free(&dest);
if (ret < 0)
return ret;
if (r < 0)
return r;
return !!migrated;
}
int cg_migrate_recursive(const char *controller, const char *from, const char *to, bool ignore_self) {
struct cgroup_file_info info;
bool migrated = false;
while (r == 0) {
int k;
char *p;
goto next;
break;
}
free(p);
if (k < 0) {
if (ret == 0)
ret = k;
} else if (k > 0)
migrated = true;
next:
}
if (ret == 0) {
if (r == 0 || r == ECGEOF)
r = !!migrated;
r = -ESRCH;
else
r = cg_translate_error(r, errno);
}
return ret;
}
char *mp;
int r;
return cg_translate_error(r, errno);
if (suffix)
else
return r < 0 ? -ENOMEM : 0;
}
char *fs;
int r;
return r;
return r;
}
int r;
return -ENOMEM;
if ((r = cgroup_delete_cgroup_ext(cg, CGFLAG_DELETE_RECURSIVE|CGFLAG_DELETE_IGNORE_MIGRATION)) != 0) {
r = cg_translate_error(r, errno);
goto finish;
}
r = 0;
cgroup_free(&cg);
return r;
}
int r;
return -ENOMEM;
r = cg_translate_error(r, errno);
goto finish;
}
r = 0;
cgroup_free(&cg);
return r;
}
int r;
return -ENOMEM;
if (pid == 0)
r = cg_translate_error(r, errno);
goto finish;
}
r = 0;
cgroup_free(&cg);
return r;
}
int r;
return -ENOMEM;
r = cg_translate_error(r, errno);
goto finish;
}
if (pid == 0)
r = cg_translate_error(r, errno);
goto finish;
}
r = 0;
cgroup_free(&cg);
return r;
}
int cg_set_group_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
char *fs;
int r;
return r;
return r;
}
int cg_set_task_access(const char *controller, const char *path, mode_t mode, uid_t uid, gid_t gid) {
char *fs;
int r;
return r;
return r;
}
int r;
char *p = NULL;
return cg_translate_error(r, errno);
assert(p);
*path = p;
return 0;
}
int r;
return cg_translate_error(r, errno);
r = -ENOMEM;
goto finish;
}
goto finish;
if (sc[0] == 0) {
r = -ENOMEM;
goto finish;
}
goto finish;
r = -EEXIST;
goto finish;
}
r = -ENOMEM;
goto finish;
}
goto finish;
goto finish;
r = -EIO;
goto finish;
}
r = 0;
return r;
}
int r;
while (r == 0) {
goto next;
break;
next:
}
if (r == ECGEOF)
r = 1;
else if (r != 0)
r = cg_translate_error(r, errno);
else
r = 0;
return r;
}
struct cgroup_file_info info;
bool empty = true;
while (r == 0) {
int k;
char *p;
goto next;
break;
}
free(p);
if (k < 0) {
ret = k;
break;
} else if (k == 0) {
empty = false;
break;
}
next:
}
if (ret == 0) {
if (r == 0 || r == ECGEOF)
else
}
return ret;
}