]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/cgroup.c
Change nscgroup interface
[mirror_lxc.git] / src / lxc / cgroup.c
CommitLineData
576f946d 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#define _GNU_SOURCE
24#include <stdio.h>
25#undef _GNU_SOURCE
26#include <stdlib.h>
27#include <errno.h>
28#include <mntent.h>
29#include <unistd.h>
30#include <string.h>
31#include <fcntl.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <sys/param.h>
35#include <sys/inotify.h>
36#include <netinet/in.h>
37#include <net/if.h>
38
e2bcd7db 39#include "error.h"
881450bb 40#include "config.h"
36eb9bde 41
36eb9bde 42#include <lxc/log.h>
00b3c2e2
CLG
43#include <lxc/cgroup.h>
44#include <lxc/start.h>
36eb9bde
CLG
45
46lxc_log_define(lxc_cgroup, lxc);
576f946d 47
48#define MTAB "/etc/mtab"
49
a6ddef61
MN
50static char nsgroup_path[MAXPATHLEN];
51
576f946d 52static int get_cgroup_mount(const char *mtab, char *mnt)
53{
54 struct mntent *mntent;
55 FILE *file = NULL;
56 int err = -1;
57
58 file = setmntent(mtab, "r");
59 if (!file) {
36eb9bde 60 SYSERROR("failed to open %s", mtab);
576f946d 61 goto out;
62 }
63
64 while ((mntent = getmntent(file))) {
0d9f8e18
DL
65
66 /* there is a cgroup mounted named "lxc" */
67 if (!strcmp(mntent->mnt_fsname, "lxc") &&
68 !strcmp(mntent->mnt_type, "cgroup")) {
69 strcpy(mnt, mntent->mnt_dir);
70 err = 0;
71 break;
72 }
73
74 /* fallback to the first non-lxc cgroup found */
75 if (!strcmp(mntent->mnt_type, "cgroup") && err) {
76 strcpy(mnt, mntent->mnt_dir);
77 err = 0;
78 }
576f946d 79 };
80
1ac470c0
DL
81 DEBUG("using cgroup mounted at '%s'", mnt);
82
576f946d 83 fclose(file);
84out:
85 return err;
86}
87
b234e44f 88int lxc_rename_nsgroup(const char *name, pid_t pid)
6203de18
DL
89{
90 char oldname[MAXPATHLEN];
7c282e3c 91 char newname[MAXPATHLEN];
6203de18 92 char cgroup[MAXPATHLEN];
2b31f553 93 int ret;
6203de18
DL
94
95 if (get_cgroup_mount(MTAB, cgroup)) {
2b31f553 96 ERROR("cgroup is not mounted");
6203de18
DL
97 return -1;
98 }
99
b234e44f 100 snprintf(oldname, MAXPATHLEN, "%s/%d", cgroup, pid);
6203de18
DL
101 snprintf(newname, MAXPATHLEN, "%s/%s", cgroup, name);
102
0dd4566e
DL
103 /* there is a previous cgroup, assume it is empty, otherwise
104 * that fails */
105 if (!access(newname, F_OK)) {
106 ret = rmdir(newname);
107 if (ret) {
108 SYSERROR("failed to remove previous cgroup '%s'",
109 newname);
110 return ret;
111 }
112 }
113
2b31f553
MN
114 ret = rename(oldname, newname);
115 if (ret)
0d9f8e18 116 SYSERROR("failed to rename cgroup %s->%s", oldname, newname);
1ac470c0
DL
117 else
118 DEBUG("'%s' renamed to '%s'", oldname, newname);
119
758437c5 120
2b31f553 121 return ret;
6203de18
DL
122}
123
576f946d 124int lxc_unlink_nsgroup(const char *name)
125{
126 char nsgroup[MAXPATHLEN];
422afdd2
MN
127 char cgroup[MAXPATHLEN];
128 int ret;
129
130 if (get_cgroup_mount(MTAB, cgroup)) {
131 ERROR("cgroup is not mounted");
132 return -1;
2b4e286d 133 }
4e2121f5 134
422afdd2
MN
135 snprintf(nsgroup, MAXPATHLEN, "%s/%s", cgroup, name);
136 ret = rmdir(nsgroup);
137 if (ret)
138 SYSERROR("failed to remove cgroup '%s'", nsgroup);
139 else
140 DEBUG("'%s' unlinked", nsgroup);
1ac470c0 141
422afdd2 142 return ret;
576f946d 143}
144
14ad6bfd 145int lxc_cgroup_path_get(char **path, const char *name)
a6ddef61
MN
146{
147 char cgroup[MAXPATHLEN];
148
149 *path = &nsgroup_path[0];
150
151 /*
152 * report nsgroup_path string if already set
153 */
154 if (**path != 0)
155 return 0;
156
157 if (get_cgroup_mount(MTAB, cgroup)) {
158 ERROR("cgroup is not mounted");
159 return -1;
160 }
161
162 snprintf(nsgroup_path, MAXPATHLEN, "%s/%s", cgroup, name);
163 return 0;
164}
165
576f946d 166int lxc_cgroup_set(const char *name, const char *subsystem, const char *value)
167{
4eec6850 168 int fd, ret;
a6ddef61 169 char *nsgroup;
576f946d 170 char path[MAXPATHLEN];
171
a6ddef61
MN
172 ret = lxc_cgroup_path_get(&nsgroup, name);
173 if (ret)
174 return -1;
175
176 snprintf(path, MAXPATHLEN, "%s/%s", nsgroup, subsystem);
576f946d 177
178 fd = open(path, O_WRONLY);
8b92dc3a
MN
179 if (fd < 0) {
180 ERROR("open %s : %s", path, strerror(errno));
576f946d 181 return -1;
8b92dc3a 182 }
576f946d 183
4eec6850
MN
184 ret = write(fd, value, strlen(value));
185 if (ret < 0) {
8b92dc3a 186 ERROR("write %s : %s", path, strerror(errno));
576f946d 187 goto out;
8b92dc3a 188 }
576f946d 189
190 ret = 0;
191out:
192 close(fd);
193 return ret;
194}
195
196int lxc_cgroup_get(const char *name, const char *subsystem,
197 char *value, size_t len)
198{
8b92dc3a 199 int fd, ret = -1;
a6ddef61 200 char *nsgroup;
576f946d 201 char path[MAXPATHLEN];
202
a6ddef61
MN
203 ret = lxc_cgroup_path_get(&nsgroup, name);
204 if (ret)
205 return -1;
206
207 snprintf(path, MAXPATHLEN, "%s/%s", nsgroup, subsystem);
576f946d 208
209 fd = open(path, O_RDONLY);
8b92dc3a
MN
210 if (fd < 0) {
211 ERROR("open %s : %s", path, strerror(errno));
576f946d 212 return -1;
8b92dc3a 213 }
576f946d 214
70f7755e
DL
215 ret = read(fd, value, len);
216 if (ret < 0)
8b92dc3a 217 ERROR("read %s : %s", path, strerror(errno));
70f7755e 218
576f946d 219 close(fd);
220 return ret;
221}
e0f888d9
DL
222
223int lxc_cgroup_nrtasks(const char *name)
224{
225 char *nsgroup;
226 char path[MAXPATHLEN];
227 int pid, ret, count = 0;
228 FILE *file;
229
230 ret = lxc_cgroup_path_get(&nsgroup, name);
231 if (ret)
232 return -1;
233
234 snprintf(path, MAXPATHLEN, "%s/tasks", nsgroup);
235
236 file = fopen(path, "r");
237 if (!file) {
238 SYSERROR("fopen '%s' failed", path);
239 return -1;
240 }
241
242 while (fscanf(file, "%d", &pid) != EOF)
243 count++;
244
245 fclose(file);
246
247 return count;
248}