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 67a2b1693bSTejun Heo /* used during policy activation */ 68a2b1693bSTejun Heo struct list_head alloc_node; 69a2b1693bSTejun Heo 700381411eSTejun Heo /* pol->pdata_size bytes of private data used by policy impl */ 710381411eSTejun Heo char pdata[] __aligned(__alignof__(unsigned long long)); 720381411eSTejun Heo }; 730381411eSTejun Heo 7431e4c28dSVivek Goyal struct blkio_group { 75c875f4d0STejun Heo /* Pointer to the associated request_queue */ 76c875f4d0STejun Heo struct request_queue *q; 77e8989faeSTejun Heo struct list_head q_node; 7831e4c28dSVivek Goyal struct hlist_node blkcg_node; 797ee9c562STejun Heo struct blkio_cgroup *blkcg; 802868ef7bSVivek Goyal /* Store cgroup path */ 812868ef7bSVivek Goyal char path[128]; 821adaf3ddSTejun Heo /* reference count */ 831adaf3ddSTejun Heo int refcnt; 8422084190SVivek Goyal 858bd435b3STejun Heo struct blkg_policy_data *pd[BLKCG_MAX_POLS]; 861adaf3ddSTejun Heo 871adaf3ddSTejun Heo struct rcu_head rcu_head; 8831e4c28dSVivek Goyal }; 8931e4c28dSVivek Goyal 900381411eSTejun Heo typedef void (blkio_init_group_fn)(struct blkio_group *blkg); 919ade5ea4STejun Heo typedef void (blkio_exit_group_fn)(struct blkio_group *blkg); 929ade5ea4STejun Heo typedef void (blkio_reset_group_stats_fn)(struct blkio_group *blkg); 933e252066SVivek Goyal 943e252066SVivek Goyal struct blkio_policy_ops { 950381411eSTejun Heo blkio_init_group_fn *blkio_init_group_fn; 969ade5ea4STejun Heo blkio_exit_group_fn *blkio_exit_group_fn; 979ade5ea4STejun Heo blkio_reset_group_stats_fn *blkio_reset_group_stats_fn; 983e252066SVivek Goyal }; 993e252066SVivek Goyal 1003e252066SVivek Goyal struct blkio_policy_type { 1013e252066SVivek Goyal struct blkio_policy_ops ops; 1028bd435b3STejun Heo int plid; 1030381411eSTejun Heo size_t pdata_size; /* policy specific private data size */ 10444ea53deSTejun Heo struct cftype *cftypes; /* cgroup files for the policy */ 1053e252066SVivek Goyal }; 1063e252066SVivek Goyal 1075efd6113STejun Heo extern int blkcg_init_queue(struct request_queue *q); 1085efd6113STejun Heo extern void blkcg_drain_queue(struct request_queue *q); 1095efd6113STejun Heo extern void blkcg_exit_queue(struct request_queue *q); 1105efd6113STejun Heo 1113e252066SVivek Goyal /* Blkio controller policy registration */ 1128bd435b3STejun Heo extern int blkio_policy_register(struct blkio_policy_type *); 1133e252066SVivek Goyal extern void blkio_policy_unregister(struct blkio_policy_type *); 114a2b1693bSTejun Heo extern int blkcg_activate_policy(struct request_queue *q, 115ec399347STejun Heo const struct blkio_policy_type *pol); 116a2b1693bSTejun Heo extern void blkcg_deactivate_policy(struct request_queue *q, 117a2b1693bSTejun Heo const struct blkio_policy_type *pol); 1183e252066SVivek Goyal 119829fdb50STejun Heo void blkcg_print_blkgs(struct seq_file *sf, struct blkio_cgroup *blkcg, 120d366e7ecSTejun Heo u64 (*prfill)(struct seq_file *, void *, int), 121ec399347STejun Heo const struct blkio_policy_type *pol, int data, 122ec399347STejun Heo bool show_total); 123d366e7ecSTejun Heo u64 __blkg_prfill_u64(struct seq_file *sf, void *pdata, u64 v); 124d366e7ecSTejun Heo u64 __blkg_prfill_rwstat(struct seq_file *sf, void *pdata, 125829fdb50STejun Heo const struct blkg_rwstat *rwstat); 1265bc4afb1STejun Heo u64 blkg_prfill_stat(struct seq_file *sf, void *pdata, int off); 1275bc4afb1STejun Heo u64 blkg_prfill_rwstat(struct seq_file *sf, void *pdata, int off); 128829fdb50STejun Heo 129829fdb50STejun Heo struct blkg_conf_ctx { 130829fdb50STejun Heo struct gendisk *disk; 131829fdb50STejun Heo struct blkio_group *blkg; 132829fdb50STejun Heo u64 v; 133829fdb50STejun Heo }; 134829fdb50STejun Heo 135da8b0662STejun Heo int blkg_conf_prep(struct blkio_cgroup *blkcg, 136da8b0662STejun Heo const struct blkio_policy_type *pol, const char *input, 137829fdb50STejun Heo struct blkg_conf_ctx *ctx); 138829fdb50STejun Heo void blkg_conf_finish(struct blkg_conf_ctx *ctx); 139829fdb50STejun Heo 140829fdb50STejun Heo 1410381411eSTejun Heo /** 1420381411eSTejun Heo * blkg_to_pdata - get policy private data 1430381411eSTejun Heo * @blkg: blkg of interest 1440381411eSTejun Heo * @pol: policy of interest 1450381411eSTejun Heo * 1460381411eSTejun Heo * Return pointer to private data associated with the @blkg-@pol pair. 1470381411eSTejun Heo */ 1480381411eSTejun Heo static inline void *blkg_to_pdata(struct blkio_group *blkg, 1490381411eSTejun Heo struct blkio_policy_type *pol) 1500381411eSTejun Heo { 151549d3aa8STejun Heo return blkg ? blkg->pd[pol->plid]->pdata : NULL; 1520381411eSTejun Heo } 1530381411eSTejun Heo 1540381411eSTejun Heo /** 1550381411eSTejun Heo * pdata_to_blkg - get blkg associated with policy private data 1560381411eSTejun Heo * @pdata: policy private data of interest 1570381411eSTejun Heo * 158aaec55a0STejun Heo * @pdata is policy private data. Determine the blkg it's associated with. 1590381411eSTejun Heo */ 160aaec55a0STejun Heo static inline struct blkio_group *pdata_to_blkg(void *pdata) 1610381411eSTejun Heo { 1620381411eSTejun Heo if (pdata) { 1630381411eSTejun Heo struct blkg_policy_data *pd = 1640381411eSTejun Heo container_of(pdata, struct blkg_policy_data, pdata); 1650381411eSTejun Heo return pd->blkg; 1660381411eSTejun Heo } 1670381411eSTejun Heo return NULL; 1680381411eSTejun Heo } 1690381411eSTejun Heo 170afc24d49SVivek Goyal static inline char *blkg_path(struct blkio_group *blkg) 171afc24d49SVivek Goyal { 172afc24d49SVivek Goyal return blkg->path; 173afc24d49SVivek Goyal } 174afc24d49SVivek Goyal 1751adaf3ddSTejun Heo /** 1761adaf3ddSTejun Heo * blkg_get - get a blkg reference 1771adaf3ddSTejun Heo * @blkg: blkg to get 1781adaf3ddSTejun Heo * 1791adaf3ddSTejun Heo * The caller should be holding queue_lock and an existing reference. 1801adaf3ddSTejun Heo */ 1811adaf3ddSTejun Heo static inline void blkg_get(struct blkio_group *blkg) 1821adaf3ddSTejun Heo { 1831adaf3ddSTejun Heo lockdep_assert_held(blkg->q->queue_lock); 1841adaf3ddSTejun Heo WARN_ON_ONCE(!blkg->refcnt); 1851adaf3ddSTejun Heo blkg->refcnt++; 1861adaf3ddSTejun Heo } 1871adaf3ddSTejun Heo 1881adaf3ddSTejun Heo void __blkg_release(struct blkio_group *blkg); 1891adaf3ddSTejun Heo 1901adaf3ddSTejun Heo /** 1911adaf3ddSTejun Heo * blkg_put - put a blkg reference 1921adaf3ddSTejun Heo * @blkg: blkg to put 1931adaf3ddSTejun Heo * 1941adaf3ddSTejun Heo * The caller should be holding queue_lock. 1951adaf3ddSTejun Heo */ 1961adaf3ddSTejun Heo static inline void blkg_put(struct blkio_group *blkg) 1971adaf3ddSTejun Heo { 1981adaf3ddSTejun Heo lockdep_assert_held(blkg->q->queue_lock); 1991adaf3ddSTejun Heo WARN_ON_ONCE(blkg->refcnt <= 0); 2001adaf3ddSTejun Heo if (!--blkg->refcnt) 2011adaf3ddSTejun Heo __blkg_release(blkg); 2021adaf3ddSTejun Heo } 2031adaf3ddSTejun Heo 204edcb0722STejun Heo /** 205edcb0722STejun Heo * blkg_stat_add - add a value to a blkg_stat 206edcb0722STejun Heo * @stat: target blkg_stat 207edcb0722STejun Heo * @val: value to add 208edcb0722STejun Heo * 209edcb0722STejun Heo * Add @val to @stat. The caller is responsible for synchronizing calls to 210edcb0722STejun Heo * this function. 211edcb0722STejun Heo */ 212edcb0722STejun Heo static inline void blkg_stat_add(struct blkg_stat *stat, uint64_t val) 213edcb0722STejun Heo { 214edcb0722STejun Heo u64_stats_update_begin(&stat->syncp); 215edcb0722STejun Heo stat->cnt += val; 216edcb0722STejun Heo u64_stats_update_end(&stat->syncp); 217edcb0722STejun Heo } 218edcb0722STejun Heo 219edcb0722STejun Heo /** 220edcb0722STejun Heo * blkg_stat_read - read the current value of a blkg_stat 221edcb0722STejun Heo * @stat: blkg_stat to read 222edcb0722STejun Heo * 223edcb0722STejun Heo * Read the current value of @stat. This function can be called without 224edcb0722STejun Heo * synchroniztion and takes care of u64 atomicity. 225edcb0722STejun Heo */ 226edcb0722STejun Heo static inline uint64_t blkg_stat_read(struct blkg_stat *stat) 227edcb0722STejun Heo { 228edcb0722STejun Heo unsigned int start; 229edcb0722STejun Heo uint64_t v; 230edcb0722STejun Heo 231edcb0722STejun Heo do { 232edcb0722STejun Heo start = u64_stats_fetch_begin(&stat->syncp); 233edcb0722STejun Heo v = stat->cnt; 234edcb0722STejun Heo } while (u64_stats_fetch_retry(&stat->syncp, start)); 235edcb0722STejun Heo 236edcb0722STejun Heo return v; 237edcb0722STejun Heo } 238edcb0722STejun Heo 239edcb0722STejun Heo /** 240edcb0722STejun Heo * blkg_stat_reset - reset a blkg_stat 241edcb0722STejun Heo * @stat: blkg_stat to reset 242edcb0722STejun Heo */ 243edcb0722STejun Heo static inline void blkg_stat_reset(struct blkg_stat *stat) 244edcb0722STejun Heo { 245edcb0722STejun Heo stat->cnt = 0; 246edcb0722STejun Heo } 247edcb0722STejun Heo 248edcb0722STejun Heo /** 249edcb0722STejun Heo * blkg_rwstat_add - add a value to a blkg_rwstat 250edcb0722STejun Heo * @rwstat: target blkg_rwstat 251edcb0722STejun Heo * @rw: mask of REQ_{WRITE|SYNC} 252edcb0722STejun Heo * @val: value to add 253edcb0722STejun Heo * 254edcb0722STejun Heo * Add @val to @rwstat. The counters are chosen according to @rw. The 255edcb0722STejun Heo * caller is responsible for synchronizing calls to this function. 256edcb0722STejun Heo */ 257edcb0722STejun Heo static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, 258edcb0722STejun Heo int rw, uint64_t val) 259edcb0722STejun Heo { 260edcb0722STejun Heo u64_stats_update_begin(&rwstat->syncp); 261edcb0722STejun Heo 262edcb0722STejun Heo if (rw & REQ_WRITE) 263edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_WRITE] += val; 264edcb0722STejun Heo else 265edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_READ] += val; 266edcb0722STejun Heo if (rw & REQ_SYNC) 267edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_SYNC] += val; 268edcb0722STejun Heo else 269edcb0722STejun Heo rwstat->cnt[BLKG_RWSTAT_ASYNC] += val; 270edcb0722STejun Heo 271edcb0722STejun Heo u64_stats_update_end(&rwstat->syncp); 272edcb0722STejun Heo } 273edcb0722STejun Heo 274edcb0722STejun Heo /** 275edcb0722STejun Heo * blkg_rwstat_read - read the current values of a blkg_rwstat 276edcb0722STejun Heo * @rwstat: blkg_rwstat to read 277edcb0722STejun Heo * 278edcb0722STejun Heo * Read the current snapshot of @rwstat and return it as the return value. 279edcb0722STejun Heo * This function can be called without synchronization and takes care of 280edcb0722STejun Heo * u64 atomicity. 281edcb0722STejun Heo */ 282*c94bed89STejun Heo static inline struct blkg_rwstat blkg_rwstat_read(struct blkg_rwstat *rwstat) 283edcb0722STejun Heo { 284edcb0722STejun Heo unsigned int start; 285edcb0722STejun Heo struct blkg_rwstat tmp; 286edcb0722STejun Heo 287edcb0722STejun Heo do { 288edcb0722STejun Heo start = u64_stats_fetch_begin(&rwstat->syncp); 289edcb0722STejun Heo tmp = *rwstat; 290edcb0722STejun Heo } while (u64_stats_fetch_retry(&rwstat->syncp, start)); 291edcb0722STejun Heo 292edcb0722STejun Heo return tmp; 293edcb0722STejun Heo } 294edcb0722STejun Heo 295edcb0722STejun Heo /** 296edcb0722STejun Heo * blkg_rwstat_sum - read the total count of a blkg_rwstat 297edcb0722STejun Heo * @rwstat: blkg_rwstat to read 298edcb0722STejun Heo * 299edcb0722STejun Heo * Return the total count of @rwstat regardless of the IO direction. This 300edcb0722STejun Heo * function can be called without synchronization and takes care of u64 301edcb0722STejun Heo * atomicity. 302edcb0722STejun Heo */ 303edcb0722STejun Heo static inline uint64_t blkg_rwstat_sum(struct blkg_rwstat *rwstat) 304edcb0722STejun Heo { 305edcb0722STejun Heo struct blkg_rwstat tmp = blkg_rwstat_read(rwstat); 306edcb0722STejun Heo 307edcb0722STejun Heo return tmp.cnt[BLKG_RWSTAT_READ] + tmp.cnt[BLKG_RWSTAT_WRITE]; 308edcb0722STejun Heo } 309edcb0722STejun Heo 310edcb0722STejun Heo /** 311edcb0722STejun Heo * blkg_rwstat_reset - reset a blkg_rwstat 312edcb0722STejun Heo * @rwstat: blkg_rwstat to reset 313edcb0722STejun Heo */ 314edcb0722STejun Heo static inline void blkg_rwstat_reset(struct blkg_rwstat *rwstat) 315edcb0722STejun Heo { 316edcb0722STejun Heo memset(rwstat->cnt, 0, sizeof(rwstat->cnt)); 317edcb0722STejun Heo } 318edcb0722STejun Heo 3192f5ea477SJens Axboe #else 3202f5ea477SJens Axboe 3212f5ea477SJens Axboe struct blkio_group { 3222f5ea477SJens Axboe }; 3232f5ea477SJens Axboe 3243e252066SVivek Goyal struct blkio_policy_type { 3253e252066SVivek Goyal }; 3263e252066SVivek Goyal 3275efd6113STejun Heo static inline int blkcg_init_queue(struct request_queue *q) { return 0; } 3285efd6113STejun Heo static inline void blkcg_drain_queue(struct request_queue *q) { } 3295efd6113STejun Heo static inline void blkcg_exit_queue(struct request_queue *q) { } 3308bd435b3STejun Heo static inline int blkio_policy_register(struct blkio_policy_type *blkiop) { return 0; } 3313e252066SVivek Goyal static inline void blkio_policy_unregister(struct blkio_policy_type *blkiop) { } 332a2b1693bSTejun Heo static inline int blkcg_activate_policy(struct request_queue *q, 333a2b1693bSTejun Heo const struct blkio_policy_type *pol) { return 0; } 334a2b1693bSTejun Heo static inline void blkcg_deactivate_policy(struct request_queue *q, 335a2b1693bSTejun Heo const struct blkio_policy_type *pol) { } 3363e252066SVivek Goyal 3370381411eSTejun Heo static inline void *blkg_to_pdata(struct blkio_group *blkg, 3380381411eSTejun Heo struct blkio_policy_type *pol) { return NULL; } 3390381411eSTejun Heo static inline struct blkio_group *pdata_to_blkg(void *pdata, 3400381411eSTejun Heo struct blkio_policy_type *pol) { return NULL; } 341afc24d49SVivek Goyal static inline char *blkg_path(struct blkio_group *blkg) { return NULL; } 3421adaf3ddSTejun Heo static inline void blkg_get(struct blkio_group *blkg) { } 3431adaf3ddSTejun Heo static inline void blkg_put(struct blkio_group *blkg) { } 344afc24d49SVivek Goyal 3452f5ea477SJens Axboe #endif 3462f5ea477SJens Axboe 34732e380aeSTejun Heo #ifdef CONFIG_BLK_CGROUP 34831e4c28dSVivek Goyal extern struct blkio_cgroup blkio_root_cgroup; 34931e4c28dSVivek Goyal extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup); 3504f85cb96STejun Heo extern struct blkio_cgroup *bio_blkio_cgroup(struct bio *bio); 351cd1604faSTejun Heo extern struct blkio_group *blkg_lookup(struct blkio_cgroup *blkcg, 352e8989faeSTejun Heo struct request_queue *q); 353cd1604faSTejun Heo struct blkio_group *blkg_lookup_create(struct blkio_cgroup *blkcg, 3543c96cb32STejun Heo struct request_queue *q); 35531e4c28dSVivek Goyal #else 3562f5ea477SJens Axboe struct cgroup; 35731e4c28dSVivek Goyal static inline struct blkio_cgroup * 35831e4c28dSVivek Goyal cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; } 35970087dc3SVivek Goyal static inline struct blkio_cgroup * 3604f85cb96STejun Heo bio_blkio_cgroup(struct bio *bio) { return NULL; } 36131e4c28dSVivek Goyal 362cd1604faSTejun Heo static inline struct blkio_group *blkg_lookup(struct blkio_cgroup *blkcg, 363cd1604faSTejun Heo void *key) { return NULL; } 36431e4c28dSVivek Goyal #endif 36531e4c28dSVivek Goyal #endif /* _BLK_CGROUP_H */ 366