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 | ||
8a4d0ff0 JA |
73 | static int write_int_to_file(struct thread_data *td, const char *path, |
74 | const char *filename, unsigned int val, | |
75 | const char *onerr) | |
a696fa2a | 76 | { |
3858bf9e | 77 | char tmp[256]; |
a696fa2a | 78 | FILE *f; |
3858bf9e | 79 | |
8a4d0ff0 | 80 | sprintf(tmp, "%s/%s", path, filename); |
a696fa2a JA |
81 | f = fopen(tmp, "w"); |
82 | if (!f) { | |
8a4d0ff0 | 83 | td_verror(td, errno, onerr); |
a696fa2a JA |
84 | return 1; |
85 | } | |
86 | ||
8a4d0ff0 | 87 | fprintf(f, "%u", val); |
a696fa2a | 88 | fclose(f); |
a696fa2a | 89 | return 0; |
8a4d0ff0 | 90 | |
a696fa2a JA |
91 | } |
92 | ||
8a4d0ff0 | 93 | static int cgroup_write_pid(struct thread_data *td, const char *root) |
a696fa2a | 94 | { |
8a4d0ff0 | 95 | unsigned int val = td->pid; |
a696fa2a | 96 | |
8a4d0ff0 | 97 | return write_int_to_file(td, root, "tasks", val, "cgroup write pid"); |
a696fa2a JA |
98 | } |
99 | ||
3858bf9e JA |
100 | /* |
101 | * Move pid to root class | |
102 | */ | |
103 | static int cgroup_del_pid(struct thread_data *td) | |
104 | { | |
105 | return cgroup_write_pid(td, td->o.cgroup_root); | |
106 | } | |
a696fa2a | 107 | |
dae5341c | 108 | int cgroup_setup(struct thread_data *td, struct flist_head *clist) |
a696fa2a | 109 | { |
8a4d0ff0 | 110 | char *root; |
a696fa2a | 111 | |
ddf16fe4 JA |
112 | if (cgroup_check_fs(td)) { |
113 | log_err("fio: blkio cgroup mount point %s not valid\n", | |
114 | td->o.cgroup_root); | |
115 | return 1; | |
116 | } | |
117 | ||
a696fa2a JA |
118 | /* |
119 | * Create container, if it doesn't exist | |
120 | */ | |
121 | root = get_cgroup_root(td); | |
122 | if (mkdir(root, 0755) < 0) { | |
123 | int __e = errno; | |
124 | ||
125 | if (__e != EEXIST) { | |
126 | td_verror(td, __e, "cgroup mkdir"); | |
3858bf9e | 127 | goto err; |
a696fa2a JA |
128 | } |
129 | } else | |
dae5341c | 130 | add_cgroup(root, clist); |
a696fa2a | 131 | |
39f22027 | 132 | if (td->o.cgroup_weight) { |
8a4d0ff0 JA |
133 | if (write_int_to_file(td, root, "blkio.weight", |
134 | td->o.cgroup_weight, | |
135 | "cgroup open weight")) | |
3858bf9e | 136 | goto err; |
a696fa2a JA |
137 | } |
138 | ||
8a4d0ff0 JA |
139 | if (!cgroup_write_pid(td, root)) { |
140 | free(root); | |
141 | return 0; | |
142 | } | |
a696fa2a | 143 | |
3858bf9e JA |
144 | err: |
145 | free(root); | |
146 | return 1; | |
a696fa2a JA |
147 | } |
148 | ||
149 | void cgroup_shutdown(struct thread_data *td) | |
150 | { | |
ddf16fe4 JA |
151 | if (cgroup_check_fs(td)) |
152 | return; | |
39f22027 | 153 | if (!td->o.cgroup_weight && td->o.cgroup) |
a696fa2a JA |
154 | return; |
155 | ||
156 | cgroup_del_pid(td); | |
39f22027 | 157 | } |
a696fa2a | 158 | |
39f22027 JA |
159 | static void fio_init cgroup_init(void) |
160 | { | |
161 | lock = fio_mutex_init(1); | |
162 | } | |
163 | ||
164 | static void fio_exit cgroup_exit(void) | |
165 | { | |
166 | fio_mutex_remove(lock); | |
a696fa2a | 167 | } |