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 | ||
85 | /* | |
86 | * Add pid to given class | |
87 | */ | |
88 | static 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 | */ | |
110 | static 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 | ||
128 | int 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 | ||
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 | } |