blob: 14bbc57bd0862a46cac3ea0fbd9162288c77341f [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>
Jens Axboe6adb38a2009-12-07 08:01:26 +01006#include <mntent.h>
Jens Axboea696fa22009-12-04 10:05:02 +01007#include "fio.h"
Jens Axboe39f22022009-12-04 11:29:12 +01008#include "flist.h"
Jens Axboea696fa22009-12-04 10:05:02 +01009#include "cgroup.h"
Jens Axboe39f22022009-12-04 11:29:12 +010010#include "smalloc.h"
11
Jens Axboe39f22022009-12-04 11:29:12 +010012static struct fio_mutex *lock;
13
14struct cgroup_member {
15 struct flist_head list;
16 char *root;
17};
18
Jens Axboe6adb38a2009-12-07 08:01:26 +010019static char *find_cgroup_mnt(struct thread_data *td)
20{
21 char *mntpoint = NULL;
22 struct mntent *mnt;
23 FILE *f;
24
25 f = setmntent("/proc/mounts", "r");
26 if (!f) {
27 td_verror(td, errno, "setmntent /proc/mounts");
28 return NULL;
29 }
30
31 while ((mnt = getmntent(f)) != NULL) {
32 if (!strcmp(mnt->mnt_type, "cgroup") &&
33 strstr(mnt->mnt_opts, "blkio"))
34 break;
35 }
36
37 if (mnt)
38 mntpoint = smalloc_strdup(mnt->mnt_dir);
39 else
40 log_err("fio: cgroup blkio does not appear to be mounted\n");
41
42 endmntent(f);
43 return mntpoint;
44}
45
Jens Axboedae53412009-12-04 19:54:18 +010046static void add_cgroup(const char *name, struct flist_head *clist)
Jens Axboe39f22022009-12-04 11:29:12 +010047{
48 struct cgroup_member *cm;
49
50 cm = smalloc(sizeof(*cm));
51 INIT_FLIST_HEAD(&cm->list);
52 cm->root = smalloc_strdup(name);
53
54 fio_mutex_down(lock);
Jens Axboedae53412009-12-04 19:54:18 +010055 flist_add_tail(&cm->list, clist);
Jens Axboe39f22022009-12-04 11:29:12 +010056 fio_mutex_up(lock);
57}
58
Jens Axboedae53412009-12-04 19:54:18 +010059void cgroup_kill(struct flist_head *clist)
Jens Axboe39f22022009-12-04 11:29:12 +010060{
61 struct flist_head *n, *tmp;
62 struct cgroup_member *cm;
63
64 fio_mutex_down(lock);
Jens Axboe39f22022009-12-04 11:29:12 +010065
Jens Axboedae53412009-12-04 19:54:18 +010066 flist_for_each_safe(n, tmp, clist) {
Jens Axboe39f22022009-12-04 11:29:12 +010067 cm = flist_entry(n, struct cgroup_member, list);
68 rmdir(cm->root);
69 flist_del(&cm->list);
70 sfree(cm->root);
71 sfree(cm);
72 }
73
Jens Axboe39f22022009-12-04 11:29:12 +010074 fio_mutex_up(lock);
75}
Jens Axboea696fa22009-12-04 10:05:02 +010076
Jens Axboe6adb38a2009-12-07 08:01:26 +010077static char *get_cgroup_root(struct thread_data *td, char *mnt)
Jens Axboea696fa22009-12-04 10:05:02 +010078{
79 char *str = malloc(64);
80
81 if (td->o.cgroup)
Jens Axboe6adb38a2009-12-07 08:01:26 +010082 sprintf(str, "%s/%s", mnt, td->o.cgroup);
Jens Axboea696fa22009-12-04 10:05:02 +010083 else
Jens Axboe6adb38a2009-12-07 08:01:26 +010084 sprintf(str, "%s/%s", mnt, td->o.name);
Jens Axboea696fa22009-12-04 10:05:02 +010085
86 return str;
87}
88
Jens Axboe8a4d0ff2009-12-04 22:13:43 +010089static int write_int_to_file(struct thread_data *td, const char *path,
90 const char *filename, unsigned int val,
91 const char *onerr)
Jens Axboea696fa22009-12-04 10:05:02 +010092{
Jens Axboe3858bf92009-12-04 19:26:22 +010093 char tmp[256];
Jens Axboea696fa22009-12-04 10:05:02 +010094 FILE *f;
Jens Axboe3858bf92009-12-04 19:26:22 +010095
Jens Axboe8a4d0ff2009-12-04 22:13:43 +010096 sprintf(tmp, "%s/%s", path, filename);
Jens Axboea696fa22009-12-04 10:05:02 +010097 f = fopen(tmp, "w");
98 if (!f) {
Jens Axboe8a4d0ff2009-12-04 22:13:43 +010099 td_verror(td, errno, onerr);
Jens Axboea696fa22009-12-04 10:05:02 +0100100 return 1;
101 }
102
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100103 fprintf(f, "%u", val);
Jens Axboea696fa22009-12-04 10:05:02 +0100104 fclose(f);
Jens Axboea696fa22009-12-04 10:05:02 +0100105 return 0;
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100106
Jens Axboe3858bf92009-12-04 19:26:22 +0100107}
108
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100109static int cgroup_write_pid(struct thread_data *td, const char *root)
Jens Axboe3858bf92009-12-04 19:26:22 +0100110{
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100111 unsigned int val = td->pid;
Jens Axboe3858bf92009-12-04 19:26:22 +0100112
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100113 return write_int_to_file(td, root, "tasks", val, "cgroup write pid");
Jens Axboea696fa22009-12-04 10:05:02 +0100114}
115
116/*
117 * Move pid to root class
118 */
Jens Axboe6adb38a2009-12-07 08:01:26 +0100119static int cgroup_del_pid(struct thread_data *td, char *mnt)
Jens Axboea696fa22009-12-04 10:05:02 +0100120{
Jens Axboe6adb38a2009-12-07 08:01:26 +0100121 return cgroup_write_pid(td, mnt);
Jens Axboea696fa22009-12-04 10:05:02 +0100122}
123
Jens Axboe6adb38a2009-12-07 08:01:26 +0100124int cgroup_setup(struct thread_data *td, struct flist_head *clist, char **mnt)
Jens Axboea696fa22009-12-04 10:05:02 +0100125{
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100126 char *root;
Jens Axboea696fa22009-12-04 10:05:02 +0100127
Jens Axboe6adb38a2009-12-07 08:01:26 +0100128 if (!*mnt) {
129 *mnt = find_cgroup_mnt(td);
130 if (!*mnt)
131 return 1;
Jens Axboeddf16fe2009-12-04 10:54:45 +0100132 }
133
Jens Axboea696fa22009-12-04 10:05:02 +0100134 /*
135 * Create container, if it doesn't exist
136 */
Jens Axboe6adb38a2009-12-07 08:01:26 +0100137 root = get_cgroup_root(td, *mnt);
Jens Axboea696fa22009-12-04 10:05:02 +0100138 if (mkdir(root, 0755) < 0) {
139 int __e = errno;
140
141 if (__e != EEXIST) {
142 td_verror(td, __e, "cgroup mkdir");
Jens Axboe6adb38a2009-12-07 08:01:26 +0100143 log_err("fio: path %s\n", root);
Jens Axboe3858bf92009-12-04 19:26:22 +0100144 goto err;
Jens Axboea696fa22009-12-04 10:05:02 +0100145 }
146 } else
Jens Axboedae53412009-12-04 19:54:18 +0100147 add_cgroup(root, clist);
Jens Axboea696fa22009-12-04 10:05:02 +0100148
Jens Axboe39f22022009-12-04 11:29:12 +0100149 if (td->o.cgroup_weight) {
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100150 if (write_int_to_file(td, root, "blkio.weight",
151 td->o.cgroup_weight,
152 "cgroup open weight"))
Jens Axboe3858bf92009-12-04 19:26:22 +0100153 goto err;
Jens Axboea696fa22009-12-04 10:05:02 +0100154 }
155
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100156 if (!cgroup_write_pid(td, root)) {
157 free(root);
158 return 0;
159 }
Jens Axboea696fa22009-12-04 10:05:02 +0100160
Jens Axboe3858bf92009-12-04 19:26:22 +0100161err:
162 free(root);
163 return 1;
Jens Axboea696fa22009-12-04 10:05:02 +0100164}
165
Jens Axboe6adb38a2009-12-07 08:01:26 +0100166void cgroup_shutdown(struct thread_data *td, char **mnt)
Jens Axboea696fa22009-12-04 10:05:02 +0100167{
Jens Axboe6adb38a2009-12-07 08:01:26 +0100168 if (*mnt == NULL)
Jens Axboeddf16fe2009-12-04 10:54:45 +0100169 return;
Jens Axboeed81ee12009-12-05 22:30:04 +0100170 if (!td->o.cgroup_weight && !td->o.cgroup)
Jens Axboea696fa22009-12-04 10:05:02 +0100171 return;
172
Jens Axboe6adb38a2009-12-07 08:01:26 +0100173 cgroup_del_pid(td, *mnt);
Jens Axboe39f22022009-12-04 11:29:12 +0100174}
Jens Axboea696fa22009-12-04 10:05:02 +0100175
Jens Axboe39f22022009-12-04 11:29:12 +0100176static void fio_init cgroup_init(void)
177{
178 lock = fio_mutex_init(1);
179}
180
181static void fio_exit cgroup_exit(void)
182{
183 fio_mutex_remove(lock);
Jens Axboea696fa22009-12-04 10:05:02 +0100184}