diff options
| -rw-r--r-- | block/ioprio.c | 22 | ||||
| -rw-r--r-- | drivers/block/loop.c | 3 | ||||
| -rw-r--r-- | fs/aio.c | 18 | ||||
| -rw-r--r-- | fs/block_dev.c | 2 | ||||
| -rw-r--r-- | fs/iomap.c | 1 | ||||
| -rw-r--r-- | include/linux/fs.h | 16 | ||||
| -rw-r--r-- | include/linux/ioprio.h | 9 | ||||
| -rw-r--r-- | include/uapi/linux/aio_abi.h | 1 |
8 files changed, 63 insertions, 9 deletions
diff --git a/block/ioprio.c b/block/ioprio.c index 6f5d0b6625e3..f9821080c92c 100644 --- a/block/ioprio.c +++ b/block/ioprio.c | |||
| @@ -61,15 +61,10 @@ int set_task_ioprio(struct task_struct *task, int ioprio) | |||
| 61 | } | 61 | } |
| 62 | EXPORT_SYMBOL_GPL(set_task_ioprio); | 62 | EXPORT_SYMBOL_GPL(set_task_ioprio); |
| 63 | 63 | ||
| 64 | SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) | 64 | int ioprio_check_cap(int ioprio) |
| 65 | { | 65 | { |
| 66 | int class = IOPRIO_PRIO_CLASS(ioprio); | 66 | int class = IOPRIO_PRIO_CLASS(ioprio); |
| 67 | int data = IOPRIO_PRIO_DATA(ioprio); | 67 | int data = IOPRIO_PRIO_DATA(ioprio); |
| 68 | struct task_struct *p, *g; | ||
| 69 | struct user_struct *user; | ||
| 70 | struct pid *pgrp; | ||
| 71 | kuid_t uid; | ||
| 72 | int ret; | ||
| 73 | 68 | ||
| 74 | switch (class) { | 69 | switch (class) { |
| 75 | case IOPRIO_CLASS_RT: | 70 | case IOPRIO_CLASS_RT: |
| @@ -92,6 +87,21 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) | |||
| 92 | return -EINVAL; | 87 | return -EINVAL; |
| 93 | } | 88 | } |
| 94 | 89 | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) | ||
| 94 | { | ||
| 95 | struct task_struct *p, *g; | ||
| 96 | struct user_struct *user; | ||
| 97 | struct pid *pgrp; | ||
| 98 | kuid_t uid; | ||
| 99 | int ret; | ||
| 100 | |||
| 101 | ret = ioprio_check_cap(ioprio); | ||
| 102 | if (ret) | ||
| 103 | return ret; | ||
| 104 | |||
| 95 | ret = -ESRCH; | 105 | ret = -ESRCH; |
| 96 | rcu_read_lock(); | 106 | rcu_read_lock(); |
| 97 | switch (which) { | 107 | switch (which) { |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 4838b0dbaad3..3ce607006c44 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -76,6 +76,8 @@ | |||
| 76 | #include <linux/miscdevice.h> | 76 | #include <linux/miscdevice.h> |
| 77 | #include <linux/falloc.h> | 77 | #include <linux/falloc.h> |
| 78 | #include <linux/uio.h> | 78 | #include <linux/uio.h> |
| 79 | #include <linux/ioprio.h> | ||
| 80 | |||
| 79 | #include "loop.h" | 81 | #include "loop.h" |
| 80 | 82 | ||
| 81 | #include <linux/uaccess.h> | 83 | #include <linux/uaccess.h> |
| @@ -559,6 +561,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, | |||
| 559 | cmd->iocb.ki_filp = file; | 561 | cmd->iocb.ki_filp = file; |
| 560 | cmd->iocb.ki_complete = lo_rw_aio_complete; | 562 | cmd->iocb.ki_complete = lo_rw_aio_complete; |
| 561 | cmd->iocb.ki_flags = IOCB_DIRECT; | 563 | cmd->iocb.ki_flags = IOCB_DIRECT; |
| 564 | cmd->iocb.ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0); | ||
| 562 | if (cmd->css) | 565 | if (cmd->css) |
| 563 | kthread_associate_blkcg(cmd->css); | 566 | kthread_associate_blkcg(cmd->css); |
| 564 | 567 | ||
| @@ -1434,7 +1434,23 @@ static int aio_prep_rw(struct kiocb *req, struct iocb *iocb) | |||
| 1434 | req->ki_flags = iocb_flags(req->ki_filp); | 1434 | req->ki_flags = iocb_flags(req->ki_filp); |
| 1435 | if (iocb->aio_flags & IOCB_FLAG_RESFD) | 1435 | if (iocb->aio_flags & IOCB_FLAG_RESFD) |
| 1436 | req->ki_flags |= IOCB_EVENTFD; | 1436 | req->ki_flags |= IOCB_EVENTFD; |
| 1437 | req->ki_hint = file_write_hint(req->ki_filp); | 1437 | req->ki_hint = ki_hint_validate(file_write_hint(req->ki_filp)); |
| 1438 | if (iocb->aio_flags & IOCB_FLAG_IOPRIO) { | ||
| 1439 | /* | ||
| 1440 | * If the IOCB_FLAG_IOPRIO flag of aio_flags is set, then | ||
| 1441 | * aio_reqprio is interpreted as an I/O scheduling | ||
| 1442 | * class and priority. | ||
| 1443 | */ | ||
| 1444 | ret = ioprio_check_cap(iocb->aio_reqprio); | ||
| 1445 | if (ret) { | ||
| 1446 | pr_debug("aio ioprio check cap error: %d\n", ret); | ||
| 1447 | return ret; | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | req->ki_ioprio = iocb->aio_reqprio; | ||
| 1451 | } else | ||
| 1452 | req->ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0); | ||
| 1453 | |||
| 1438 | ret = kiocb_set_rw_flags(req, iocb->aio_rw_flags); | 1454 | ret = kiocb_set_rw_flags(req, iocb->aio_rw_flags); |
| 1439 | if (unlikely(ret)) | 1455 | if (unlikely(ret)) |
| 1440 | fput(req->ki_filp); | 1456 | fput(req->ki_filp); |
diff --git a/fs/block_dev.c b/fs/block_dev.c index bef6934b6189..05e12aea2404 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -216,6 +216,7 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter, | |||
| 216 | bio.bi_write_hint = iocb->ki_hint; | 216 | bio.bi_write_hint = iocb->ki_hint; |
| 217 | bio.bi_private = current; | 217 | bio.bi_private = current; |
| 218 | bio.bi_end_io = blkdev_bio_end_io_simple; | 218 | bio.bi_end_io = blkdev_bio_end_io_simple; |
| 219 | bio.bi_ioprio = iocb->ki_ioprio; | ||
| 219 | 220 | ||
| 220 | ret = bio_iov_iter_get_pages(&bio, iter); | 221 | ret = bio_iov_iter_get_pages(&bio, iter); |
| 221 | if (unlikely(ret)) | 222 | if (unlikely(ret)) |
| @@ -355,6 +356,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages) | |||
| 355 | bio->bi_write_hint = iocb->ki_hint; | 356 | bio->bi_write_hint = iocb->ki_hint; |
| 356 | bio->bi_private = dio; | 357 | bio->bi_private = dio; |
| 357 | bio->bi_end_io = blkdev_bio_end_io; | 358 | bio->bi_end_io = blkdev_bio_end_io; |
| 359 | bio->bi_ioprio = iocb->ki_ioprio; | ||
| 358 | 360 | ||
| 359 | ret = bio_iov_iter_get_pages(bio, iter); | 361 | ret = bio_iov_iter_get_pages(bio, iter); |
| 360 | if (unlikely(ret)) { | 362 | if (unlikely(ret)) { |
diff --git a/fs/iomap.c b/fs/iomap.c index 206539d369a8..7d1e9f45f098 100644 --- a/fs/iomap.c +++ b/fs/iomap.c | |||
| @@ -1046,6 +1046,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, | |||
| 1046 | bio_set_dev(bio, iomap->bdev); | 1046 | bio_set_dev(bio, iomap->bdev); |
| 1047 | bio->bi_iter.bi_sector = iomap_sector(iomap, pos); | 1047 | bio->bi_iter.bi_sector = iomap_sector(iomap, pos); |
| 1048 | bio->bi_write_hint = dio->iocb->ki_hint; | 1048 | bio->bi_write_hint = dio->iocb->ki_hint; |
| 1049 | bio->bi_ioprio = dio->iocb->ki_ioprio; | ||
| 1049 | bio->bi_private = dio; | 1050 | bio->bi_private = dio; |
| 1050 | bio->bi_end_io = iomap_dio_bio_end_io; | 1051 | bio->bi_end_io = iomap_dio_bio_end_io; |
| 1051 | 1052 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 77333ed3a488..7207de8c4e9a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/delayed_call.h> | 36 | #include <linux/delayed_call.h> |
| 37 | #include <linux/uuid.h> | 37 | #include <linux/uuid.h> |
| 38 | #include <linux/errseq.h> | 38 | #include <linux/errseq.h> |
| 39 | #include <linux/ioprio.h> | ||
| 39 | 40 | ||
| 40 | #include <asm/byteorder.h> | 41 | #include <asm/byteorder.h> |
| 41 | #include <uapi/linux/fs.h> | 42 | #include <uapi/linux/fs.h> |
| @@ -299,7 +300,8 @@ struct kiocb { | |||
| 299 | void (*ki_complete)(struct kiocb *iocb, long ret, long ret2); | 300 | void (*ki_complete)(struct kiocb *iocb, long ret, long ret2); |
| 300 | void *private; | 301 | void *private; |
| 301 | int ki_flags; | 302 | int ki_flags; |
| 302 | enum rw_hint ki_hint; | 303 | u16 ki_hint; |
| 304 | u16 ki_ioprio; /* See linux/ioprio.h */ | ||
| 303 | } __randomize_layout; | 305 | } __randomize_layout; |
| 304 | 306 | ||
| 305 | static inline bool is_sync_kiocb(struct kiocb *kiocb) | 307 | static inline bool is_sync_kiocb(struct kiocb *kiocb) |
| @@ -1934,12 +1936,22 @@ static inline enum rw_hint file_write_hint(struct file *file) | |||
| 1934 | 1936 | ||
| 1935 | static inline int iocb_flags(struct file *file); | 1937 | static inline int iocb_flags(struct file *file); |
| 1936 | 1938 | ||
| 1939 | static inline u16 ki_hint_validate(enum rw_hint hint) | ||
| 1940 | { | ||
| 1941 | typeof(((struct kiocb *)0)->ki_hint) max_hint = -1; | ||
| 1942 | |||
| 1943 | if (hint <= max_hint) | ||
| 1944 | return hint; | ||
| 1945 | return 0; | ||
| 1946 | } | ||
| 1947 | |||
| 1937 | static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) | 1948 | static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) |
| 1938 | { | 1949 | { |
| 1939 | *kiocb = (struct kiocb) { | 1950 | *kiocb = (struct kiocb) { |
| 1940 | .ki_filp = filp, | 1951 | .ki_filp = filp, |
| 1941 | .ki_flags = iocb_flags(filp), | 1952 | .ki_flags = iocb_flags(filp), |
| 1942 | .ki_hint = file_write_hint(filp), | 1953 | .ki_hint = ki_hint_validate(file_write_hint(filp)), |
| 1954 | .ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0), | ||
| 1943 | }; | 1955 | }; |
| 1944 | } | 1956 | } |
| 1945 | 1957 | ||
diff --git a/include/linux/ioprio.h b/include/linux/ioprio.h index 627efac73e6d..9e30ed6443db 100644 --- a/include/linux/ioprio.h +++ b/include/linux/ioprio.h | |||
| @@ -77,4 +77,13 @@ extern int ioprio_best(unsigned short aprio, unsigned short bprio); | |||
| 77 | 77 | ||
| 78 | extern int set_task_ioprio(struct task_struct *task, int ioprio); | 78 | extern int set_task_ioprio(struct task_struct *task, int ioprio); |
| 79 | 79 | ||
| 80 | #ifdef CONFIG_BLOCK | ||
| 81 | extern int ioprio_check_cap(int ioprio); | ||
| 82 | #else | ||
| 83 | static inline int ioprio_check_cap(int ioprio) | ||
| 84 | { | ||
| 85 | return -ENOTBLK; | ||
| 86 | } | ||
| 87 | #endif /* CONFIG_BLOCK */ | ||
| 88 | |||
| 80 | #endif | 89 | #endif |
diff --git a/include/uapi/linux/aio_abi.h b/include/uapi/linux/aio_abi.h index ed0185945bb2..75846164290e 100644 --- a/include/uapi/linux/aio_abi.h +++ b/include/uapi/linux/aio_abi.h | |||
| @@ -53,6 +53,7 @@ enum { | |||
| 53 | * is valid. | 53 | * is valid. |
| 54 | */ | 54 | */ |
| 55 | #define IOCB_FLAG_RESFD (1 << 0) | 55 | #define IOCB_FLAG_RESFD (1 << 0) |
| 56 | #define IOCB_FLAG_IOPRIO (1 << 1) | ||
| 56 | 57 | ||
| 57 | /* read() from /dev/aio returns these structures. */ | 58 | /* read() from /dev/aio returns these structures. */ |
| 58 | struct io_event { | 59 | struct io_event { |
