]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/lxclock.c
lxc-user-nic: bugfixes
[mirror_lxc.git] / src / lxc / lxclock.c
CommitLineData
72d0e1cb
SG
1/* liblxcapi
2 *
3 * Copyright © 2012 Serge Hallyn <serge.hallyn@ubuntu.com>.
4 * Copyright © 2012 Canonical Ltd.
5 *
d75462e4
SH
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
72d0e1cb
SG
19 */
20
052616eb 21#define _GNU_SOURCE
72d0e1cb 22#include <malloc.h>
8173e600 23#include <stdio.h>
df271a59
SH
24#include <errno.h>
25#include <unistd.h>
93dc5327 26#include <fcntl.h>
469b5787 27#include <stdlib.h>
052616eb 28#include <pthread.h>
f2363e38 29
5cee8c50 30#include <lxc/lxccontainer.h>
72d0e1cb 31
ccfc84ca 32#include "lxclock.h"
f2363e38
ÇO
33#include "utils.h"
34#include "log.h"
35
41f68357
ÇO
36#ifdef MUTEX_DEBUGGING
37#include <execinfo.h>
38#endif
39
5b28d063
SH
40#define MAX_STACKDEPTH 25
41
df271a59 42lxc_log_define(lxc_lock, lxc);
72d0e1cb 43
052616eb 44#ifdef MUTEX_DEBUGGING
74a3920a 45static pthread_mutex_t thread_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
41f68357 46
74a3920a 47static inline void dump_stacktrace(void)
41f68357
ÇO
48{
49 void *array[MAX_STACKDEPTH];
50 size_t size;
51 char **strings;
52 size_t i;
53
54 size = backtrace(array, MAX_STACKDEPTH);
55 strings = backtrace_symbols(array, size);
56
1a0e70ac 57 /* Using fprintf here as our logging module is not thread safe. */
6fc7d8b6 58 fprintf(stderr, "\tObtained %zu stack frames.\n", size);
41f68357
ÇO
59
60 for (i = 0; i < size; i++)
61 fprintf(stderr, "\t\t%s\n", strings[i]);
62
157ad8d4 63 free(strings);
41f68357 64}
052616eb 65#else
74a3920a 66static pthread_mutex_t thread_mutex = PTHREAD_MUTEX_INITIALIZER;
41f68357 67
74a3920a 68static inline void dump_stacktrace(void) {;}
052616eb 69#endif
df271a59 70
74a3920a 71static void lock_mutex(pthread_mutex_t *l)
41f68357
ÇO
72{
73 int ret;
74
75 if ((ret = pthread_mutex_lock(l)) != 0) {
03fadd16 76 fprintf(stderr, "pthread_mutex_lock returned:%d %s\n", ret, strerror(ret));
41f68357 77 dump_stacktrace();
ccfc84ca 78 exit(EXIT_FAILURE);
41f68357
ÇO
79 }
80}
81
74a3920a 82static void unlock_mutex(pthread_mutex_t *l)
41f68357
ÇO
83{
84 int ret;
85
86 if ((ret = pthread_mutex_unlock(l)) != 0) {
03fadd16 87 fprintf(stderr, "pthread_mutex_unlock returned:%d %s\n", ret, strerror(ret));
41f68357 88 dump_stacktrace();
ccfc84ca 89 exit(EXIT_FAILURE);
41f68357
ÇO
90 }
91}
92
df271a59 93static char *lxclock_name(const char *p, const char *n)
72d0e1cb
SG
94{
95 int ret;
469b5787
SH
96 int len;
97 char *dest;
44b9ae4b 98 char *rundir;
71b0fed6 99
469b5787 100 /* lockfile will be:
72cf81f6 101 * "/run" + "/lxc/lock/$lxcpath/$lxcname + '\0' if root
469b5787 102 * or
72cf81f6 103 * $XDG_RUNTIME_DIR + "/lxc/lock/$lxcpath/$lxcname + '\0' if non-root
469b5787
SH
104 */
105
72cf81f6
SH
106 /* length of "/lxc/lock/" + $lxcpath + "/" + "." + $lxcname + '\0' */
107 len = strlen("/lxc/lock/") + strlen(n) + strlen(p) + 3;
9e60f51d 108 rundir = get_rundir();
97a696c6
SG
109 if (!rundir)
110 return NULL;
469b5787
SH
111 len += strlen(rundir);
112
44b9ae4b
SG
113 if ((dest = malloc(len)) == NULL) {
114 free(rundir);
72d0e1cb 115 return NULL;
44b9ae4b 116 }
469b5787 117
72cf81f6 118 ret = snprintf(dest, len, "%s/lxc/lock/%s", rundir, p);
72d0e1cb
SG
119 if (ret < 0 || ret >= len) {
120 free(dest);
44b9ae4b 121 free(rundir);
72d0e1cb
SG
122 return NULL;
123 }
5cee8c50 124 ret = mkdir_p(dest, 0755);
5cee8c50 125 if (ret < 0) {
72cf81f6
SH
126 free(dest);
127 free(rundir);
128 return NULL;
129 }
72d0e1cb 130
72cf81f6 131 ret = snprintf(dest, len, "%s/lxc/lock/%s/.%s", rundir, p, n);
44b9ae4b 132 free(rundir);
df271a59
SH
133 if (ret < 0 || ret >= len) {
134 free(dest);
135 return NULL;
136 }
137 return dest;
72d0e1cb
SG
138}
139
140static sem_t *lxc_new_unnamed_sem(void)
141{
87677950
SH
142 sem_t *s;
143 int ret;
72d0e1cb 144
87677950
SH
145 s = malloc(sizeof(*s));
146 if (!s)
147 return NULL;
148 ret = sem_init(s, 0, 1);
bdb539b8
SH
149 if (ret) {
150 free(s);
87677950 151 return NULL;
bdb539b8 152 }
87677950 153 return s;
72d0e1cb
SG
154}
155
df271a59 156struct lxc_lock *lxc_newlock(const char *lxcpath, const char *name)
72d0e1cb 157{
df271a59 158 struct lxc_lock *l;
72d0e1cb 159
df271a59
SH
160 l = malloc(sizeof(*l));
161 if (!l)
162 goto out;
72d0e1cb 163
df271a59
SH
164 if (!name) {
165 l->type = LXC_LOCK_ANON_SEM;
166 l->u.sem = lxc_new_unnamed_sem();
41c3b7c7
DE
167 if (!l->u.sem) {
168 free(l);
169 l = NULL;
170 }
df271a59
SH
171 goto out;
172 }
173
174 l->type = LXC_LOCK_FLOCK;
175 l->u.f.fname = lxclock_name(lxcpath, name);
176 if (!l->u.f.fname) {
177 free(l);
178 l = NULL;
179 goto out;
180 }
181 l->u.f.fd = -1;
182
183out:
df271a59 184 return l;
72d0e1cb
SG
185}
186
df271a59 187int lxclock(struct lxc_lock *l, int timeout)
72d0e1cb 188{
5cee8c50 189 int ret = -1, saved_errno = errno;
93dc5327 190 struct flock lk;
72d0e1cb 191
df271a59
SH
192 switch(l->type) {
193 case LXC_LOCK_ANON_SEM:
194 if (!timeout) {
195 ret = sem_wait(l->u.sem);
196 if (ret == -1)
197 saved_errno = errno;
198 } else {
199 struct timespec ts;
200 if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
201 ret = -2;
202 goto out;
203 }
204 ts.tv_sec += timeout;
205 ret = sem_timedwait(l->u.sem, &ts);
206 if (ret == -1)
207 saved_errno = errno;
208 }
209 break;
210 case LXC_LOCK_FLOCK:
211 ret = -2;
212 if (timeout) {
213 ERROR("Error: timeout not supported with flock");
df271a59
SH
214 goto out;
215 }
216 if (!l->u.f.fname) {
217 ERROR("Error: filename not set for flock");
df271a59
SH
218 goto out;
219 }
220 if (l->u.f.fd == -1) {
221 l->u.f.fd = open(l->u.f.fname, O_RDWR|O_CREAT,
222 S_IWUSR | S_IRUSR);
223 if (l->u.f.fd == -1) {
224 ERROR("Error opening %s", l->u.f.fname);
98375790 225 saved_errno = errno;
df271a59
SH
226 goto out;
227 }
228 }
93dc5327
SH
229 lk.l_type = F_WRLCK;
230 lk.l_whence = SEEK_SET;
231 lk.l_start = 0;
232 lk.l_len = 0;
233 ret = fcntl(l->u.f.fd, F_SETLKW, &lk);
df271a59
SH
234 if (ret == -1)
235 saved_errno = errno;
236 break;
72d0e1cb
SG
237 }
238
df271a59 239out:
df271a59 240 errno = saved_errno;
72d0e1cb
SG
241 return ret;
242}
243
df271a59 244int lxcunlock(struct lxc_lock *l)
72d0e1cb 245{
5cee8c50 246 int ret = 0, saved_errno = errno;
93dc5327 247 struct flock lk;
df271a59
SH
248
249 switch(l->type) {
250 case LXC_LOCK_ANON_SEM:
251 if (!l->u.sem)
252 ret = -2;
659aa061 253 else {
df271a59
SH
254 ret = sem_post(l->u.sem);
255 saved_errno = errno;
659aa061 256 }
df271a59
SH
257 break;
258 case LXC_LOCK_FLOCK:
259 if (l->u.f.fd != -1) {
93dc5327
SH
260 lk.l_type = F_UNLCK;
261 lk.l_whence = SEEK_SET;
262 lk.l_start = 0;
263 lk.l_len = 0;
264 ret = fcntl(l->u.f.fd, F_SETLK, &lk);
265 if (ret < 0)
df271a59
SH
266 saved_errno = errno;
267 close(l->u.f.fd);
268 l->u.f.fd = -1;
269 } else
270 ret = -2;
271 break;
272 }
273
df271a59
SH
274 errno = saved_errno;
275 return ret;
276}
277
5cee8c50
SH
278/*
279 * lxc_putlock() is only called when a container_new() fails,
280 * or during container_put(), which is already guaranteed to
281 * only be done by one task.
282 * So the only exclusion we need to provide here is for regular
283 * thread safety (i.e. file descriptor table changes).
284 */
df271a59
SH
285void lxc_putlock(struct lxc_lock *l)
286{
df271a59 287 if (!l)
5cee8c50 288 return;
df271a59
SH
289 switch(l->type) {
290 case LXC_LOCK_ANON_SEM:
41c3b7c7 291 if (l->u.sem) {
527dacf6 292 sem_destroy(l->u.sem);
41c3b7c7
DE
293 free(l->u.sem);
294 l->u.sem = NULL;
295 }
df271a59
SH
296 break;
297 case LXC_LOCK_FLOCK:
298 if (l->u.f.fd != -1) {
299 close(l->u.f.fd);
300 l->u.f.fd = -1;
301 }
f10fad2f
ME
302 free(l->u.f.fname);
303 l->u.f.fname = NULL;
df271a59
SH
304 break;
305 }
41c3b7c7 306 free(l);
5cee8c50
SH
307}
308
025ed0f3 309void process_lock(void)
5cee8c50 310{
41f68357 311 lock_mutex(&thread_mutex);
5cee8c50
SH
312}
313
314void process_unlock(void)
315{
41f68357
ÇO
316 unlock_mutex(&thread_mutex);
317}
052616eb 318
67c4fe9b 319/* One thread can do fork() while another one is holding a mutex.
ec64264d 320 * There is only one thread in child just after the fork(), so no one will ever release that mutex.
67c4fe9b
SG
321 * We setup a "child" fork handler to unlock the mutex just after the fork().
322 * For several mutex types, unlocking an unlocked mutex can lead to undefined behavior.
323 * One way to deal with it is to setup "prepare" fork handler
324 * to lock the mutex before fork() and both "parent" and "child" fork handlers
325 * to unlock the mutex.
326 * This forbids doing fork() while explicitly holding the lock.
327 */
babbea4b 328#ifdef HAVE_PTHREAD_ATFORK
67c4fe9b
SG
329__attribute__((constructor))
330static void process_lock_setup_atfork(void)
331{
332 pthread_atfork(process_lock, process_unlock, process_unlock);
333}
babbea4b 334#endif
67c4fe9b 335
5cee8c50
SH
336int container_mem_lock(struct lxc_container *c)
337{
338 return lxclock(c->privlock, 0);
339}
340
341void container_mem_unlock(struct lxc_container *c)
342{
343 lxcunlock(c->privlock);
344}
345
346int container_disk_lock(struct lxc_container *c)
347{
348 int ret;
349
350 if ((ret = lxclock(c->privlock, 0)))
351 return ret;
352 if ((ret = lxclock(c->slock, 0))) {
353 lxcunlock(c->privlock);
354 return ret;
355 }
356 return 0;
357}
358
359void container_disk_unlock(struct lxc_container *c)
360{
361 lxcunlock(c->slock);
362 lxcunlock(c->privlock);
363}