aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-06-26 18:05:44 -0400
committerJens Axboe <axboe@kernel.dk>2012-06-26 18:42:49 -0400
commita051661ca6d134c18599498b185b667859d4339b (patch)
tree9d840030874aed9b97a58051bf9568455126e8e8 /include/linux
parent5b788ce3e2acac9bf109743b1281d77347cf2101 (diff)
blkcg: implement per-blkg request allocation
Currently, request_queue has one request_list to allocate requests from regardless of blkcg of the IO being issued. When the unified request pool is used up, cfq proportional IO limits become meaningless - whoever grabs the next request being freed wins the race regardless of the configured weights. This can be easily demonstrated by creating a blkio cgroup w/ very low weight, put a program which can issue a lot of random direct IOs there and running a sequential IO from a different cgroup. As soon as the request pool is used up, the sequential IO bandwidth crashes. This patch implements per-blkg request_list. Each blkg has its own request_list and any IO allocates its request from the matching blkg making blkcgs completely isolated in terms of request allocation. * Root blkcg uses the request_list embedded in each request_queue, which was renamed to @q->root_rl from @q->rq. While making blkcg rl handling a bit harier, this enables avoiding most overhead for root blkcg. * Queue fullness is properly per request_list but bdi isn't blkcg aware yet, so congestion state currently just follows the root blkcg. As writeback isn't aware of blkcg yet, this works okay for async congestion but readahead may get the wrong signals. It's better than blkcg completely collapsing with shared request_list but needs to be improved with future changes. * After this change, each block cgroup gets a full request pool making resource consumption of each cgroup higher. This makes allowing non-root users to create cgroups less desirable; however, note that allowing non-root users to directly manage cgroups is already severely broken regardless of this patch - each block cgroup consumes kernel memory and skews IO weight (IO weights are not hierarchical). v2: queue-sysfs.txt updated and patch description udpated as suggested by Vivek. v3: blk_get_rl() wasn't checking error return from blkg_lookup_create() and may cause oops on lookup failure. Fix it by falling back to root_rl on blkg lookup failures. This problem was spotted by Rakesh Iyer <rni@google.com>. v4: Updated to accomodate 458f27a982 "block: Avoid missed wakeup in request waitqueue". blk_drain_queue() now wakes up waiters on all blkg->rl on the target queue. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Vivek Goyal <vgoyal@redhat.com> Cc: Wu Fengguang <fengguang.wu@intel.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/blkdev.h12
1 files changed, 9 insertions, 3 deletions
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index f2385ee7c7b2..3816ce8a08fc 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -51,7 +51,9 @@ typedef void (rq_end_io_fn)(struct request *, int);
51 51
52struct request_list { 52struct request_list {
53 struct request_queue *q; /* the queue this rl belongs to */ 53 struct request_queue *q; /* the queue this rl belongs to */
54 54#ifdef CONFIG_BLK_CGROUP
55 struct blkcg_gq *blkg; /* blkg this request pool belongs to */
56#endif
55 /* 57 /*
56 * count[], starved[], and wait[] are indexed by 58 * count[], starved[], and wait[] are indexed by
57 * BLK_RW_SYNC/BLK_RW_ASYNC 59 * BLK_RW_SYNC/BLK_RW_ASYNC
@@ -143,6 +145,7 @@ struct request {
143 struct hd_struct *part; 145 struct hd_struct *part;
144 unsigned long start_time; 146 unsigned long start_time;
145#ifdef CONFIG_BLK_CGROUP 147#ifdef CONFIG_BLK_CGROUP
148 struct request_list *rl; /* rl this rq is alloced from */
146 unsigned long long start_time_ns; 149 unsigned long long start_time_ns;
147 unsigned long long io_start_time_ns; /* when passed to hardware */ 150 unsigned long long io_start_time_ns; /* when passed to hardware */
148#endif 151#endif
@@ -291,9 +294,12 @@ struct request_queue {
291 int nr_rqs_elvpriv; /* # allocated rqs w/ elvpriv */ 294 int nr_rqs_elvpriv; /* # allocated rqs w/ elvpriv */
292 295
293 /* 296 /*
294 * the queue request freelist, one for reads and one for writes 297 * If blkcg is not used, @q->root_rl serves all requests. If blkcg
298 * is used, root blkg allocates from @q->root_rl and all other
299 * blkgs from their own blkg->rl. Which one to use should be
300 * determined using bio_request_list().
295 */ 301 */
296 struct request_list rq; 302 struct request_list root_rl;
297 303
298 request_fn_proc *request_fn; 304 request_fn_proc *request_fn;
299 make_request_fn *make_request_fn; 305 make_request_fn *make_request_fn;