diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bio.c | 61 | ||||
-rw-r--r-- | fs/ioprio.c | 2 | ||||
-rw-r--r-- | fs/splice.c | 4 |
3 files changed, 64 insertions, 3 deletions
@@ -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/export.h> | 26 | #include <linux/export.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 | } |
@@ -1646,6 +1649,64 @@ bad: | |||
1646 | } | 1649 | } |
1647 | EXPORT_SYMBOL(bioset_create); | 1650 | EXPORT_SYMBOL(bioset_create); |
1648 | 1651 | ||
1652 | #ifdef CONFIG_BLK_CGROUP | ||
1653 | /** | ||
1654 | * bio_associate_current - associate a bio with %current | ||
1655 | * @bio: target bio | ||
1656 | * | ||
1657 | * Associate @bio with %current if it hasn't been associated yet. Block | ||
1658 | * layer will treat @bio as if it were issued by %current no matter which | ||
1659 | * task actually issues it. | ||
1660 | * | ||
1661 | * This function takes an extra reference of @task's io_context and blkcg | ||
1662 | * which will be put when @bio is released. The caller must own @bio, | ||
1663 | * ensure %current->io_context exists, and is responsible for synchronizing | ||
1664 | * calls to this function. | ||
1665 | */ | ||
1666 | int bio_associate_current(struct bio *bio) | ||
1667 | { | ||
1668 | struct io_context *ioc; | ||
1669 | struct cgroup_subsys_state *css; | ||
1670 | |||
1671 | if (bio->bi_ioc) | ||
1672 | return -EBUSY; | ||
1673 | |||
1674 | ioc = current->io_context; | ||
1675 | if (!ioc) | ||
1676 | return -ENOENT; | ||
1677 | |||
1678 | /* acquire active ref on @ioc and associate */ | ||
1679 | get_io_context_active(ioc); | ||
1680 | bio->bi_ioc = ioc; | ||
1681 | |||
1682 | /* associate blkcg if exists */ | ||
1683 | rcu_read_lock(); | ||
1684 | css = task_subsys_state(current, blkio_subsys_id); | ||
1685 | if (css && css_tryget(css)) | ||
1686 | bio->bi_css = css; | ||
1687 | rcu_read_unlock(); | ||
1688 | |||
1689 | return 0; | ||
1690 | } | ||
1691 | |||
1692 | /** | ||
1693 | * bio_disassociate_task - undo bio_associate_current() | ||
1694 | * @bio: target bio | ||
1695 | */ | ||
1696 | void bio_disassociate_task(struct bio *bio) | ||
1697 | { | ||
1698 | if (bio->bi_ioc) { | ||
1699 | put_io_context(bio->bi_ioc); | ||
1700 | bio->bi_ioc = NULL; | ||
1701 | } | ||
1702 | if (bio->bi_css) { | ||
1703 | css_put(bio->bi_css); | ||
1704 | bio->bi_css = NULL; | ||
1705 | } | ||
1706 | } | ||
1707 | |||
1708 | #endif /* CONFIG_BLK_CGROUP */ | ||
1709 | |||
1649 | static void __init biovec_init_slabs(void) | 1710 | static void __init biovec_init_slabs(void) |
1650 | { | 1711 | { |
1651 | int i; | 1712 | int i; |
diff --git a/fs/ioprio.c b/fs/ioprio.c index 5e6dbe8958fc..e50170ca7c33 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
@@ -50,7 +50,7 @@ int set_task_ioprio(struct task_struct *task, int ioprio) | |||
50 | 50 | ||
51 | ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); | 51 | ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); |
52 | if (ioc) { | 52 | if (ioc) { |
53 | ioc_ioprio_changed(ioc, ioprio); | 53 | ioc->ioprio = ioprio; |
54 | put_io_context(ioc); | 54 | put_io_context(ioc); |
55 | } | 55 | } |
56 | 56 | ||
diff --git a/fs/splice.c b/fs/splice.c index f8476841eb04..406ef2b792c2 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -1388,7 +1388,7 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
1388 | */ | 1388 | */ |
1389 | static int get_iovec_page_array(const struct iovec __user *iov, | 1389 | static int get_iovec_page_array(const struct iovec __user *iov, |
1390 | unsigned int nr_vecs, struct page **pages, | 1390 | unsigned int nr_vecs, struct page **pages, |
1391 | struct partial_page *partial, int aligned, | 1391 | struct partial_page *partial, bool aligned, |
1392 | unsigned int pipe_buffers) | 1392 | unsigned int pipe_buffers) |
1393 | { | 1393 | { |
1394 | int buffers = 0, error = 0; | 1394 | int buffers = 0, error = 0; |
@@ -1626,7 +1626,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, | |||
1626 | return -ENOMEM; | 1626 | return -ENOMEM; |
1627 | 1627 | ||
1628 | spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages, | 1628 | spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages, |
1629 | spd.partial, flags & SPLICE_F_GIFT, | 1629 | spd.partial, false, |
1630 | pipe->buffers); | 1630 | pipe->buffers); |
1631 | if (spd.nr_pages <= 0) | 1631 | if (spd.nr_pages <= 0) |
1632 | ret = spd.nr_pages; | 1632 | ret = spd.nr_pages; |