1a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe/* 2a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe * Code related to setting up a blkio cgroup 3a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe */ 4a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe#include <stdio.h> 5a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe#include <stdlib.h> 66adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe#include <mntent.h> 74f49b8a762f20279095e5c27c51a6afc629b835fJens Axboe#include <sys/stat.h> 84f49b8a762f20279095e5c27c51a6afc629b835fJens Axboe#include <sys/types.h> 9a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe#include "fio.h" 1039f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe#include "flist.h" 11a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe#include "cgroup.h" 1239f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe#include "smalloc.h" 1339f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 1439f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboestatic struct fio_mutex *lock; 1539f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 1639f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboestruct cgroup_member { 1739f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe struct flist_head list; 1839f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe char *root; 197de870993035f855e1d1299a2b5c2c90b792c238Vivek Goyal unsigned int cgroup_nodelete; 2039f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe}; 2139f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 226adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboestatic char *find_cgroup_mnt(struct thread_data *td) 236adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe{ 246adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe char *mntpoint = NULL; 25599e72b74ed2c44fd846b95160c5037c16438994Zhu Yanhai struct mntent *mnt, dummy; 26599e72b74ed2c44fd846b95160c5037c16438994Zhu Yanhai char buf[256] = {0}; 276adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe FILE *f; 286adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe 296adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe f = setmntent("/proc/mounts", "r"); 306adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe if (!f) { 316adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe td_verror(td, errno, "setmntent /proc/mounts"); 326adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe return NULL; 336adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe } 346adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe 35599e72b74ed2c44fd846b95160c5037c16438994Zhu Yanhai while ((mnt = getmntent_r(f, &dummy, buf, sizeof(buf))) != NULL) { 366adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe if (!strcmp(mnt->mnt_type, "cgroup") && 376adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe strstr(mnt->mnt_opts, "blkio")) 386adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe break; 396adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe } 406adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe 416adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe if (mnt) 426adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe mntpoint = smalloc_strdup(mnt->mnt_dir); 436adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe else 446adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe log_err("fio: cgroup blkio does not appear to be mounted\n"); 456adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe 466adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe endmntent(f); 476adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe return mntpoint; 486adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe} 496adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe 507de870993035f855e1d1299a2b5c2c90b792c238Vivek Goyalstatic void add_cgroup(struct thread_data *td, const char *name, 517de870993035f855e1d1299a2b5c2c90b792c238Vivek Goyal struct flist_head *clist) 5239f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe{ 5339f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe struct cgroup_member *cm; 5439f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 55fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!lock) 56fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe return; 57fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe 5839f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe cm = smalloc(sizeof(*cm)); 59fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!cm) { 60fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboeerr: 61fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe log_err("fio: failed to allocate cgroup member\n"); 62fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe return; 63fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe } 64fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe 6539f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe INIT_FLIST_HEAD(&cm->list); 6639f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe cm->root = smalloc_strdup(name); 67fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!cm->root) { 68fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe sfree(cm); 69fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe goto err; 70fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe } 717de870993035f855e1d1299a2b5c2c90b792c238Vivek Goyal if (td->o.cgroup_nodelete) 727de870993035f855e1d1299a2b5c2c90b792c238Vivek Goyal cm->cgroup_nodelete = 1; 7339f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe fio_mutex_down(lock); 74dae5341c3059273242598de2bc27cc9f18c627c1Jens Axboe flist_add_tail(&cm->list, clist); 7539f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe fio_mutex_up(lock); 7639f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe} 7739f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 78dae5341c3059273242598de2bc27cc9f18c627c1Jens Axboevoid cgroup_kill(struct flist_head *clist) 7939f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe{ 8039f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe struct flist_head *n, *tmp; 8139f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe struct cgroup_member *cm; 8239f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 83fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!lock) 84fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe return; 85fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe 8639f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe fio_mutex_down(lock); 8739f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 88dae5341c3059273242598de2bc27cc9f18c627c1Jens Axboe flist_for_each_safe(n, tmp, clist) { 8939f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe cm = flist_entry(n, struct cgroup_member, list); 907de870993035f855e1d1299a2b5c2c90b792c238Vivek Goyal if (!cm->cgroup_nodelete) 917de870993035f855e1d1299a2b5c2c90b792c238Vivek Goyal rmdir(cm->root); 9239f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe flist_del(&cm->list); 9339f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe sfree(cm->root); 9439f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe sfree(cm); 9539f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe } 9639f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 9739f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe fio_mutex_up(lock); 9839f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe} 99a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1006adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboestatic char *get_cgroup_root(struct thread_data *td, char *mnt) 101a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe{ 102a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe char *str = malloc(64); 103a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 104a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe if (td->o.cgroup) 105eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes sprintf(str, "%s/%s", mnt, td->o.cgroup); 106a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe else 107eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes sprintf(str, "%s/%s", mnt, td->o.name); 108a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 109a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe return str; 110a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe} 111a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1128a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboestatic int write_int_to_file(struct thread_data *td, const char *path, 1138a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe const char *filename, unsigned int val, 1148a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe const char *onerr) 115a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe{ 1163858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe char tmp[256]; 117a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe FILE *f; 118b9fd788f0e8adacc33316107594e9eb0463743d7Bruce Cran 119eda3a60699e1d96bb68875ef2169ca819eb8f4f9Elliott Hughes sprintf(tmp, "%s/%s", path, filename); 120a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe f = fopen(tmp, "w"); 121a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe if (!f) { 1228a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe td_verror(td, errno, onerr); 123a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe return 1; 124a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe } 125a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1268a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe fprintf(f, "%u", val); 127a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe fclose(f); 128a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe return 0; 1298a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe 130a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe} 131a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1328a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboestatic int cgroup_write_pid(struct thread_data *td, const char *root) 133a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe{ 1348a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe unsigned int val = td->pid; 135a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1368a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe return write_int_to_file(td, root, "tasks", val, "cgroup write pid"); 137a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe} 138a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1393858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe/* 1403858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe * Move pid to root class 1413858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe */ 1426adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboestatic int cgroup_del_pid(struct thread_data *td, char *mnt) 1433858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe{ 1446adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe return cgroup_write_pid(td, mnt); 1453858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe} 146a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1476adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboeint cgroup_setup(struct thread_data *td, struct flist_head *clist, char **mnt) 148a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe{ 1498a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe char *root; 150a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1516adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe if (!*mnt) { 1526adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe *mnt = find_cgroup_mnt(td); 1536adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe if (!*mnt) 1546adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe return 1; 155ddf16fe4da558a2778bf1ba06c965080d318cb24Jens Axboe } 156ddf16fe4da558a2778bf1ba06c965080d318cb24Jens Axboe 157a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe /* 158a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe * Create container, if it doesn't exist 159a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe */ 1606adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe root = get_cgroup_root(td, *mnt); 161a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe if (mkdir(root, 0755) < 0) { 162a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe int __e = errno; 163a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 164a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe if (__e != EEXIST) { 165a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe td_verror(td, __e, "cgroup mkdir"); 1666adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe log_err("fio: path %s\n", root); 1673858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe goto err; 168a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe } 169a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe } else 1707de870993035f855e1d1299a2b5c2c90b792c238Vivek Goyal add_cgroup(td, root, clist); 171a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 17239f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe if (td->o.cgroup_weight) { 1738a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe if (write_int_to_file(td, root, "blkio.weight", 1748a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe td->o.cgroup_weight, 1758a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe "cgroup open weight")) 1763858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe goto err; 177a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe } 178a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1798a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe if (!cgroup_write_pid(td, root)) { 1808a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe free(root); 1818a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe return 0; 1828a4d0ff0b2d8192ef58e69b7f2a3c976f3bebd5cJens Axboe } 183a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1843858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboeerr: 1853858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe free(root); 1863858bf9eb509136b800cda1a08247e9c0ff167b9Jens Axboe return 1; 187a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe} 188a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1896adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboevoid cgroup_shutdown(struct thread_data *td, char **mnt) 190a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe{ 1916adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe if (*mnt == NULL) 192ddf16fe4da558a2778bf1ba06c965080d318cb24Jens Axboe return; 193ed81ee199ec8f3cdfcdc78ff067a0397c3b02f5fJens Axboe if (!td->o.cgroup_weight && !td->o.cgroup) 194a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe return; 195a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 1966adb38a1a1cbe95f7131815416c8bb31683c3f47Jens Axboe cgroup_del_pid(td, *mnt); 19739f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe} 198a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe 19939f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboestatic void fio_init cgroup_init(void) 20039f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe{ 201521da527743088a9bd2ab882f8b64799d49d5848Jens Axboe lock = fio_mutex_init(FIO_MUTEX_UNLOCKED); 202fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe if (!lock) 203fba5c5ff89163062922c3e560e871c087f2177c3Jens Axboe log_err("fio: failed to allocate cgroup lock\n"); 20439f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe} 20539f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe 20639f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboestatic void fio_exit cgroup_exit(void) 20739f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe{ 20839f22027248f658ade599e89c2fe6afae02ac9d7Jens Axboe fio_mutex_remove(lock); 209a696fa2a9c2e21a1c88813235d6fc39d267f6155Jens Axboe} 210