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