blob: 0e3a71ebbfa75f57c9980ff6ba5c990b972d0c50 [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;
Vivek Goyal7de87092010-03-31 22:55:15 +020017 unsigned int cgroup_nodelete;
Jens Axboe39f22022009-12-04 11:29:12 +010018};
19
Jens Axboe6adb38a2009-12-07 08:01:26 +010020static char *find_cgroup_mnt(struct thread_data *td)
21{
22 char *mntpoint = NULL;
23 struct mntent *mnt;
24 FILE *f;
25
26 f = setmntent("/proc/mounts", "r");
27 if (!f) {
28 td_verror(td, errno, "setmntent /proc/mounts");
29 return NULL;
30 }
31
32 while ((mnt = getmntent(f)) != NULL) {
33 if (!strcmp(mnt->mnt_type, "cgroup") &&
34 strstr(mnt->mnt_opts, "blkio"))
35 break;
36 }
37
38 if (mnt)
39 mntpoint = smalloc_strdup(mnt->mnt_dir);
40 else
41 log_err("fio: cgroup blkio does not appear to be mounted\n");
42
43 endmntent(f);
44 return mntpoint;
45}
46
Vivek Goyal7de87092010-03-31 22:55:15 +020047static void add_cgroup(struct thread_data *td, const char *name,
48 struct flist_head *clist)
Jens Axboe39f22022009-12-04 11:29:12 +010049{
50 struct cgroup_member *cm;
51
52 cm = smalloc(sizeof(*cm));
53 INIT_FLIST_HEAD(&cm->list);
54 cm->root = smalloc_strdup(name);
Vivek Goyal7de87092010-03-31 22:55:15 +020055 if (td->o.cgroup_nodelete)
56 cm->cgroup_nodelete = 1;
Jens Axboe39f22022009-12-04 11:29:12 +010057 fio_mutex_down(lock);
Jens Axboedae53412009-12-04 19:54:18 +010058 flist_add_tail(&cm->list, clist);
Jens Axboe39f22022009-12-04 11:29:12 +010059 fio_mutex_up(lock);
60}
61
Jens Axboedae53412009-12-04 19:54:18 +010062void cgroup_kill(struct flist_head *clist)
Jens Axboe39f22022009-12-04 11:29:12 +010063{
64 struct flist_head *n, *tmp;
65 struct cgroup_member *cm;
66
67 fio_mutex_down(lock);
Jens Axboe39f22022009-12-04 11:29:12 +010068
Jens Axboedae53412009-12-04 19:54:18 +010069 flist_for_each_safe(n, tmp, clist) {
Jens Axboe39f22022009-12-04 11:29:12 +010070 cm = flist_entry(n, struct cgroup_member, list);
Vivek Goyal7de87092010-03-31 22:55:15 +020071 if (!cm->cgroup_nodelete)
72 rmdir(cm->root);
Jens Axboe39f22022009-12-04 11:29:12 +010073 flist_del(&cm->list);
74 sfree(cm->root);
75 sfree(cm);
76 }
77
Jens Axboe39f22022009-12-04 11:29:12 +010078 fio_mutex_up(lock);
79}
Jens Axboea696fa22009-12-04 10:05:02 +010080
Jens Axboe6adb38a2009-12-07 08:01:26 +010081static char *get_cgroup_root(struct thread_data *td, char *mnt)
Jens Axboea696fa22009-12-04 10:05:02 +010082{
83 char *str = malloc(64);
84
85 if (td->o.cgroup)
Jens Axboe6adb38a2009-12-07 08:01:26 +010086 sprintf(str, "%s/%s", mnt, td->o.cgroup);
Jens Axboea696fa22009-12-04 10:05:02 +010087 else
Jens Axboe6adb38a2009-12-07 08:01:26 +010088 sprintf(str, "%s/%s", mnt, td->o.name);
Jens Axboea696fa22009-12-04 10:05:02 +010089
90 return str;
91}
92
Jens Axboe8a4d0ff2009-12-04 22:13:43 +010093static int write_int_to_file(struct thread_data *td, const char *path,
94 const char *filename, unsigned int val,
95 const char *onerr)
Jens Axboea696fa22009-12-04 10:05:02 +010096{
Jens Axboe3858bf92009-12-04 19:26:22 +010097 char tmp[256];
Jens Axboea696fa22009-12-04 10:05:02 +010098 FILE *f;
Jens Axboe3858bf92009-12-04 19:26:22 +010099
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100100 sprintf(tmp, "%s/%s", path, filename);
Jens Axboea696fa22009-12-04 10:05:02 +0100101 f = fopen(tmp, "w");
102 if (!f) {
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100103 td_verror(td, errno, onerr);
Jens Axboea696fa22009-12-04 10:05:02 +0100104 return 1;
105 }
106
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100107 fprintf(f, "%u", val);
Jens Axboea696fa22009-12-04 10:05:02 +0100108 fclose(f);
Jens Axboea696fa22009-12-04 10:05:02 +0100109 return 0;
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100110
Jens Axboe3858bf92009-12-04 19:26:22 +0100111}
112
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100113static int cgroup_write_pid(struct thread_data *td, const char *root)
Jens Axboe3858bf92009-12-04 19:26:22 +0100114{
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100115 unsigned int val = td->pid;
Jens Axboe3858bf92009-12-04 19:26:22 +0100116
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100117 return write_int_to_file(td, root, "tasks", val, "cgroup write pid");
Jens Axboea696fa22009-12-04 10:05:02 +0100118}
119
120/*
121 * Move pid to root class
122 */
Jens Axboe6adb38a2009-12-07 08:01:26 +0100123static int cgroup_del_pid(struct thread_data *td, char *mnt)
Jens Axboea696fa22009-12-04 10:05:02 +0100124{
Jens Axboe6adb38a2009-12-07 08:01:26 +0100125 return cgroup_write_pid(td, mnt);
Jens Axboea696fa22009-12-04 10:05:02 +0100126}
127
Jens Axboe6adb38a2009-12-07 08:01:26 +0100128int cgroup_setup(struct thread_data *td, struct flist_head *clist, char **mnt)
Jens Axboea696fa22009-12-04 10:05:02 +0100129{
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100130 char *root;
Jens Axboea696fa22009-12-04 10:05:02 +0100131
Jens Axboe6adb38a2009-12-07 08:01:26 +0100132 if (!*mnt) {
133 *mnt = find_cgroup_mnt(td);
134 if (!*mnt)
135 return 1;
Jens Axboeddf16fe2009-12-04 10:54:45 +0100136 }
137
Jens Axboea696fa22009-12-04 10:05:02 +0100138 /*
139 * Create container, if it doesn't exist
140 */
Jens Axboe6adb38a2009-12-07 08:01:26 +0100141 root = get_cgroup_root(td, *mnt);
Jens Axboea696fa22009-12-04 10:05:02 +0100142 if (mkdir(root, 0755) < 0) {
143 int __e = errno;
144
145 if (__e != EEXIST) {
146 td_verror(td, __e, "cgroup mkdir");
Jens Axboe6adb38a2009-12-07 08:01:26 +0100147 log_err("fio: path %s\n", root);
Jens Axboe3858bf92009-12-04 19:26:22 +0100148 goto err;
Jens Axboea696fa22009-12-04 10:05:02 +0100149 }
150 } else
Vivek Goyal7de87092010-03-31 22:55:15 +0200151 add_cgroup(td, root, clist);
Jens Axboea696fa22009-12-04 10:05:02 +0100152
Jens Axboe39f22022009-12-04 11:29:12 +0100153 if (td->o.cgroup_weight) {
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100154 if (write_int_to_file(td, root, "blkio.weight",
155 td->o.cgroup_weight,
156 "cgroup open weight"))
Jens Axboe3858bf92009-12-04 19:26:22 +0100157 goto err;
Jens Axboea696fa22009-12-04 10:05:02 +0100158 }
159
Jens Axboe8a4d0ff2009-12-04 22:13:43 +0100160 if (!cgroup_write_pid(td, root)) {
161 free(root);
162 return 0;
163 }
Jens Axboea696fa22009-12-04 10:05:02 +0100164
Jens Axboe3858bf92009-12-04 19:26:22 +0100165err:
166 free(root);
167 return 1;
Jens Axboea696fa22009-12-04 10:05:02 +0100168}
169
Jens Axboe6adb38a2009-12-07 08:01:26 +0100170void cgroup_shutdown(struct thread_data *td, char **mnt)
Jens Axboea696fa22009-12-04 10:05:02 +0100171{
Jens Axboe6adb38a2009-12-07 08:01:26 +0100172 if (*mnt == NULL)
Jens Axboeddf16fe2009-12-04 10:54:45 +0100173 return;
Jens Axboeed81ee12009-12-05 22:30:04 +0100174 if (!td->o.cgroup_weight && !td->o.cgroup)
Jens Axboea696fa22009-12-04 10:05:02 +0100175 return;
176
Jens Axboe6adb38a2009-12-07 08:01:26 +0100177 cgroup_del_pid(td, *mnt);
Jens Axboe39f22022009-12-04 11:29:12 +0100178}
Jens Axboea696fa22009-12-04 10:05:02 +0100179
Jens Axboe39f22022009-12-04 11:29:12 +0100180static void fio_init cgroup_init(void)
181{
182 lock = fio_mutex_init(1);
183}
184
185static void fio_exit cgroup_exit(void)
186{
187 fio_mutex_remove(lock);
Jens Axboea696fa22009-12-04 10:05:02 +0100188}