]>
Commit | Line | Data |
---|---|---|
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 | |
46 | lxc_log_define(lxc_cgroup, lxc); | |
576f946d | 47 | |
48 | #define MTAB "/etc/mtab" | |
49 | ||
a6ddef61 MN |
50 | static char nsgroup_path[MAXPATHLEN]; |
51 | ||
576f946d | 52 | static 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); |
84 | out: | |
85 | return err; | |
86 | } | |
87 | ||
b234e44f | 88 | int 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 | 124 | int 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 | 145 | int 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 | 166 | int 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; | |
191 | out: | |
192 | close(fd); | |
193 | return ret; | |
194 | } | |
195 | ||
196 | int 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 | |
223 | int 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 | } |