cgroup cleanups
[fio.git] / cgroup.c
1 /*
2  * Code related to setting up a blkio cgroup
3  */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include "fio.h"
7 #include "flist.h"
8 #include "cgroup.h"
9 #include "smalloc.h"
10
11 static struct fio_mutex *lock;
12
13 struct cgroup_member {
14         struct flist_head list;
15         char *root;
16 };
17
18 static void add_cgroup(const char *name, struct flist_head *clist)
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);
27         flist_add_tail(&cm->list, clist);
28         fio_mutex_up(lock);
29 }
30
31 void cgroup_kill(struct flist_head *clist)
32 {
33         struct flist_head *n, *tmp;
34         struct cgroup_member *cm;
35
36         fio_mutex_down(lock);
37
38         flist_for_each_safe(n, tmp, clist) {
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
46         fio_mutex_up(lock);
47 }
48
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
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
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)
76 {
77         char tmp[256];
78         FILE *f;
79         
80         sprintf(tmp, "%s/%s", path, filename);
81         f = fopen(tmp, "w");
82         if (!f) {
83                 td_verror(td, errno, onerr);
84                 return 1;
85         }
86
87         fprintf(f, "%u", val);
88         fclose(f);
89         return 0;
90
91 }
92
93 static int cgroup_write_pid(struct thread_data *td, const char *root)
94 {
95         unsigned int val = td->pid;
96
97         return write_int_to_file(td, root, "tasks", val, "cgroup write pid");
98 }
99
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 }
107
108 int cgroup_setup(struct thread_data *td, struct flist_head *clist)
109 {
110         char *root;
111
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
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");
127                         goto err;
128                 }
129         } else
130                 add_cgroup(root, clist);
131
132         if (td->o.cgroup_weight) {
133                 if (write_int_to_file(td, root, "blkio.weight",
134                                         td->o.cgroup_weight,
135                                         "cgroup open weight"))
136                         goto err;
137         }
138
139         if (!cgroup_write_pid(td, root)) {
140                 free(root);
141                 return 0;
142         }
143
144 err:
145         free(root);
146         return 1;
147 }
148
149 void cgroup_shutdown(struct thread_data *td)
150 {
151         if (cgroup_check_fs(td))
152                 return;
153         if (!td->o.cgroup_weight && td->o.cgroup)
154                 return;
155
156         cgroup_del_pid(td);
157 }
158
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);
167 }