aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--block/ioprio.c22
-rw-r--r--drivers/block/loop.c3
-rw-r--r--fs/aio.c18
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/iomap.c1
-rw-r--r--include/linux/fs.h16
-rw-r--r--include/linux/ioprio.h9
-rw-r--r--include/uapi/linux/aio_abi.h1
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}
62EXPORT_SYMBOL_GPL(set_task_ioprio); 62EXPORT_SYMBOL_GPL(set_task_ioprio);
63 63
64SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) 64int 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
93SYSCALL_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
diff --git a/fs/aio.c b/fs/aio.c
index b850e92ee0d5..134e5b635d64 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -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
305static inline bool is_sync_kiocb(struct kiocb *kiocb) 307static 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
1935static inline int iocb_flags(struct file *file); 1937static inline int iocb_flags(struct file *file);
1936 1938
1939static 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
1937static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp) 1948static 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
78extern int set_task_ioprio(struct task_struct *task, int ioprio); 78extern int set_task_ioprio(struct task_struct *task, int ioprio);
79 79
80#ifdef CONFIG_BLOCK
81extern int ioprio_check_cap(int ioprio);
82#else
83static 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. */
58struct io_event { 59struct io_event {