]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/freezer.c
cgroups: use zalloc
[mirror_lxc.git] / src / lxc / freezer.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/param.h>
12 #include <sys/types.h>
13 #include <unistd.h>
14
15 #include "cgroups/cgroup.h"
16 #include "cgroups/cgroup_utils.h"
17 #include "commands.h"
18 #include "config.h"
19 #include "error.h"
20 #include "log.h"
21 #include "lxc.h"
22 #include "monitor.h"
23 #include "state.h"
24 #include "string_utils.h"
25
26 lxc_log_define(freezer, lxc);
27
28 static void notify_state_listeners(const char *name, const char *lxcpath,
29 lxc_state_t state)
30 {
31 (void)lxc_cmd_serve_state_clients(name, lxcpath, state);
32 (void)lxc_monitor_send_state(name, state, lxcpath);
33 }
34
35 static int do_freeze_thaw(bool freeze, struct lxc_conf *conf, const char *name,
36 const char *lxcpath)
37 {
38 call_cleaner(cgroup_exit) struct cgroup_ops *cgroup_ops = NULL;
39 lxc_state_t new_state = freeze ? FROZEN : THAWED;
40 int ret;
41 const char *state;
42 size_t state_len;
43
44 state = lxc_state2str(new_state);
45 state_len = strlen(state);
46
47 cgroup_ops = cgroup_init(conf);
48 if (!cgroup_ops)
49 return -1;
50
51 ret = cgroup_ops->set(cgroup_ops, "freezer.state", state, name, lxcpath);
52 if (ret < 0)
53 return log_error(-1, "Failed to %s %s",
54 freeze ? "freeze" : "unfreeze", name);
55
56 for (;;) {
57 char cur_state[MAX_STATE_LENGTH] = "";
58
59 ret = cgroup_ops->get(cgroup_ops, "freezer.state", cur_state,
60 sizeof(cur_state), name, lxcpath);
61 if (ret < 0)
62 return log_error(-1, "Failed to get freezer state of %s", name);
63
64 cur_state[lxc_char_right_gc(cur_state, strlen(cur_state))] = '\0';
65 ret = strncmp(cur_state, state, state_len);
66 if (ret == 0) {
67 notify_state_listeners(name, lxcpath, new_state);
68 return 0;
69 }
70
71 sleep(1);
72 }
73
74 return 0;
75 }
76
77 int lxc_freeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
78 {
79 int ret;
80
81 notify_state_listeners(name, lxcpath, FREEZING);
82 if (unified_cgroup_hierarchy() > 0)
83 ret = lxc_cmd_freeze(name, lxcpath, -1);
84 else
85 ret = do_freeze_thaw(true, conf, name, lxcpath);
86 notify_state_listeners(name, lxcpath, !ret ? FROZEN : RUNNING);
87 return ret;
88 }
89
90 int lxc_unfreeze(struct lxc_conf *conf, const char *name, const char *lxcpath)
91 {
92 int ret;
93
94 notify_state_listeners(name, lxcpath, THAWED);
95 if (unified_cgroup_hierarchy() > 0)
96 ret = lxc_cmd_unfreeze(name, lxcpath, -1);
97 else
98 ret = do_freeze_thaw(false, conf, name, lxcpath);
99 notify_state_listeners(name, lxcpath, !ret ? RUNNING : FROZEN);
100 return ret;
101 }