1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2eea8f41cSTejun Heo #ifndef _BLK_CGROUP_H 3eea8f41cSTejun Heo #define _BLK_CGROUP_H 4eea8f41cSTejun Heo /* 5eea8f41cSTejun Heo * Common Block IO controller cgroup interface 6eea8f41cSTejun Heo * 7eea8f41cSTejun Heo * Based on ideas and code from CFQ, CFS and BFQ: 8eea8f41cSTejun Heo * Copyright (C) 2003 Jens Axboe <[email protected]> 9eea8f41cSTejun Heo * 10eea8f41cSTejun Heo * Copyright (C) 2008 Fabio Checconi <[email protected]> 11eea8f41cSTejun Heo * Paolo Valente <[email protected]> 12eea8f41cSTejun Heo * 13eea8f41cSTejun Heo * Copyright (C) 2009 Vivek Goyal <[email protected]> 14eea8f41cSTejun Heo * Nauman Rafique <[email protected]> 15eea8f41cSTejun Heo */ 16eea8f41cSTejun Heo 17eea8f41cSTejun Heo #include <linux/cgroup.h> 18f7331648STejun Heo #include <linux/percpu.h> 1924bdb8efSTejun Heo #include <linux/percpu_counter.h> 20f7331648STejun Heo #include <linux/u64_stats_sync.h> 21eea8f41cSTejun Heo #include <linux/seq_file.h> 22eea8f41cSTejun Heo #include <linux/radix-tree.h> 23eea8f41cSTejun Heo #include <linux/blkdev.h> 24eea8f41cSTejun Heo #include <linux/atomic.h> 25902ec5b6SShaohua Li #include <linux/kthread.h> 265cdf2e3fSDennis Zhou #include <linux/fs.h> 27eea8f41cSTejun Heo 28d2bcbeabSMuneendra Kumar #define FC_APPID_LEN 129 29d2bcbeabSMuneendra Kumar 30eea8f41cSTejun Heo #ifdef CONFIG_BLK_CGROUP 31eea8f41cSTejun Heo 32f7331648STejun Heo enum blkg_iostat_type { 33f7331648STejun Heo BLKG_IOSTAT_READ, 34f7331648STejun Heo BLKG_IOSTAT_WRITE, 35f7331648STejun Heo BLKG_IOSTAT_DISCARD, 36f7331648STejun Heo 37f7331648STejun Heo BLKG_IOSTAT_NR, 38f7331648STejun Heo }; 39f7331648STejun Heo 40eea8f41cSTejun Heo struct blkcg_gq; 41672fdcf0SMing Lei struct blkg_policy_data; 42eea8f41cSTejun Heo 43eea8f41cSTejun Heo struct blkcg { 44eea8f41cSTejun Heo struct cgroup_subsys_state css; 45eea8f41cSTejun Heo spinlock_t lock; 46d866dbf6STejun Heo refcount_t online_pin; 47eea8f41cSTejun Heo 48eea8f41cSTejun Heo struct radix_tree_root blkg_tree; 4955679c8dSBart Van Assche struct blkcg_gq __rcu *blkg_hint; 50eea8f41cSTejun Heo struct hlist_head blkg_list; 51eea8f41cSTejun Heo 5281437648STejun Heo struct blkcg_policy_data *cpd[BLKCG_MAX_POLS]; 5352ebea74STejun Heo 547876f930STejun Heo struct list_head all_blkcgs_node; 55d2bcbeabSMuneendra Kumar #ifdef CONFIG_BLK_CGROUP_FC_APPID 56d2bcbeabSMuneendra Kumar char fc_app_id[FC_APPID_LEN]; 57d2bcbeabSMuneendra Kumar #endif 5852ebea74STejun Heo #ifdef CONFIG_CGROUP_WRITEBACK 5952ebea74STejun Heo struct list_head cgwb_list; 6052ebea74STejun Heo #endif 61eea8f41cSTejun Heo }; 62eea8f41cSTejun Heo 63f7331648STejun Heo struct blkg_iostat { 64f7331648STejun Heo u64 bytes[BLKG_IOSTAT_NR]; 65f7331648STejun Heo u64 ios[BLKG_IOSTAT_NR]; 66f7331648STejun Heo }; 67f7331648STejun Heo 68f7331648STejun Heo struct blkg_iostat_set { 69f7331648STejun Heo struct u64_stats_sync sync; 70f7331648STejun Heo struct blkg_iostat cur; 71f7331648STejun Heo struct blkg_iostat last; 72f7331648STejun Heo }; 73f7331648STejun Heo 74eea8f41cSTejun Heo /* association between a blk cgroup and a request queue */ 75eea8f41cSTejun Heo struct blkcg_gq { 76eea8f41cSTejun Heo /* Pointer to the associated request_queue */ 77eea8f41cSTejun Heo struct request_queue *q; 78eea8f41cSTejun Heo struct list_head q_node; 79eea8f41cSTejun Heo struct hlist_node blkcg_node; 80eea8f41cSTejun Heo struct blkcg *blkcg; 81eea8f41cSTejun Heo 82eea8f41cSTejun Heo /* all non-root blkcg_gq's are guaranteed to have access to parent */ 83eea8f41cSTejun Heo struct blkcg_gq *parent; 84eea8f41cSTejun Heo 85eea8f41cSTejun Heo /* reference count */ 867fcf2b03SDennis Zhou struct percpu_ref refcnt; 87eea8f41cSTejun Heo 88eea8f41cSTejun Heo /* is this blkg online? protected by both blkcg and q locks */ 89eea8f41cSTejun Heo bool online; 90eea8f41cSTejun Heo 91f7331648STejun Heo struct blkg_iostat_set __percpu *iostat_cpu; 92f7331648STejun Heo struct blkg_iostat_set iostat; 9377ea7338STejun Heo 94eea8f41cSTejun Heo struct blkg_policy_data *pd[BLKCG_MAX_POLS]; 95eea8f41cSTejun Heo 96d3f77dfdSTejun Heo spinlock_t async_bio_lock; 97d3f77dfdSTejun Heo struct bio_list async_bios; 98d578c770SMing Lei union { 99d3f77dfdSTejun Heo struct work_struct async_bio_work; 100d578c770SMing Lei struct work_struct free_work; 101d578c770SMing Lei }; 102d09d8df3SJosef Bacik 103d09d8df3SJosef Bacik atomic_t use_delay; 104d09d8df3SJosef Bacik atomic64_t delay_nsec; 105d09d8df3SJosef Bacik atomic64_t delay_start; 106d09d8df3SJosef Bacik u64 last_delay; 107d09d8df3SJosef Bacik int last_use; 108d3f77dfdSTejun Heo 109d3f77dfdSTejun Heo struct rcu_head rcu_head; 110eea8f41cSTejun Heo }; 111eea8f41cSTejun Heo 112496d5e75STejun Heo extern struct cgroup_subsys_state * const blkcg_root_css; 113eea8f41cSTejun Heo 114672fdcf0SMing Lei void blkcg_destroy_blkgs(struct blkcg *blkcg); 115672fdcf0SMing Lei void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay); 116672fdcf0SMing Lei void blkcg_maybe_throttle_current(void); 1170fe061b9SDennis Zhou 118eea8f41cSTejun Heo static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css) 119eea8f41cSTejun Heo { 120eea8f41cSTejun Heo return css ? container_of(css, struct blkcg, css) : NULL; 121eea8f41cSTejun Heo } 122eea8f41cSTejun Heo 1230fe061b9SDennis Zhou /** 1240fe061b9SDennis Zhou * bio_blkcg - grab the blkcg associated with a bio 1250fe061b9SDennis Zhou * @bio: target bio 1260fe061b9SDennis Zhou * 1270fe061b9SDennis Zhou * This returns the blkcg associated with a bio, %NULL if not associated. 1280fe061b9SDennis Zhou * Callers are expected to either handle %NULL or know association has been 1290fe061b9SDennis Zhou * done prior to calling this. 1300fe061b9SDennis Zhou */ 1310fe061b9SDennis Zhou static inline struct blkcg *bio_blkcg(struct bio *bio) 1320fe061b9SDennis Zhou { 133db6638d7SDennis Zhou if (bio && bio->bi_blkg) 134db6638d7SDennis Zhou return bio->bi_blkg->blkcg; 1350fe061b9SDennis Zhou return NULL; 136fd383c2dSTejun Heo } 137fd383c2dSTejun Heo 138d09d8df3SJosef Bacik static inline bool blk_cgroup_congested(void) 139d09d8df3SJosef Bacik { 140d09d8df3SJosef Bacik struct cgroup_subsys_state *css; 141d09d8df3SJosef Bacik bool ret = false; 142d09d8df3SJosef Bacik 143d09d8df3SJosef Bacik rcu_read_lock(); 144d09d8df3SJosef Bacik css = kthread_blkcg(); 145d09d8df3SJosef Bacik if (!css) 146d09d8df3SJosef Bacik css = task_css(current, io_cgrp_id); 147d09d8df3SJosef Bacik while (css) { 148d09d8df3SJosef Bacik if (atomic_read(&css->cgroup->congestion_count)) { 149d09d8df3SJosef Bacik ret = true; 150d09d8df3SJosef Bacik break; 151d09d8df3SJosef Bacik } 152d09d8df3SJosef Bacik css = css->parent; 153d09d8df3SJosef Bacik } 154d09d8df3SJosef Bacik rcu_read_unlock(); 155d09d8df3SJosef Bacik return ret; 156d09d8df3SJosef Bacik } 157d09d8df3SJosef Bacik 158eea8f41cSTejun Heo /** 159eea8f41cSTejun Heo * blkcg_parent - get the parent of a blkcg 160eea8f41cSTejun Heo * @blkcg: blkcg of interest 161eea8f41cSTejun Heo * 162eea8f41cSTejun Heo * Return the parent blkcg of @blkcg. Can be called anytime. 163eea8f41cSTejun Heo */ 164eea8f41cSTejun Heo static inline struct blkcg *blkcg_parent(struct blkcg *blkcg) 165eea8f41cSTejun Heo { 166eea8f41cSTejun Heo return css_to_blkcg(blkcg->css.parent); 167eea8f41cSTejun Heo } 168eea8f41cSTejun Heo 169eea8f41cSTejun Heo /** 170d866dbf6STejun Heo * blkcg_pin_online - pin online state 17159b57717SDennis Zhou (Facebook) * @blkcg: blkcg of interest 17259b57717SDennis Zhou (Facebook) * 173d866dbf6STejun Heo * While pinned, a blkcg is kept online. This is primarily used to 174d866dbf6STejun Heo * impedance-match blkg and cgwb lifetimes so that blkg doesn't go offline 175d866dbf6STejun Heo * while an associated cgwb is still active. 17659b57717SDennis Zhou (Facebook) */ 177d866dbf6STejun Heo static inline void blkcg_pin_online(struct blkcg *blkcg) 17859b57717SDennis Zhou (Facebook) { 179d866dbf6STejun Heo refcount_inc(&blkcg->online_pin); 18059b57717SDennis Zhou (Facebook) } 18159b57717SDennis Zhou (Facebook) 18259b57717SDennis Zhou (Facebook) /** 183d866dbf6STejun Heo * blkcg_unpin_online - unpin online state 18459b57717SDennis Zhou (Facebook) * @blkcg: blkcg of interest 18559b57717SDennis Zhou (Facebook) * 186d866dbf6STejun Heo * This is primarily used to impedance-match blkg and cgwb lifetimes so 187d866dbf6STejun Heo * that blkg doesn't go offline while an associated cgwb is still active. 188d866dbf6STejun Heo * When this count goes to zero, all active cgwbs have finished so the 18959b57717SDennis Zhou (Facebook) * blkcg can continue destruction by calling blkcg_destroy_blkgs(). 19059b57717SDennis Zhou (Facebook) */ 191d866dbf6STejun Heo static inline void blkcg_unpin_online(struct blkcg *blkcg) 19259b57717SDennis Zhou (Facebook) { 1934308a434STejun Heo do { 1944308a434STejun Heo if (!refcount_dec_and_test(&blkcg->online_pin)) 1954308a434STejun Heo break; 19659b57717SDennis Zhou (Facebook) blkcg_destroy_blkgs(blkcg); 1974308a434STejun Heo blkcg = blkcg_parent(blkcg); 1984308a434STejun Heo } while (blkcg); 19959b57717SDennis Zhou (Facebook) } 20059b57717SDennis Zhou (Facebook) 201eea8f41cSTejun Heo #else /* CONFIG_BLK_CGROUP */ 202eea8f41cSTejun Heo 203efa7d1c7STejun Heo struct blkcg { 204efa7d1c7STejun Heo }; 205eea8f41cSTejun Heo 206eea8f41cSTejun Heo struct blkcg_gq { 207eea8f41cSTejun Heo }; 208eea8f41cSTejun Heo 209496d5e75STejun Heo #define blkcg_root_css ((struct cgroup_subsys_state *)ERR_PTR(-EINVAL)) 210496d5e75STejun Heo 211d09d8df3SJosef Bacik static inline void blkcg_maybe_throttle_current(void) { } 212d09d8df3SJosef Bacik static inline bool blk_cgroup_congested(void) { return false; } 213d09d8df3SJosef Bacik 214efa7d1c7STejun Heo #ifdef CONFIG_BLOCK 215d09d8df3SJosef Bacik static inline void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay) { } 216eea8f41cSTejun Heo static inline struct blkcg *bio_blkcg(struct bio *bio) { return NULL; } 217efa7d1c7STejun Heo #endif /* CONFIG_BLOCK */ 218672fdcf0SMing Lei 219eea8f41cSTejun Heo #endif /* CONFIG_BLK_CGROUP */ 220d2bcbeabSMuneendra Kumar 221*db056284SChristoph Hellwig int blkcg_set_fc_appid(char *app_id, u64 cgrp_id, size_t app_id_len); 222*db056284SChristoph Hellwig char *blkcg_get_fc_appid(struct bio *bio); 223d2bcbeabSMuneendra Kumar 224eea8f41cSTejun Heo #endif /* _BLK_CGROUP_H */ 225