Better support for setting up and removing private cgroups
[fio.git] / cgroup.c
CommitLineData
a696fa2a
JA
1/*
2 * Code related to setting up a blkio cgroup
3 */
4#include <stdio.h>
5#include <stdlib.h>
6#include "fio.h"
39f22027 7#include "flist.h"
a696fa2a 8#include "cgroup.h"
39f22027
JA
9#include "smalloc.h"
10
11static struct flist_head *cgroup_list;
12static struct fio_mutex *lock;
13
14struct cgroup_member {
15 struct flist_head list;
16 char *root;
17};
18
19static void add_cgroup(const char *name)
20{
21 struct cgroup_member *cm;
22
23 cm = smalloc(sizeof(*cm));
24 INIT_FLIST_HEAD(&cm->list);
25 cm->root = smalloc_strdup(name);
26
27 fio_mutex_down(lock);
28
29 if (!cgroup_list) {
30 cgroup_list = smalloc(sizeof(struct flist_head));
31 INIT_FLIST_HEAD(cgroup_list);
32 }
33
34 flist_add_tail(&cm->list, cgroup_list);
35 fio_mutex_up(lock);
36}
37
38void cgroup_kill(void)
39{
40 struct flist_head *n, *tmp;
41 struct cgroup_member *cm;
42
43 fio_mutex_down(lock);
44 if (!cgroup_list)
45 goto out;
46
47 flist_for_each_safe(n, tmp, cgroup_list) {
48 cm = flist_entry(n, struct cgroup_member, list);
49 rmdir(cm->root);
50 flist_del(&cm->list);
51 sfree(cm->root);
52 sfree(cm);
53 }
54
55 sfree(cgroup_list);
56 cgroup_list = NULL;
57out:
58 fio_mutex_up(lock);
59}
a696fa2a 60
ddf16fe4
JA
61/*
62 * Check if the given root appears valid
63 */
64static int cgroup_check_fs(struct thread_data *td)
65{
66 struct stat sb;
67 char tmp[256];
68
69 sprintf(tmp, "%s/tasks", td->o.cgroup_root);
70 return stat(tmp, &sb);
71}
72
a696fa2a
JA
73static char *get_cgroup_root(struct thread_data *td)
74{
75 char *str = malloc(64);
76
77 if (td->o.cgroup)
78 sprintf(str, "%s/%s", td->o.cgroup_root, td->o.cgroup);
79 else
80 sprintf(str, "%s/%s", td->o.cgroup_root, td->o.name);
81
82 return str;
83}
84
85/*
86 * Add pid to given class
87 */
88static int cgroup_add_pid(struct thread_data *td)
89{
90 char *root, tmp[256];
91 FILE *f;
92
93 root = get_cgroup_root(td);
94 sprintf(tmp, "%s/tasks", root);
a696fa2a
JA
95 f = fopen(tmp, "w");
96 if (!f) {
97 td_verror(td, errno, "cgroup open tasks");
98 return 1;
99 }
100
101 fprintf(f, "%d", td->pid);
102 fclose(f);
103 free(root);
104 return 0;
105}
106
107/*
108 * Move pid to root class
109 */
110static int cgroup_del_pid(struct thread_data *td)
111{
112 char tmp[256];
113 FILE *f;
114
115 sprintf(tmp, "%s/tasks", td->o.cgroup_root);
116 f = fopen(tmp, "w");
117 if (!f) {
118 td_verror(td, errno, "cgroup open tasks");
119 return 1;
120 }
121
122 fprintf(f, "%d", td->pid);
123 fclose(f);
124 return 0;
125}
126
127
128int cgroup_setup(struct thread_data *td)
129{
130 char *root, tmp[256];
131 FILE *f;
132
ddf16fe4
JA
133 if (cgroup_check_fs(td)) {
134 log_err("fio: blkio cgroup mount point %s not valid\n",
135 td->o.cgroup_root);
136 return 1;
137 }
138
a696fa2a
JA
139 /*
140 * Create container, if it doesn't exist
141 */
142 root = get_cgroup_root(td);
143 if (mkdir(root, 0755) < 0) {
144 int __e = errno;
145
146 if (__e != EEXIST) {
147 td_verror(td, __e, "cgroup mkdir");
148 return 1;
149 }
150 } else
39f22027 151 add_cgroup(root);
a696fa2a 152
39f22027
JA
153 if (td->o.cgroup_weight) {
154 sprintf(tmp, "%s/blkio.weight", root);
155 f = fopen(tmp, "w");
156 if (!f) {
157 td_verror(td, errno, "cgroup open weight");
158 return 1;
159 }
160
161 fprintf(f, "%d", td->o.cgroup_weight);
162 fclose(f);
a696fa2a
JA
163 }
164
a696fa2a
JA
165 free(root);
166
167 if (cgroup_add_pid(td))
168 return 1;
169
170 return 0;
171}
172
173void cgroup_shutdown(struct thread_data *td)
174{
ddf16fe4
JA
175 if (cgroup_check_fs(td))
176 return;
39f22027 177 if (!td->o.cgroup_weight && td->o.cgroup)
a696fa2a
JA
178 return;
179
180 cgroup_del_pid(td);
39f22027 181}
a696fa2a 182
a696fa2a 183
39f22027
JA
184static void fio_init cgroup_init(void)
185{
186 lock = fio_mutex_init(1);
187}
188
189static void fio_exit cgroup_exit(void)
190{
191 fio_mutex_remove(lock);
a696fa2a 192}