aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2012-03-05 16:15:27 -0500
committerJens Axboe <axboe@kernel.dk>2012-03-06 15:27:24 -0500
commit852c788f8365062c8a383c5a93f7f7289977cb50 (patch)
tree561b69e7f2b6bcc16de165b3b988990de7913615 /fs
parentf6e8d01bee036460e03bd4f6a79d014f98ba712e (diff)
block: implement bio_associate_current()
IO scheduling and cgroup are tied to the issuing task via io_context and cgroup of %current. Unfortunately, there are cases where IOs need to be routed via a different task which makes scheduling and cgroup limit enforcement applied completely incorrectly. For example, all bios delayed by blk-throttle end up being issued by a delayed work item and get assigned the io_context of the worker task which happens to serve the work item and dumped to the default block cgroup. This is double confusing as bios which aren't delayed end up in the correct cgroup and makes using blk-throttle and cfq propio together impossible. Any code which punts IO issuing to another task is affected which is getting more and more common (e.g. btrfs). As both io_context and cgroup are firmly tied to task including userland visible APIs to manipulate them, it makes a lot of sense to match up tasks to bios. This patch implements bio_associate_current() which associates the specified bio with %current. The bio will record the associated ioc and blkcg at that point and block layer will use the recorded ones regardless of which task actually ends up issuing the bio. bio release puts the associated ioc and blkcg. It grabs and remembers ioc and blkcg instead of the task itself because task may already be dead by the time the bio is issued making ioc and blkcg inaccessible and those are all block layer cares about. elevator_set_req_fn() is updated such that the bio elvdata is being allocated for is available to the elevator. This doesn't update block cgroup policies yet. Further patches will implement the support. -v2: #ifdef CONFIG_BLK_CGROUP added around bio->bi_ioc dereference in rq_ioc() to fix build breakage. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Kent Overstreet <koverstreet@google.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs')
-rw-r--r--fs/bio.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/fs/bio.c b/fs/bio.c
index b980ecde026a..142214b80039 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -19,12 +19,14 @@
19#include <linux/swap.h> 19#include <linux/swap.h>
20#include <linux/bio.h> 20#include <linux/bio.h>
21#include <linux/blkdev.h> 21#include <linux/blkdev.h>
22#include <linux/iocontext.h>
22#include <linux/slab.h> 23#include <linux/slab.h>
23#include <linux/init.h> 24#include <linux/init.h>
24#include <linux/kernel.h> 25#include <linux/kernel.h>
25#include <linux/module.h> 26#include <linux/module.h>
26#include <linux/mempool.h> 27#include <linux/mempool.h>
27#include <linux/workqueue.h> 28#include <linux/workqueue.h>
29#include <linux/cgroup.h>
28#include <scsi/sg.h> /* for struct sg_iovec */ 30#include <scsi/sg.h> /* for struct sg_iovec */
29 31
30#include <trace/events/block.h> 32#include <trace/events/block.h>
@@ -418,6 +420,7 @@ void bio_put(struct bio *bio)
418 * last put frees it 420 * last put frees it
419 */ 421 */
420 if (atomic_dec_and_test(&bio->bi_cnt)) { 422 if (atomic_dec_and_test(&bio->bi_cnt)) {
423 bio_disassociate_task(bio);
421 bio->bi_next = NULL; 424 bio->bi_next = NULL;
422 bio->bi_destructor(bio); 425 bio->bi_destructor(bio);
423 } 426 }
@@ -1641,6 +1644,64 @@ bad:
1641} 1644}
1642EXPORT_SYMBOL(bioset_create); 1645EXPORT_SYMBOL(bioset_create);
1643 1646
1647#ifdef CONFIG_BLK_CGROUP
1648/**
1649 * bio_associate_current - associate a bio with %current
1650 * @bio: target bio
1651 *
1652 * Associate @bio with %current if it hasn't been associated yet. Block
1653 * layer will treat @bio as if it were issued by %current no matter which
1654 * task actually issues it.
1655 *
1656 * This function takes an extra reference of @task's io_context and blkcg
1657 * which will be put when @bio is released. The caller must own @bio,
1658 * ensure %current->io_context exists, and is responsible for synchronizing
1659 * calls to this function.
1660 */
1661int bio_associate_current(struct bio *bio)
1662{
1663 struct io_context *ioc;
1664 struct cgroup_subsys_state *css;
1665
1666 if (bio->bi_ioc)
1667 return -EBUSY;
1668
1669 ioc = current->io_context;
1670 if (!ioc)
1671 return -ENOENT;
1672
1673 /* acquire active ref on @ioc and associate */
1674 get_io_context_active(ioc);
1675 bio->bi_ioc = ioc;
1676
1677 /* associate blkcg if exists */
1678 rcu_read_lock();
1679 css = task_subsys_state(current, blkio_subsys_id);
1680 if (css && css_tryget(css))
1681 bio->bi_css = css;
1682 rcu_read_unlock();
1683
1684 return 0;
1685}
1686
1687/**
1688 * bio_disassociate_task - undo bio_associate_current()
1689 * @bio: target bio
1690 */
1691void bio_disassociate_task(struct bio *bio)
1692{
1693 if (bio->bi_ioc) {
1694 put_io_context(bio->bi_ioc);
1695 bio->bi_ioc = NULL;
1696 }
1697 if (bio->bi_css) {
1698 css_put(bio->bi_css);
1699 bio->bi_css = NULL;
1700 }
1701}
1702
1703#endif /* CONFIG_BLK_CGROUP */
1704
1644static void __init biovec_init_slabs(void) 1705static void __init biovec_init_slabs(void)
1645{ 1706{
1646 int i; 1707 int i;