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 20062a644dSVivek Goyal enum blkio_policy_id { 21062a644dSVivek Goyal BLKIO_POLICY_PROP = 0, /* Proportional Bandwidth division */ 224c9eefa1SVivek Goyal BLKIO_POLICY_THROTL, /* Throttling */ 23035d10b2STejun Heo 24035d10b2STejun Heo BLKIO_NR_POLICIES, 25062a644dSVivek Goyal }; 26062a644dSVivek Goyal 279355aedeSVivek Goyal /* Max limits for throttle policy */ 289355aedeSVivek Goyal #define THROTL_IOPS_MAX UINT_MAX 299355aedeSVivek Goyal 303381cb8dSTejun Heo /* CFQ specific, out here for blkcg->cfq_weight */ 313381cb8dSTejun Heo #define CFQ_WEIGHT_MIN 10 323381cb8dSTejun Heo #define CFQ_WEIGHT_MAX 1000 333381cb8dSTejun Heo #define CFQ_WEIGHT_DEFAULT 500 343381cb8dSTejun Heo 35*f48ec1d7STejun Heo #ifdef CONFIG_BLK_CGROUP 36*f48ec1d7STejun Heo 37edcb0722STejun Heo enum blkg_rwstat_type { 38edcb0722STejun Heo BLKG_RWSTAT_READ, 39edcb0722STejun Heo BLKG_RWSTAT_WRITE, 40edcb0722STejun Heo BLKG_RWSTAT_SYNC, 41edcb0722STejun Heo BLKG_RWSTAT_ASYNC, 42edcb0722STejun Heo 43edcb0722STejun Heo BLKG_RWSTAT_NR, 44edcb0722STejun Heo BLKG_RWSTAT_TOTAL = BLKG_RWSTAT_NR, 45303a3acbSDivyesh Shah }; 46303a3acbSDivyesh Shah 4731e4c28dSVivek Goyal struct blkio_cgroup { 4831e4c28dSVivek Goyal struct cgroup_subsys_state css; 4931e4c28dSVivek Goyal spinlock_t lock; 5031e4c28dSVivek Goyal struct hlist_head blkg_list; 519a9e8a26STejun Heo 529a9e8a26STejun Heo /* for policies to test whether associated blkcg has changed */ 539a9e8a26STejun Heo uint64_t id; 543381cb8dSTejun Heo 553381cb8dSTejun Heo /* TODO: per-policy storage in blkio_cgroup */ 563381cb8dSTejun Heo unsigned int cfq_weight; /* belongs to cfq */ 5731e4c28dSVivek Goyal }; 5831e4c28dSVivek Goyal 59edcb0722STejun Heo struct blkg_stat { 60edf1b879STejun Heo struct u64_stats_sync syncp; 61edcb0722STejun Heo uint64_t cnt; 62edcb0722STejun Heo }; 63edcb0722STejun Heo 64edcb0722STejun Heo struct blkg_rwstat { 65edcb0722STejun Heo struct u64_stats_sync syncp; 66edcb0722STejun Heo uint64_t cnt[BLKG_RWSTAT_NR]; 67edcb0722STejun Heo }; 68edcb0722STejun Heo 690381411eSTejun Heo /* per-blkg per-policy data */ 700381411eSTejun Heo struct blkg_policy_data { 710381411eSTejun Heo /* the blkg this per-policy data belongs to */ 720381411eSTejun Heo struct blkio_group *blkg; 730381411eSTejun Heo 740381411eSTejun Heo /* pol->pdata_size bytes of private data used by policy impl */ 750381411eSTejun Heo char pdata[] __aligned(__alignof__(unsigned long long)); 760381411eSTejun Heo }; 770381411eSTejun Heo 7831e4c28dSVivek Goyal struct blkio_group { 79c875f4d0STejun Heo /* Pointer to the associated request_queue */ 80c875f4d0STejun Heo struct request_queue *q; 81e8989faeSTejun Heo struct list_head q_node; 8231e4c28dSVivek Goyal struct hlist_node blkcg_node; 837ee9c562STejun Heo struct blkio_cgroup *blkcg; 842868ef7bSVivek Goyal /* Store cgroup path */ 852868ef7bSVivek Goyal char path[128]; 861adaf3ddSTejun Heo /* reference count */ 871adaf3ddSTejun Heo int refcnt; 8822084190SVivek Goyal 89549d3aa8STejun Heo struct blkg_policy_data *pd[BLKIO_NR_POLICIES]; 901adaf3ddSTejun Heo 911adaf3ddSTejun Heo struct rcu_head rcu_head; 9231e4c28dSVivek Goyal }; 9331e4c28dSVivek Goyal 940381411eSTejun Heo typedef void (blkio_init_group_fn)(struct blkio_group *blkg); 959ade5ea4STejun Heo typedef void (blkio_exit_group_fn)(struct blkio_group *blkg); 969ade5ea4STejun Heo typedef void (blkio_reset_group_stats_fn)(struct blkio_group *blkg); 973e252066SVivek Goyal 983e252066SVivek Goyal struct blkio_policy_ops { 990381411eSTejun Heo blkio_init_group_fn *blkio_init_group_fn; 1009ade5ea4STejun Heo blkio_exit_group_fn *blkio_exit_group_fn; 1019ade5ea4STejun Heo blkio_reset_group_stats_fn *blkio_reset_group_stats_fn; 1023e252066SVivek Goyal }; 1033e252066SVivek Goyal 1043e252066SVivek Goyal struct blkio_policy_type { 1053e252066SVivek Goyal struct list_head list; 1063e252066SVivek Goyal struct blkio_policy_ops ops; 107062a644dSVivek Goyal enum blkio_policy_id plid; 1080381411eSTejun Heo size_t pdata_size; /* policy specific private data size */ 10944ea53deSTejun Heo struct cftype *cftypes; /* cgroup files for the policy */ 1103e252066SVivek Goyal }; 1113e252066SVivek Goyal 1125efd6113STejun Heo extern int blkcg_init_queue(struct request_queue *q); 1135efd6113STejun Heo extern void blkcg_drain_queue(struct request_queue *q); 1145efd6113STejun Heo extern void blkcg_exit_queue(struct request_queue *q); 1155efd6113STejun Heo 1163e252066SVivek Goyal /* Blkio controller policy registration */ 1173e252066SVivek Goyal extern void blkio_policy_register(struct blkio_policy_type *); 1183e252066SVivek Goyal extern void blkio_policy_unregister(struct blkio_policy_type *); 119e8989faeSTejun Heo extern void blkg_destroy_all(struct request_queue *q, bool destroy_root); 120e8989faeSTejun Heo extern void update_root_blkg_pd(struct request_queue *q, 121e8989faeSTejun Heo enum blkio_policy_id plid); 1223e252066SVivek Goyal 123829fdb50STejun Heo void blkcg_print_blkgs(struct seq_file *sf, struct blkio_cgroup *blkcg, 124d366e7ecSTejun Heo u64 (*prfill)(struct seq_file *, void *, int), 125829fdb50STejun Heo int pol, int data, bool show_total); 126d366e7ecSTejun Heo u64 __blkg_prfill_u64(struct seq_file *sf, void *pdata, u64 v); 127d366e7ecSTejun Heo u64 __blkg_prfill_rwstat(struct seq_file *sf, void *pdata, 128829fdb50STejun Heo const struct blkg_rwstat *rwstat); 1295bc4afb1STejun Heo u64 blkg_prfill_stat(struct seq_file *sf, void *pdata, int off); 1305bc4afb1STejun Heo u64 blkg_prfill_rwstat(struct seq_file *sf, void *pdata, int off); 131829fdb50STejun Heo 132829fdb50STejun Heo struct blkg_conf_ctx { 133829fdb50STejun Heo struct gendisk *disk; 134829fdb50STejun Heo struct blkio_group *blkg; 135829fdb50STejun Heo u64 v; 136829fdb50STejun Heo }; 137829fdb50STejun Heo 138829fdb50STejun Heo int blkg_conf_prep(struct blkio_cgroup *blkcg, const char *input, 139829fdb50STejun Heo struct blkg_conf_ctx *ctx); 140829fdb50STejun Heo void blkg_conf_finish(struct blkg_conf_ctx *ctx); 141829fdb50STejun Heo 142829fdb50STejun Heo 1430381411eSTejun Heo /** 1440381411eSTejun Heo * blkg_to_pdata - get policy private data 1450381411eSTejun Heo * @blkg: blkg of interest 1460381411eSTejun Heo * @pol: policy of interest 1470381411eSTejun Heo * 1480381411eSTejun Heo * Return pointer to private data associated with the @blkg-@pol pair. 1490381411eSTejun Heo */ 1500381411eSTejun Heo static inline void *blkg_to_pdata(struct blkio_group *blkg, 1510381411eSTejun Heo struct blkio_policy_type *pol) 1520381411eSTejun Heo { 153549d3aa8STejun Heo return blkg ? blkg->pd[pol->plid]->pdata : NULL; 1540381411eSTejun Heo } 1550381411eSTejun Heo 1560381411eSTejun Heo /** 1570381411eSTejun Heo * pdata_to_blkg - get blkg associated with policy private data 1580381411eSTejun Heo * @pdata: policy private data of interest 1590381411eSTejun Heo * 160aaec55a0STejun Heo * @pdata is policy private data. Determine the blkg it's associated with. 1610381411eSTejun Heo */ 162aaec55a0STejun Heo static inline struct blkio_group *pdata_to_blkg(void *pdata) 1630381411eSTejun Heo { 1640381411eSTejun Heo if (pdata) { 1650381411eSTejun Heo struct blkg_policy_data *pd = 1660381411eSTejun Heo container_of(pdata, struct blkg_policy_data, pdata); 1670381411eSTejun Heo return pd->blkg; 1680381411eSTejun Heo } 1690381411eSTejun Heo return NULL; 1700381411eSTejun Heo } 1710381411eSTejun Heo 172afc24d49SVivek Goyal static inline char *blkg_path(struct blkio_group *blkg) 173afc24d49SVivek Goyal { 174afc24d49SVivek Goyal return blkg->path; 175afc24d49SVivek Goyal } 176afc24d49SVivek Goyal 1771adaf3ddSTejun Heo /** 1781adaf3ddSTejun Heo * blkg_get - get a blkg reference 1791adaf3ddSTejun Heo * @blkg: blkg to get 1801adaf3ddSTejun Heo * 1811adaf3ddSTejun Heo * The caller should be holding queue_lock and an existing reference. 1821adaf3ddSTejun Heo */ 1831adaf3ddSTejun Heo static inline void blkg_get(struct blkio_group *blkg) 1841adaf3ddSTejun Heo { 1851adaf3ddSTejun Heo lockdep_assert_held(blkg->q->queue_lock); 1861adaf3ddSTejun Heo WARN_ON_ONCE(!blkg->refcnt); 1871adaf3ddSTejun Heo blkg->refcnt++; 1881adaf3ddSTejun Heo } 1891adaf3ddSTejun Heo 1901adaf3ddSTejun Heo void __blkg_release(struct blkio_group *blkg); 1911adaf3ddSTejun Heo 1921adaf3ddSTejun Heo /** 1931adaf3ddSTejun Heo * blkg_put - put a blkg reference 1941adaf3ddSTejun Heo * @blkg: blkg to put 1951adaf3ddSTejun Heo * 1961adaf3ddSTejun Heo * The caller should be holding queue_lock. 1971adaf3ddSTejun Heo */ 1981adaf3ddSTejun Heo static inline void blkg_put(struct blkio_group *blkg) 1991adaf3ddSTejun Heo { 2001adaf3ddSTejun Heo lockdep_assert_held(blkg->q->queue_lock); 2011adaf3ddSTejun Heo WARN_ON_ONCE(blkg->refcnt <= 0); 2021adaf3ddSTejun Heo if (!--blkg->refcnt) 2031adaf3ddSTejun Heo __blkg_release(blkg); 2041adaf3ddSTejun Heo } 2051adaf3ddSTejun Heo 206edcb0722STejun Heo /** 207edcb0722STejun Heo * blkg_stat_add - add a value to a blkg_stat 208edcb0722STejun Heo * @stat: target blkg_stat 209edcb0722STejun Heo * @val: value to add 210edcb0722STejun Heo * 211edcb0722STejun Heo * Add @val to @stat. The caller is responsible for synchronizing calls to 212edcb0722STejun Heo * this function. 213edcb0722STejun Heo */ 214edcb0722STejun Heo static inline void blkg_stat_add(struct blkg_stat *stat, uint64_t val) 215edcb0722STejun Heo { 216edcb0722STejun Heo u64_stats_update_begin(&stat->syncp); 217edcb0722STejun Heo stat->cnt += val; 218edcb0722STejun Heo u64_stats_update_end(&stat->syncp); 219edcb0722STejun Heo } 220edcb0722STejun Heo 221edcb0722STejun Heo /** 222edcb0722STejun Heo * blkg_stat_read - read the current value of a blkg_stat 223edcb0722STejun Heo * @stat: blkg_stat to read 224edcb0722STejun Heo * 225edcb0722STejun Heo * Read the current value of @stat. This function can be called without 226edcb0722STejun Heo * synchroniztion and takes care of u64 atomicity. 227edcb0722STejun Heo */ 228edcb0722STejun Heo static inline uint64_t blkg_stat_read(struct blkg_stat *stat) 229edcb0722STejun Heo { 230edcb0722STejun Heo unsigned int start; 231edcb0722STejun Heo uint64_t v; 232edcb0722STejun Heo 233edcb0722STejun Heo do { 234edcb0722STejun Heo start = u64_stats_fetch_begin(&stat->syncp); 235edcb0722STejun Heo v = stat->cnt; 236edcb0722STejun Heo } while (u64_stats_fetch_retry(&stat->syncp, start)); 237edcb0722STejun Heo 238edcb0722STejun Heo return v; 239edcb0722STejun Heo } 240edcb0722STejun Heo 241edcb0722STejun Heo /** 242edcb0722STejun Heo * blkg_stat_reset - reset a blkg_stat 243edcb0722STejun Heo * @stat: blkg_stat to reset 244edcb0722STejun Heo */ 245edcb0722STejun Heo static inline void blkg_stat_reset(struct blkg_stat *stat) 246edcb0722STejun Heo { 247edcb0722STejun Heo stat->cnt = 0; 248edcb0722STejun Heo } 249edcb0722STejun Heo 250edcb0722STejun Heo /** 251edcb0722STejun Heo * blkg_rwstat_add - add a value to a blkg_rwstat 252edcb0722STejun Heo * @rwstat: target blkg_rwstat 253edcb0722STejun Heo * @rw: mask of REQ_{WRITE|SYNC} 254edcb0722STejun Heo * @val: value to add 255edcb0722STejun Heo * 256edcb0722STejun Heo * Add @val to @rwstat. The counters are chosen according to @rw. The 257edcb0722STejun Heo * caller is responsible for synchronizing calls to this function. 258edcb0722STejun Heo */ 259edcb0722STejun Heo static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, 260edcb0722STejun Heo int rw, uint64_t val) 261edcb0722STejun Heo { 262edcb0722STejun Heo u64_stats_update_begin(&rwstat->syncp); 263edcb0722STejun Heo 264edcb0722STejun Heo if (rw & REQ_WRITE) 265edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_WRITE] += val; 266edcb0722STejun Heo else 267edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_READ] += val; 268edcb0722STejun Heo if (rw & REQ_SYNC) 269edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_SYNC] += val; 270edcb0722STejun Heo else 271edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_ASYNC] += val; 272edcb0722STejun Heo 273edcb0722STejun Heo u64_stats_update_end(&rwstat->syncp); 274edcb0722STejun Heo } 275edcb0722STejun Heo 276edcb0722STejun Heo /** 277edcb0722STejun Heo * blkg_rwstat_read - read the current values of a blkg_rwstat 278edcb0722STejun Heo * @rwstat: blkg_rwstat to read 279edcb0722STejun Heo * 280edcb0722STejun Heo * Read the current snapshot of @rwstat and return it as the return value. 281edcb0722STejun Heo * This function can be called without synchronization and takes care of 282edcb0722STejun Heo * u64 atomicity. 283edcb0722STejun Heo */ 284edcb0722STejun Heo static struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat) 285edcb0722STejun Heo { 286edcb0722STejun Heo unsigned int start; 287edcb0722STejun Heo struct blkg_rwstat tmp; 288edcb0722STejun Heo 289edcb0722STejun Heo do { 290edcb0722STejun Heo start = u64_stats_fetch_begin(&rwstat->syncp); 291edcb0722STejun Heo tmp = *rwstat; 292edcb0722STejun Heo } while (u64_stats_fetch_retry(&rwstat->syncp, start)); 293edcb0722STejun Heo 294edcb0722STejun Heo return tmp; 295edcb0722STejun Heo } 296edcb0722STejun Heo 297edcb0722STejun Heo /** 298edcb0722STejun Heo * blkg_rwstat_sum - read the total count of a blkg_rwstat 299edcb0722STejun Heo * @rwstat: blkg_rwstat to read 300edcb0722STejun Heo * 301edcb0722STejun Heo * Return the total count of @rwstat regardless of the IO direction. This 302edcb0722STejun Heo * function can be called without synchronization and takes care of u64 303edcb0722STejun Heo * atomicity. 304edcb0722STejun Heo */ 305edcb0722STejun Heo static inline uint64_t blkg_rwstat_sum(struct blkg_rwstat *rwstat) 306edcb0722STejun Heo { 307edcb0722STejun Heo struct blkg_rwstat tmp = blkg_rwstat_read(rwstat); 308edcb0722STejun Heo 309edcb0722STejun Heo return tmp.cnt[BLKG_RWSTAT_READ] + tmp.cnt[BLKG_RWSTAT_WRITE]; 310edcb0722STejun Heo } 311edcb0722STejun Heo 312edcb0722STejun Heo /** 313edcb0722STejun Heo * blkg_rwstat_reset - reset a blkg_rwstat 314edcb0722STejun Heo * @rwstat: blkg_rwstat to reset 315edcb0722STejun Heo */ 316edcb0722STejun Heo static inline void blkg_rwstat_reset(struct blkg_rwstat *rwstat) 317edcb0722STejun Heo { 318edcb0722STejun Heo memset(rwstat->cnt, 0, sizeof(rwstat->cnt)); 319edcb0722STejun Heo } 320edcb0722STejun Heo 3212f5ea477SJens Axboe #else 3222f5ea477SJens Axboe 3232f5ea477SJens Axboe struct blkio_group { 3242f5ea477SJens Axboe }; 3252f5ea477SJens Axboe 3263e252066SVivek Goyal struct blkio_policy_type { 3273e252066SVivek Goyal }; 3283e252066SVivek Goyal 3295efd6113STejun Heo static inline int blkcg_init_queue(struct request_queue *q) { return 0; } 3305efd6113STejun Heo static inline void blkcg_drain_queue(struct request_queue *q) { } 3315efd6113STejun Heo static inline void blkcg_exit_queue(struct request_queue *q) { } 3323e252066SVivek Goyal static inline void blkio_policy_register(struct blkio_policy_type *blkiop) { } 3333e252066SVivek Goyal static inline void blkio_policy_unregister(struct blkio_policy_type *blkiop) { } 33403aa264aSTejun Heo static inline void blkg_destroy_all(struct request_queue *q, 33503aa264aSTejun Heo bool destory_root) { } 336e8989faeSTejun Heo static inline void update_root_blkg_pd(struct request_queue *q, 337e8989faeSTejun Heo enum blkio_policy_id plid) { } 3383e252066SVivek Goyal 3390381411eSTejun Heo static inline void *blkg_to_pdata(struct blkio_group *blkg, 3400381411eSTejun Heo struct blkio_policy_type *pol) { return NULL; } 3410381411eSTejun Heo static inline struct blkio_group *pdata_to_blkg(void *pdata, 3420381411eSTejun Heo struct blkio_policy_type *pol) { return NULL; } 343afc24d49SVivek Goyal static inline char *blkg_path(struct blkio_group *blkg) { return NULL; } 3441adaf3ddSTejun Heo static inline void blkg_get(struct blkio_group *blkg) { } 3451adaf3ddSTejun Heo static inline void blkg_put(struct blkio_group *blkg) { } 346afc24d49SVivek Goyal 3472f5ea477SJens Axboe #endif 3482f5ea477SJens Axboe 34932e380aeSTejun Heo #ifdef CONFIG_BLK_CGROUP 35031e4c28dSVivek Goyal extern struct blkio_cgroup blkio_root_cgroup; 35131e4c28dSVivek Goyal extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup); 3524f85cb96STejun Heo extern struct blkio_cgroup *bio_blkio_cgroup(struct bio *bio); 353cd1604faSTejun Heo extern struct blkio_group *blkg_lookup(struct blkio_cgroup *blkcg, 354e8989faeSTejun Heo struct request_queue *q); 355cd1604faSTejun Heo struct blkio_group *blkg_lookup_create(struct blkio_cgroup *blkcg, 356cd1604faSTejun Heo struct request_queue *q, 357cd1604faSTejun Heo bool for_root); 35831e4c28dSVivek Goyal #else 3592f5ea477SJens Axboe struct cgroup; 36031e4c28dSVivek Goyal static inline struct blkio_cgroup * 36131e4c28dSVivek Goyal cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; } 36270087dc3SVivek Goyal static inline struct blkio_cgroup * 3634f85cb96STejun Heo bio_blkio_cgroup(struct bio *bio) { return NULL; } 36431e4c28dSVivek Goyal 365cd1604faSTejun Heo static inline struct blkio_group *blkg_lookup(struct blkio_cgroup *blkcg, 366cd1604faSTejun Heo void *key) { return NULL; } 36731e4c28dSVivek Goyal #endif 36831e4c28dSVivek Goyal #endif /* _BLK_CGROUP_H */ 369