Commit | Line | Data |
---|---|---|
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 | ||
11 | static struct flist_head *cgroup_list; | |
12 | static struct fio_mutex *lock; | |
13 | ||
14 | struct cgroup_member { | |
15 | struct flist_head list; | |
16 | char *root; | |
17 | }; | |
18 | ||
19 | static 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 | ||
38 | void 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; | |
57 | out: | |
58 | fio_mutex_up(lock); | |
59 | } | |
a696fa2a | 60 | |
ddf16fe4 JA |
61 | /* |
62 | * Check if the given root appears valid | |
63 | */ | |
64 | static 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 |
73 | static 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 | ||
3858bf9e | 85 | static int cgroup_write_pid(struct thread_data *td, const char *root) |
a696fa2a | 86 | { |
3858bf9e | 87 | char tmp[256]; |
a696fa2a | 88 | FILE *f; |
3858bf9e | 89 | |
a696fa2a | 90 | sprintf(tmp, "%s/tasks", root); |
a696fa2a JA |
91 | f = fopen(tmp, "w"); |
92 | if (!f) { | |
93 | td_verror(td, errno, "cgroup open tasks"); | |
94 | return 1; | |
95 | } | |
96 | ||
97 | fprintf(f, "%d", td->pid); | |
98 | fclose(f); | |
a696fa2a | 99 | return 0; |
3858bf9e | 100 | |
a696fa2a JA |
101 | } |
102 | ||
103 | /* | |
3858bf9e | 104 | * Add pid to given class |
a696fa2a | 105 | */ |
3858bf9e | 106 | static int cgroup_add_pid(struct thread_data *td) |
a696fa2a | 107 | { |
3858bf9e JA |
108 | char *root; |
109 | int ret; | |
a696fa2a | 110 | |
3858bf9e JA |
111 | root = get_cgroup_root(td); |
112 | ret = cgroup_write_pid(td, root); | |
113 | free(root); | |
114 | return ret; | |
a696fa2a JA |
115 | } |
116 | ||
3858bf9e JA |
117 | /* |
118 | * Move pid to root class | |
119 | */ | |
120 | static int cgroup_del_pid(struct thread_data *td) | |
121 | { | |
122 | return cgroup_write_pid(td, td->o.cgroup_root); | |
123 | } | |
a696fa2a JA |
124 | |
125 | int cgroup_setup(struct thread_data *td) | |
126 | { | |
127 | char *root, tmp[256]; | |
128 | FILE *f; | |
129 | ||
ddf16fe4 JA |
130 | if (cgroup_check_fs(td)) { |
131 | log_err("fio: blkio cgroup mount point %s not valid\n", | |
132 | td->o.cgroup_root); | |
133 | return 1; | |
134 | } | |
135 | ||
a696fa2a JA |
136 | /* |
137 | * Create container, if it doesn't exist | |
138 | */ | |
139 | root = get_cgroup_root(td); | |
140 | if (mkdir(root, 0755) < 0) { | |
141 | int __e = errno; | |
142 | ||
143 | if (__e != EEXIST) { | |
144 | td_verror(td, __e, "cgroup mkdir"); | |
3858bf9e | 145 | goto err; |
a696fa2a JA |
146 | } |
147 | } else | |
39f22027 | 148 | add_cgroup(root); |
a696fa2a | 149 | |
39f22027 JA |
150 | if (td->o.cgroup_weight) { |
151 | sprintf(tmp, "%s/blkio.weight", root); | |
152 | f = fopen(tmp, "w"); | |
153 | if (!f) { | |
154 | td_verror(td, errno, "cgroup open weight"); | |
3858bf9e | 155 | goto err; |
39f22027 JA |
156 | } |
157 | ||
158 | fprintf(f, "%d", td->o.cgroup_weight); | |
159 | fclose(f); | |
a696fa2a JA |
160 | } |
161 | ||
a696fa2a JA |
162 | free(root); |
163 | ||
164 | if (cgroup_add_pid(td)) | |
165 | return 1; | |
166 | ||
167 | return 0; | |
3858bf9e JA |
168 | err: |
169 | free(root); | |
170 | return 1; | |
a696fa2a JA |
171 | } |
172 | ||
173 | void 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 |
184 | static void fio_init cgroup_init(void) |
185 | { | |
186 | lock = fio_mutex_init(1); | |
187 | } | |
188 | ||
189 | static void fio_exit cgroup_exit(void) | |
190 | { | |
191 | fio_mutex_remove(lock); | |
a696fa2a | 192 | } |