blob: 417c50be1088cc77bf531febfb29bbe1eeb8ddb2 [file] [log] [blame]
Jens Axboea696fa22009-12-04 10:05:02 +01001/*
2 * Code related to setting up a blkio cgroup
3 */
4#include <stdio.h>
5#include <stdlib.h>
6#include "fio.h"
Jens Axboe39f22022009-12-04 11:29:12 +01007#include "flist.h"
Jens Axboea696fa22009-12-04 10:05:02 +01008#include "cgroup.h"
Jens Axboe39f22022009-12-04 11:29:12 +01009#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}
Jens Axboea696fa22009-12-04 10:05:02 +010060
Jens Axboeddf16fe2009-12-04 10:54:45 +010061/*
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
Jens Axboea696fa22009-12-04 10:05:02 +010073static 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
Jens Axboe3858bf92009-12-04 19:26:22 +010085static int cgroup_write_pid(struct thread_data *td, const char *root)
Jens Axboea696fa22009-12-04 10:05:02 +010086{
Jens Axboe3858bf92009-12-04 19:26:22 +010087 char tmp[256];
Jens Axboea696fa22009-12-04 10:05:02 +010088 FILE *f;
Jens Axboe3858bf92009-12-04 19:26:22 +010089
Jens Axboea696fa22009-12-04 10:05:02 +010090 sprintf(tmp, "%s/tasks", root);
Jens Axboea696fa22009-12-04 10:05:02 +010091 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);
Jens Axboea696fa22009-12-04 10:05:02 +010099 return 0;
Jens Axboe3858bf92009-12-04 19:26:22 +0100100
101}
102
103/*
104 * Add pid to given class
105 */
106static int cgroup_add_pid(struct thread_data *td)
107{
108 char *root;
109 int ret;
110
111 root = get_cgroup_root(td);
112 ret = cgroup_write_pid(td, root);
113 free(root);
114 return ret;
Jens Axboea696fa22009-12-04 10:05:02 +0100115}
116
117/*
118 * Move pid to root class
119 */
120static int cgroup_del_pid(struct thread_data *td)
121{
Jens Axboe3858bf92009-12-04 19:26:22 +0100122 return cgroup_write_pid(td, td->o.cgroup_root);
Jens Axboea696fa22009-12-04 10:05:02 +0100123}
124
Jens Axboea696fa22009-12-04 10:05:02 +0100125int cgroup_setup(struct thread_data *td)
126{
127 char *root, tmp[256];
128 FILE *f;
129
Jens Axboeddf16fe2009-12-04 10:54:45 +0100130 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
Jens Axboea696fa22009-12-04 10:05:02 +0100136 /*
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");
Jens Axboe3858bf92009-12-04 19:26:22 +0100145 goto err;
Jens Axboea696fa22009-12-04 10:05:02 +0100146 }
147 } else
Jens Axboe39f22022009-12-04 11:29:12 +0100148 add_cgroup(root);
Jens Axboea696fa22009-12-04 10:05:02 +0100149
Jens Axboe39f22022009-12-04 11:29:12 +0100150 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");
Jens Axboe3858bf92009-12-04 19:26:22 +0100155 goto err;
Jens Axboe39f22022009-12-04 11:29:12 +0100156 }
157
158 fprintf(f, "%d", td->o.cgroup_weight);
159 fclose(f);
Jens Axboea696fa22009-12-04 10:05:02 +0100160 }
161
Jens Axboea696fa22009-12-04 10:05:02 +0100162 free(root);
163
164 if (cgroup_add_pid(td))
165 return 1;
166
167 return 0;
Jens Axboe3858bf92009-12-04 19:26:22 +0100168err:
169 free(root);
170 return 1;
Jens Axboea696fa22009-12-04 10:05:02 +0100171}
172
173void cgroup_shutdown(struct thread_data *td)
174{
Jens Axboeddf16fe2009-12-04 10:54:45 +0100175 if (cgroup_check_fs(td))
176 return;
Jens Axboe39f22022009-12-04 11:29:12 +0100177 if (!td->o.cgroup_weight && td->o.cgroup)
Jens Axboea696fa22009-12-04 10:05:02 +0100178 return;
179
180 cgroup_del_pid(td);
Jens Axboe39f22022009-12-04 11:29:12 +0100181}
Jens Axboea696fa22009-12-04 10:05:02 +0100182
Jens Axboea696fa22009-12-04 10:05:02 +0100183
Jens Axboe39f22022009-12-04 11:29:12 +0100184static 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);
Jens Axboea696fa22009-12-04 10:05:02 +0100192}