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; |
