Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[platform/kernel/linux-starfive.git] / include / linux / blk-cgroup.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _BLK_CGROUP_H
3 #define _BLK_CGROUP_H
4 /*
5  * Common Block IO controller cgroup interface
6  *
7  * Based on ideas and code from CFQ, CFS and BFQ:
8  * Copyright (C) 2003 Jens Axboe <axboe@kernel.dk>
9  *
10  * Copyright (C) 2008 Fabio Checconi <fabio@gandalf.sssup.it>
11  *                    Paolo Valente <paolo.valente@unimore.it>
12  *
13  * Copyright (C) 2009 Vivek Goyal <vgoyal@redhat.com>
14  *                    Nauman Rafique <nauman@google.com>
15  */
16
17 #include <linux/cgroup.h>
18 #include <linux/percpu.h>
19 #include <linux/percpu_counter.h>
20 #include <linux/u64_stats_sync.h>
21 #include <linux/seq_file.h>
22 #include <linux/radix-tree.h>
23 #include <linux/blkdev.h>
24 #include <linux/atomic.h>
25 #include <linux/kthread.h>
26 #include <linux/fs.h>
27
28 #define FC_APPID_LEN              129
29
30 #ifdef CONFIG_BLK_CGROUP
31
32 enum blkg_iostat_type {
33         BLKG_IOSTAT_READ,
34         BLKG_IOSTAT_WRITE,
35         BLKG_IOSTAT_DISCARD,
36
37         BLKG_IOSTAT_NR,
38 };
39
40 struct blkcg_gq;
41 struct blkg_policy_data;
42
43 struct blkcg {
44         struct cgroup_subsys_state      css;
45         spinlock_t                      lock;
46         refcount_t                      online_pin;
47
48         struct radix_tree_root          blkg_tree;
49         struct blkcg_gq __rcu           *blkg_hint;
50         struct hlist_head               blkg_list;
51
52         struct blkcg_policy_data        *cpd[BLKCG_MAX_POLS];
53
54         struct list_head                all_blkcgs_node;
55 #ifdef CONFIG_BLK_CGROUP_FC_APPID
56         char                            fc_app_id[FC_APPID_LEN];
57 #endif
58 #ifdef CONFIG_CGROUP_WRITEBACK
59         struct list_head                cgwb_list;
60 #endif
61 };
62
63 struct blkg_iostat {
64         u64                             bytes[BLKG_IOSTAT_NR];
65         u64                             ios[BLKG_IOSTAT_NR];
66 };
67
68 struct blkg_iostat_set {
69         struct u64_stats_sync           sync;
70         struct blkg_iostat              cur;
71         struct blkg_iostat              last;
72 };
73
74 /* association between a blk cgroup and a request queue */
75 struct blkcg_gq {
76         /* Pointer to the associated request_queue */
77         struct request_queue            *q;
78         struct list_head                q_node;
79         struct hlist_node               blkcg_node;
80         struct blkcg                    *blkcg;
81
82         /* all non-root blkcg_gq's are guaranteed to have access to parent */
83         struct blkcg_gq                 *parent;
84
85         /* reference count */
86         struct percpu_ref               refcnt;
87
88         /* is this blkg online? protected by both blkcg and q locks */
89         bool                            online;
90
91         struct blkg_iostat_set __percpu *iostat_cpu;
92         struct blkg_iostat_set          iostat;
93
94         struct blkg_policy_data         *pd[BLKCG_MAX_POLS];
95
96         spinlock_t                      async_bio_lock;
97         struct bio_list                 async_bios;
98         struct work_struct              async_bio_work;
99
100         atomic_t                        use_delay;
101         atomic64_t                      delay_nsec;
102         atomic64_t                      delay_start;
103         u64                             last_delay;
104         int                             last_use;
105
106         struct rcu_head                 rcu_head;
107 };
108
109 extern struct cgroup_subsys_state * const blkcg_root_css;
110
111 void blkcg_destroy_blkgs(struct blkcg *blkcg);
112 void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay);
113 void blkcg_maybe_throttle_current(void);
114
115 static inline struct blkcg *css_to_blkcg(struct cgroup_subsys_state *css)
116 {
117         return css ? container_of(css, struct blkcg, css) : NULL;
118 }
119
120 /**
121  * bio_blkcg - grab the blkcg associated with a bio
122  * @bio: target bio
123  *
124  * This returns the blkcg associated with a bio, %NULL if not associated.
125  * Callers are expected to either handle %NULL or know association has been
126  * done prior to calling this.
127  */
128 static inline struct blkcg *bio_blkcg(struct bio *bio)
129 {
130         if (bio && bio->bi_blkg)
131                 return bio->bi_blkg->blkcg;
132         return NULL;
133 }
134
135 static inline bool blk_cgroup_congested(void)
136 {
137         struct cgroup_subsys_state *css;
138         bool ret = false;
139
140         rcu_read_lock();
141         css = kthread_blkcg();
142         if (!css)
143                 css = task_css(current, io_cgrp_id);
144         while (css) {
145                 if (atomic_read(&css->cgroup->congestion_count)) {
146                         ret = true;
147                         break;
148                 }
149                 css = css->parent;
150         }
151         rcu_read_unlock();
152         return ret;
153 }
154
155 /**
156  * blkcg_parent - get the parent of a blkcg
157  * @blkcg: blkcg of interest
158  *
159  * Return the parent blkcg of @blkcg.  Can be called anytime.
160  */
161 static inline struct blkcg *blkcg_parent(struct blkcg *blkcg)
162 {
163         return css_to_blkcg(blkcg->css.parent);
164 }
165
166 /**
167  * blkcg_pin_online - pin online state
168  * @blkcg: blkcg of interest
169  *
170  * While pinned, a blkcg is kept online.  This is primarily used to
171  * impedance-match blkg and cgwb lifetimes so that blkg doesn't go offline
172  * while an associated cgwb is still active.
173  */
174 static inline void blkcg_pin_online(struct blkcg *blkcg)
175 {
176         refcount_inc(&blkcg->online_pin);
177 }
178
179 /**
180  * blkcg_unpin_online - unpin online state
181  * @blkcg: blkcg of interest
182  *
183  * This is primarily used to impedance-match blkg and cgwb lifetimes so
184  * that blkg doesn't go offline while an associated cgwb is still active.
185  * When this count goes to zero, all active cgwbs have finished so the
186  * blkcg can continue destruction by calling blkcg_destroy_blkgs().
187  */
188 static inline void blkcg_unpin_online(struct blkcg *blkcg)
189 {
190         do {
191                 if (!refcount_dec_and_test(&blkcg->online_pin))
192                         break;
193                 blkcg_destroy_blkgs(blkcg);
194                 blkcg = blkcg_parent(blkcg);
195         } while (blkcg);
196 }
197
198 #else   /* CONFIG_BLK_CGROUP */
199
200 struct blkcg {
201 };
202
203 struct blkcg_gq {
204 };
205
206 #define blkcg_root_css  ((struct cgroup_subsys_state *)ERR_PTR(-EINVAL))
207
208 static inline void blkcg_maybe_throttle_current(void) { }
209 static inline bool blk_cgroup_congested(void) { return false; }
210
211 #ifdef CONFIG_BLOCK
212 static inline void blkcg_schedule_throttle(struct request_queue *q, bool use_memdelay) { }
213 static inline struct blkcg *bio_blkcg(struct bio *bio) { return NULL; }
214 #endif /* CONFIG_BLOCK */
215
216 #endif  /* CONFIG_BLK_CGROUP */
217
218 #ifdef CONFIG_BLK_CGROUP_FC_APPID
219 /*
220  * Sets the fc_app_id field associted to blkcg
221  * @app_id: application identifier
222  * @cgrp_id: cgroup id
223  * @app_id_len: size of application identifier
224  */
225 static inline int blkcg_set_fc_appid(char *app_id, u64 cgrp_id, size_t app_id_len)
226 {
227         struct cgroup *cgrp;
228         struct cgroup_subsys_state *css;
229         struct blkcg *blkcg;
230         int ret  = 0;
231
232         if (app_id_len > FC_APPID_LEN)
233                 return -EINVAL;
234
235         cgrp = cgroup_get_from_id(cgrp_id);
236         if (!cgrp)
237                 return -ENOENT;
238         css = cgroup_get_e_css(cgrp, &io_cgrp_subsys);
239         if (!css) {
240                 ret = -ENOENT;
241                 goto out_cgrp_put;
242         }
243         blkcg = css_to_blkcg(css);
244         /*
245          * There is a slight race condition on setting the appid.
246          * Worst case an I/O may not find the right id.
247          * This is no different from the I/O we let pass while obtaining
248          * the vmid from the fabric.
249          * Adding the overhead of a lock is not necessary.
250          */
251         strlcpy(blkcg->fc_app_id, app_id, app_id_len);
252         css_put(css);
253 out_cgrp_put:
254         cgroup_put(cgrp);
255         return ret;
256 }
257
258 /**
259  * blkcg_get_fc_appid - get the fc app identifier associated with a bio
260  * @bio: target bio
261  *
262  * On success return the fc_app_id, on failure return NULL
263  */
264 static inline char *blkcg_get_fc_appid(struct bio *bio)
265 {
266         if (bio && bio->bi_blkg &&
267                 (bio->bi_blkg->blkcg->fc_app_id[0] != '\0'))
268                 return bio->bi_blkg->blkcg->fc_app_id;
269         return NULL;
270 }
271 #else
272 static inline int blkcg_set_fc_appid(char *buf, u64 id, size_t len) { return -EINVAL; }
273 static inline char *blkcg_get_fc_appid(struct bio *bio) { return NULL; }
274 #endif /*CONFIG_BLK_CGROUP_FC_APPID*/
275 #endif  /* _BLK_CGROUP_H */