131e4c28dSVivek Goyal #ifndef _BLK_CGROUP_H 231e4c28dSVivek Goyal #define _BLK_CGROUP_H 331e4c28dSVivek Goyal /* 431e4c28dSVivek Goyal * Common Block IO controller cgroup interface 531e4c28dSVivek Goyal * 631e4c28dSVivek Goyal * Based on ideas and code from CFQ, CFS and BFQ: 731e4c28dSVivek Goyal * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk> 831e4c28dSVivek Goyal * 931e4c28dSVivek Goyal * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it> 1031e4c28dSVivek Goyal * Paolo Valente <paolo.valente@unimore.it> 1131e4c28dSVivek Goyal * 1231e4c28dSVivek Goyal * Copyright (C) 2009 Vivek Goyal <vgoyal@redhat.com> 1331e4c28dSVivek Goyal * Nauman Rafique <nauman@google.com> 1431e4c28dSVivek Goyal */ 1531e4c28dSVivek Goyal 1631e4c28dSVivek Goyal #include <linux/cgroup.h> 17575969a0SVivek Goyal #include <linux/u64_stats_sync.h> 18829fdb50STejun Heo #include <linux/seq_file.h> 1931e4c28dSVivek Goyal 209355aedeSVivek Goyal /* Max limits for throttle policy */ 219355aedeSVivek Goyal #define THROTL_IOPS_MAX UINT_MAX 229355aedeSVivek Goyal 233381cb8dSTejun Heo /* CFQ specific, out here for blkcg->cfq_weight */ 243381cb8dSTejun Heo #define CFQ_WEIGHT_MIN 10 253381cb8dSTejun Heo #define CFQ_WEIGHT_MAX 1000 263381cb8dSTejun Heo #define CFQ_WEIGHT_DEFAULT 500 273381cb8dSTejun Heo 28f48ec1d7STejun Heo #ifdef CONFIG_BLK_CGROUP 29f48ec1d7STejun Heo 30edcb0722STejun Heo enum blkg_rwstat_type { 31edcb0722STejun Heo BLKG_RWSTAT_READ, 32edcb0722STejun Heo BLKG_RWSTAT_WRITE, 33edcb0722STejun Heo BLKG_RWSTAT_SYNC, 34edcb0722STejun Heo BLKG_RWSTAT_ASYNC, 35edcb0722STejun Heo 36edcb0722STejun Heo BLKG_RWSTAT_NR, 37edcb0722STejun Heo BLKG_RWSTAT_TOTAL = BLKG_RWSTAT_NR, 38303a3acbSDivyesh Shah }; 39303a3acbSDivyesh Shah 4031e4c28dSVivek Goyal struct blkio_cgroup { 4131e4c28dSVivek Goyal struct cgroup_subsys_state css; 4231e4c28dSVivek Goyal spinlock_t lock; 4331e4c28dSVivek Goyal struct hlist_head blkg_list; 449a9e8a26STejun Heo 459a9e8a26STejun Heo /* for policies to test whether associated blkcg has changed */ 469a9e8a26STejun Heo uint64_t id; 473381cb8dSTejun Heo 483381cb8dSTejun Heo /* TODO: per-policy storage in blkio_cgroup */ 493381cb8dSTejun Heo unsigned int cfq_weight; /* belongs to cfq */ 5031e4c28dSVivek Goyal }; 5131e4c28dSVivek Goyal 52edcb0722STejun Heo struct blkg_stat { 53edf1b879STejun Heo struct u64_stats_sync syncp; 54edcb0722STejun Heo uint64_t cnt; 55edcb0722STejun Heo }; 56edcb0722STejun Heo 57edcb0722STejun Heo struct blkg_rwstat { 58edcb0722STejun Heo struct u64_stats_sync syncp; 59edcb0722STejun Heo uint64_t cnt[BLKG_RWSTAT_NR]; 60edcb0722STejun Heo }; 61edcb0722STejun Heo 620381411eSTejun Heo /* per-blkg per-policy data */ 630381411eSTejun Heo struct blkg_policy_data { 640381411eSTejun Heo /* the blkg this per-policy data belongs to */ 650381411eSTejun Heo struct blkio_group *blkg; 660381411eSTejun Heo 670381411eSTejun Heo /* pol->pdata_size bytes of private data used by policy impl */ 680381411eSTejun Heo char pdata[] __aligned(__alignof__(unsigned long long)); 690381411eSTejun Heo }; 700381411eSTejun Heo 7131e4c28dSVivek Goyal struct blkio_group { 72c875f4d0STejun Heo /* Pointer to the associated request_queue */ 73c875f4d0STejun Heo struct request_queue *q; 74e8989faeSTejun Heo struct list_head q_node; 7531e4c28dSVivek Goyal struct hlist_node blkcg_node; 767ee9c562STejun Heo struct blkio_cgroup *blkcg; 772868ef7bSVivek Goyal /* Store cgroup path */ 782868ef7bSVivek Goyal char path[128]; 791adaf3ddSTejun Heo /* reference count */ 801adaf3ddSTejun Heo int refcnt; 8122084190SVivek Goyal 82*8bd435b3STejun Heo struct blkg_policy_data *pd[BLKCG_MAX_POLS]; 831adaf3ddSTejun Heo 841adaf3ddSTejun Heo struct rcu_head rcu_head; 8531e4c28dSVivek Goyal }; 8631e4c28dSVivek Goyal 870381411eSTejun Heo typedef void (blkio_init_group_fn)(struct blkio_group *blkg); 889ade5ea4STejun Heo typedef void (blkio_exit_group_fn)(struct blkio_group *blkg); 899ade5ea4STejun Heo typedef void (blkio_reset_group_stats_fn)(struct blkio_group *blkg); 903e252066SVivek Goyal 913e252066SVivek Goyal struct blkio_policy_ops { 920381411eSTejun Heo blkio_init_group_fn *blkio_init_group_fn; 939ade5ea4STejun Heo blkio_exit_group_fn *blkio_exit_group_fn; 949ade5ea4STejun Heo blkio_reset_group_stats_fn *blkio_reset_group_stats_fn; 953e252066SVivek Goyal }; 963e252066SVivek Goyal 973e252066SVivek Goyal struct blkio_policy_type { 983e252066SVivek Goyal struct blkio_policy_ops ops; 99*8bd435b3STejun Heo int plid; 1000381411eSTejun Heo size_t pdata_size; /* policy specific private data size */ 10144ea53deSTejun Heo struct cftype *cftypes; /* cgroup files for the policy */ 1023e252066SVivek Goyal }; 1033e252066SVivek Goyal 1045efd6113STejun Heo extern int blkcg_init_queue(struct request_queue *q); 1055efd6113STejun Heo extern void blkcg_drain_queue(struct request_queue *q); 1065efd6113STejun Heo extern void blkcg_exit_queue(struct request_queue *q); 1075efd6113STejun Heo 1083e252066SVivek Goyal /* Blkio controller policy registration */ 109*8bd435b3STejun Heo extern int blkio_policy_register(struct blkio_policy_type *); 1103e252066SVivek Goyal extern void blkio_policy_unregister(struct blkio_policy_type *); 111e8989faeSTejun Heo extern void blkg_destroy_all(struct request_queue *q, bool destroy_root); 112e8989faeSTejun Heo extern void update_root_blkg_pd(struct request_queue *q, 113ec399347STejun Heo const struct blkio_policy_type *pol); 1143e252066SVivek Goyal 115829fdb50STejun Heo void blkcg_print_blkgs(struct seq_file *sf, struct blkio_cgroup *blkcg, 116d366e7ecSTejun Heo u64 (*prfill)(struct seq_file *, void *, int), 117ec399347STejun Heo const struct blkio_policy_type *pol, int data, 118ec399347STejun Heo bool show_total); 119d366e7ecSTejun Heo u64 __blkg_prfill_u64(struct seq_file *sf, void *pdata, u64 v); 120d366e7ecSTejun Heo u64 __blkg_prfill_rwstat(struct seq_file *sf, void *pdata, 121829fdb50STejun Heo const struct blkg_rwstat *rwstat); 1225bc4afb1STejun Heo u64 blkg_prfill_stat(struct seq_file *sf, void *pdata, int off); 1235bc4afb1STejun Heo u64 blkg_prfill_rwstat(struct seq_file *sf, void *pdata, int off); 124829fdb50STejun Heo 125829fdb50STejun Heo struct blkg_conf_ctx { 126829fdb50STejun Heo struct gendisk *disk; 127829fdb50STejun Heo struct blkio_group *blkg; 128829fdb50STejun Heo u64 v; 129829fdb50STejun Heo }; 130829fdb50STejun Heo 131829fdb50STejun Heo int blkg_conf_prep(struct blkio_cgroup *blkcg, const char *input, 132829fdb50STejun Heo struct blkg_conf_ctx *ctx); 133829fdb50STejun Heo void blkg_conf_finish(struct blkg_conf_ctx *ctx); 134829fdb50STejun Heo 135829fdb50STejun Heo 1360381411eSTejun Heo /** 1370381411eSTejun Heo * blkg_to_pdata - get policy private data 1380381411eSTejun Heo * @blkg: blkg of interest 1390381411eSTejun Heo * @pol: policy of interest 1400381411eSTejun Heo * 1410381411eSTejun Heo * Return pointer to private data associated with the @blkg-@pol pair. 1420381411eSTejun Heo */ 1430381411eSTejun Heo static inline void *blkg_to_pdata(struct blkio_group *blkg, 1440381411eSTejun Heo struct blkio_policy_type *pol) 1450381411eSTejun Heo { 146549d3aa8STejun Heo return blkg ? blkg->pd[pol->plid]->pdata : NULL; 1470381411eSTejun Heo } 1480381411eSTejun Heo 1490381411eSTejun Heo /** 1500381411eSTejun Heo * pdata_to_blkg - get blkg associated with policy private data 1510381411eSTejun Heo * @pdata: policy private data of interest 1520381411eSTejun Heo * 153aaec55a0STejun Heo * @pdata is policy private data. Determine the blkg it's associated with. 1540381411eSTejun Heo */ 155aaec55a0STejun Heo static inline struct blkio_group *pdata_to_blkg(void *pdata) 1560381411eSTejun Heo { 1570381411eSTejun Heo if (pdata) { 1580381411eSTejun Heo struct blkg_policy_data *pd = 1590381411eSTejun Heo container_of(pdata, struct blkg_policy_data, pdata); 1600381411eSTejun Heo return pd->blkg; 1610381411eSTejun Heo } 1620381411eSTejun Heo return NULL; 1630381411eSTejun Heo } 1640381411eSTejun Heo 165afc24d49SVivek Goyal static inline char *blkg_path(struct blkio_group *blkg) 166afc24d49SVivek Goyal { 167afc24d49SVivek Goyal return blkg->path; 168afc24d49SVivek Goyal } 169afc24d49SVivek Goyal 1701adaf3ddSTejun Heo /** 1711adaf3ddSTejun Heo * blkg_get - get a blkg reference 1721adaf3ddSTejun Heo * @blkg: blkg to get 1731adaf3ddSTejun Heo * 1741adaf3ddSTejun Heo * The caller should be holding queue_lock and an existing reference. 1751adaf3ddSTejun Heo */ 1761adaf3ddSTejun Heo static inline void blkg_get(struct blkio_group *blkg) 1771adaf3ddSTejun Heo { 1781adaf3ddSTejun Heo lockdep_assert_held(blkg->q->queue_lock); 1791adaf3ddSTejun Heo WARN_ON_ONCE(!blkg->refcnt); 1801adaf3ddSTejun Heo blkg->refcnt++; 1811adaf3ddSTejun Heo } 1821adaf3ddSTejun Heo 1831adaf3ddSTejun Heo void __blkg_release(struct blkio_group *blkg); 1841adaf3ddSTejun Heo 1851adaf3ddSTejun Heo /** 1861adaf3ddSTejun Heo * blkg_put - put a blkg reference 1871adaf3ddSTejun Heo * @blkg: blkg to put 1881adaf3ddSTejun Heo * 1891adaf3ddSTejun Heo * The caller should be holding queue_lock. 1901adaf3ddSTejun Heo */ 1911adaf3ddSTejun Heo static inline void blkg_put(struct blkio_group *blkg) 1921adaf3ddSTejun Heo { 1931adaf3ddSTejun Heo lockdep_assert_held(blkg->q->queue_lock); 1941adaf3ddSTejun Heo WARN_ON_ONCE(blkg->refcnt <= 0); 1951adaf3ddSTejun Heo if (!--blkg->refcnt) 1961adaf3ddSTejun Heo __blkg_release(blkg); 1971adaf3ddSTejun Heo } 1981adaf3ddSTejun Heo 199edcb0722STejun Heo /** 200edcb0722STejun Heo * blkg_stat_add - add a value to a blkg_stat 201edcb0722STejun Heo * @stat: target blkg_stat 202edcb0722STejun Heo * @val: value to add 203edcb0722STejun Heo * 204edcb0722STejun Heo * Add @val to @stat. The caller is responsible for synchronizing calls to 205edcb0722STejun Heo * this function. 206edcb0722STejun Heo */ 207edcb0722STejun Heo static inline void blkg_stat_add(struct blkg_stat *stat, uint64_t val) 208edcb0722STejun Heo { 209edcb0722STejun Heo u64_stats_update_begin(&stat->syncp); 210edcb0722STejun Heo stat->cnt += val; 211edcb0722STejun Heo u64_stats_update_end(&stat->syncp); 212edcb0722STejun Heo } 213edcb0722STejun Heo 214edcb0722STejun Heo /** 215edcb0722STejun Heo * blkg_stat_read - read the current value of a blkg_stat 216edcb0722STejun Heo * @stat: blkg_stat to read 217edcb0722STejun Heo * 218edcb0722STejun Heo * Read the current value of @stat. This function can be called without 219edcb0722STejun Heo * synchroniztion and takes care of u64 atomicity. 220edcb0722STejun Heo */ 221edcb0722STejun Heo static inline uint64_t blkg_stat_read(struct blkg_stat *stat) 222edcb0722STejun Heo { 223edcb0722STejun Heo unsigned int start; 224edcb0722STejun Heo uint64_t v; 225edcb0722STejun Heo 226edcb0722STejun Heo do { 227edcb0722STejun Heo start = u64_stats_fetch_begin(&stat->syncp); 228edcb0722STejun Heo v = stat->cnt; 229edcb0722STejun Heo } while (u64_stats_fetch_retry(&stat->syncp, start)); 230edcb0722STejun Heo 231edcb0722STejun Heo return v; 232edcb0722STejun Heo } 233edcb0722STejun Heo 234edcb0722STejun Heo /** 235edcb0722STejun Heo * blkg_stat_reset - reset a blkg_stat 236edcb0722STejun Heo * @stat: blkg_stat to reset 237edcb0722STejun Heo */ 238edcb0722STejun Heo static inline void blkg_stat_reset(struct blkg_stat *stat) 239edcb0722STejun Heo { 240edcb0722STejun Heo stat->cnt = 0; 241edcb0722STejun Heo } 242edcb0722STejun Heo 243edcb0722STejun Heo /** 244edcb0722STejun Heo * blkg_rwstat_add - add a value to a blkg_rwstat 245edcb0722STejun Heo * @rwstat: target blkg_rwstat 246edcb0722STejun Heo * @rw: mask of REQ_{WRITE|SYNC} 247edcb0722STejun Heo * @val: value to add 248edcb0722STejun Heo * 249edcb0722STejun Heo * Add @val to @rwstat. The counters are chosen according to @rw. The 250edcb0722STejun Heo * caller is responsible for synchronizing calls to this function. 251edcb0722STejun Heo */ 252edcb0722STejun Heo static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, 253edcb0722STejun Heo int rw, uint64_t val) 254edcb0722STejun Heo { 255edcb0722STejun Heo u64_stats_update_begin(&rwstat->syncp); 256edcb0722STejun Heo 257edcb0722STejun Heo if (rw & REQ_WRITE) 258edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_WRITE] += val; 259edcb0722STejun Heo else 260edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_READ] += val; 261edcb0722STejun Heo if (rw & REQ_SYNC) 262edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_SYNC] += val; 263edcb0722STejun Heo else 264edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_ASYNC] += val; 265edcb0722STejun Heo 266edcb0722STejun Heo u64_stats_update_end(&rwstat->syncp); 267edcb0722STejun Heo } 268edcb0722STejun Heo 269edcb0722STejun Heo /** 270edcb0722STejun Heo * blkg_rwstat_read - read the current values of a blkg_rwstat 271edcb0722STejun Heo * @rwstat: blkg_rwstat to read 272edcb0722STejun Heo * 273edcb0722STejun Heo * Read the current snapshot of @rwstat and return it as the return value. 274edcb0722STejun Heo * This function can be called without synchronization and takes care of 275edcb0722STejun Heo * u64 atomicity. 276edcb0722STejun Heo */ 277edcb0722STejun Heo static struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat) 278edcb0722STejun Heo { 279edcb0722STejun Heo unsigned int start; 280edcb0722STejun Heo struct blkg_rwstat tmp; 281edcb0722STejun Heo 282edcb0722STejun Heo do { 283edcb0722STejun Heo start = u64_stats_fetch_begin(&rwstat->syncp); 284edcb0722STejun Heo tmp = *rwstat; 285edcb0722STejun Heo } while (u64_stats_fetch_retry(&rwstat->syncp, start)); 286edcb0722STejun Heo 287edcb0722STejun Heo return tmp; 288edcb0722STejun Heo } 289edcb0722STejun Heo 290edcb0722STejun Heo /** 291edcb0722STejun Heo * blkg_rwstat_sum - read the total count of a blkg_rwstat 292edcb0722STejun Heo * @rwstat: blkg_rwstat to read 293edcb0722STejun Heo * 294edcb0722STejun Heo * Return the total count of @rwstat regardless of the IO direction. This 295edcb0722STejun Heo * function can be called without synchronization and takes care of u64 296edcb0722STejun Heo * atomicity. 297edcb0722STejun Heo */ 298edcb0722STejun Heo static inline uint64_t blkg_rwstat_sum(struct blkg_rwstat *rwstat) 299edcb0722STejun Heo { 300edcb0722STejun Heo struct blkg_rwstat tmp = blkg_rwstat_read(rwstat); 301edcb0722STejun Heo 302edcb0722STejun Heo return tmp.cnt[BLKG_RWSTAT_READ] + tmp.cnt[BLKG_RWSTAT_WRITE]; 303edcb0722STejun Heo } 304edcb0722STejun Heo 305edcb0722STejun Heo /** 306edcb0722STejun Heo * blkg_rwstat_reset - reset a blkg_rwstat 307edcb0722STejun Heo * @rwstat: blkg_rwstat to reset 308edcb0722STejun Heo */ 309edcb0722STejun Heo static inline void blkg_rwstat_reset(struct blkg_rwstat *rwstat) 310edcb0722STejun Heo { 311edcb0722STejun Heo memset(rwstat->cnt, 0, sizeof(rwstat->cnt)); 312edcb0722STejun Heo } 313edcb0722STejun Heo 3142f5ea477SJens Axboe #else 3152f5ea477SJens Axboe 3162f5ea477SJens Axboe struct blkio_group { 3172f5ea477SJens Axboe }; 3182f5ea477SJens Axboe 3193e252066SVivek Goyal struct blkio_policy_type { 3203e252066SVivek Goyal }; 3213e252066SVivek Goyal 3225efd6113STejun Heo static inline int blkcg_init_queue(struct request_queue *q) { return 0; } 3235efd6113STejun Heo static inline void blkcg_drain_queue(struct request_queue *q) { } 3245efd6113STejun Heo static inline void blkcg_exit_queue(struct request_queue *q) { } 325*8bd435b3STejun Heo static inline int blkio_policy_register(struct blkio_policy_type *blkiop) { return 0; } 3263e252066SVivek Goyal static inline void blkio_policy_unregister(struct blkio_policy_type *blkiop) { } 32703aa264aSTejun Heo static inline void blkg_destroy_all(struct request_queue *q, 32803aa264aSTejun Heo bool destory_root) { } 329e8989faeSTejun Heo static inline void update_root_blkg_pd(struct request_queue *q, 330ec399347STejun Heo const struct blkio_policy_type *pol) { } 3313e252066SVivek Goyal 3320381411eSTejun Heo static inline void *blkg_to_pdata(struct blkio_group *blkg, 3330381411eSTejun Heo struct blkio_policy_type *pol) { return NULL; } 3340381411eSTejun Heo static inline struct blkio_group *pdata_to_blkg(void *pdata, 3350381411eSTejun Heo struct blkio_policy_type *pol) { return NULL; } 336afc24d49SVivek Goyal static inline char *blkg_path(struct blkio_group *blkg) { return NULL; } 3371adaf3ddSTejun Heo static inline void blkg_get(struct blkio_group *blkg) { } 3381adaf3ddSTejun Heo static inline void blkg_put(struct blkio_group *blkg) { } 339afc24d49SVivek Goyal 3402f5ea477SJens Axboe #endif 3412f5ea477SJens Axboe 34232e380aeSTejun Heo #ifdef CONFIG_BLK_CGROUP 34331e4c28dSVivek Goyal extern struct blkio_cgroup blkio_root_cgroup; 34431e4c28dSVivek Goyal extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup); 3454f85cb96STejun Heo extern struct blkio_cgroup *bio_blkio_cgroup(struct bio *bio); 346cd1604faSTejun Heo extern struct blkio_group *blkg_lookup(struct blkio_cgroup *blkcg, 347e8989faeSTejun Heo struct request_queue *q); 348cd1604faSTejun Heo struct blkio_group *blkg_lookup_create(struct blkio_cgroup *blkcg, 349cd1604faSTejun Heo struct request_queue *q, 350cd1604faSTejun Heo bool for_root); 35131e4c28dSVivek Goyal #else 3522f5ea477SJens Axboe struct cgroup; 35331e4c28dSVivek Goyal static inline struct blkio_cgroup * 35431e4c28dSVivek Goyal cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; } 35570087dc3SVivek Goyal static inline struct blkio_cgroup * 3564f85cb96STejun Heo bio_blkio_cgroup(struct bio *bio) { return NULL; } 35731e4c28dSVivek Goyal 358cd1604faSTejun Heo static inline struct blkio_group *blkg_lookup(struct blkio_cgroup *blkcg, 359cd1604faSTejun Heo void *key) { return NULL; } 36031e4c28dSVivek Goyal #endif 36131e4c28dSVivek Goyal #endif /* _BLK_CGROUP_H */ 362