Merge branch 'work.aio' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Jun 2018 17:00:20 +0000 (10:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 8 Jun 2018 17:00:20 +0000 (10:00 -0700)
Pull aio iopriority support from Al Viro:
 "The rest of aio stuff for this cycle - Adam's aio ioprio series"

* 'work.aio' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  fs: aio ioprio use ioprio_check_cap ret val
  fs: aio ioprio add explicit block layer dependence
  fs: iomap dio set bio prio from kiocb prio
  fs: blkdev set bio prio from kiocb prio
  fs: Add aio iopriority support
  fs: Convert kiocb rw_hint from enum to u16
  block: add ioprio_check_cap function

block/ioprio.c
drivers/block/loop.c
fs/aio.c
fs/block_dev.c
fs/iomap.c
include/linux/fs.h
include/linux/ioprio.h
include/uapi/linux/aio_abi.h

index 6f5d0b6625e39b930d93aca15082daec481f0199..f9821080c92ccbc242ef9d2f819d06588c3d7fe9 100644 (file)
@@ -61,15 +61,10 @@ int set_task_ioprio(struct task_struct *task, int ioprio)
 }
 EXPORT_SYMBOL_GPL(set_task_ioprio);
 
-SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
+int ioprio_check_cap(int ioprio)
 {
        int class = IOPRIO_PRIO_CLASS(ioprio);
        int data = IOPRIO_PRIO_DATA(ioprio);
-       struct task_struct *p, *g;
-       struct user_struct *user;
-       struct pid *pgrp;
-       kuid_t uid;
-       int ret;
 
        switch (class) {
                case IOPRIO_CLASS_RT:
@@ -92,6 +87,21 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
                        return -EINVAL;
        }
 
+       return 0;
+}
+
+SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio)
+{
+       struct task_struct *p, *g;
+       struct user_struct *user;
+       struct pid *pgrp;
+       kuid_t uid;
+       int ret;
+
+       ret = ioprio_check_cap(ioprio);
+       if (ret)
+               return ret;
+
        ret = -ESRCH;
        rcu_read_lock();
        switch (which) {
index 4838b0dbaad34e35419ff1140fbd9aeda876b09a..3ce607006c44ca55e85892ebc853889bfd33255b 100644 (file)
@@ -76,6 +76,8 @@
 #include <linux/miscdevice.h>
 #include <linux/falloc.h>
 #include <linux/uio.h>
+#include <linux/ioprio.h>
+
 #include "loop.h"
 
 #include <linux/uaccess.h>
@@ -559,6 +561,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
        cmd->iocb.ki_filp = file;
        cmd->iocb.ki_complete = lo_rw_aio_complete;
        cmd->iocb.ki_flags = IOCB_DIRECT;
+       cmd->iocb.ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0);
        if (cmd->css)
                kthread_associate_blkcg(cmd->css);
 
index b850e92ee0d51fe5e43beb3b693588b95101b466..134e5b635d643da8868b477a0990e5d3cdb4077e 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1434,7 +1434,23 @@ static int aio_prep_rw(struct kiocb *req, struct iocb *iocb)
        req->ki_flags = iocb_flags(req->ki_filp);
        if (iocb->aio_flags & IOCB_FLAG_RESFD)
                req->ki_flags |= IOCB_EVENTFD;
-       req->ki_hint = file_write_hint(req->ki_filp);
+       req->ki_hint = ki_hint_validate(file_write_hint(req->ki_filp));
+       if (iocb->aio_flags & IOCB_FLAG_IOPRIO) {
+               /*
+                * If the IOCB_FLAG_IOPRIO flag of aio_flags is set, then
+                * aio_reqprio is interpreted as an I/O scheduling
+                * class and priority.
+                */
+               ret = ioprio_check_cap(iocb->aio_reqprio);
+               if (ret) {
+                       pr_debug("aio ioprio check cap error: %d\n", ret);
+                       return ret;
+               }
+
+               req->ki_ioprio = iocb->aio_reqprio;
+       } else
+               req->ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0);
+
        ret = kiocb_set_rw_flags(req, iocb->aio_rw_flags);
        if (unlikely(ret))
                fput(req->ki_filp);
index bef6934b61891ab04c448c8fc1f3d738f310d150..05e12aea24043dac01826bcc833be0e9e8c2e13b 100644 (file)
@@ -216,6 +216,7 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,
        bio.bi_write_hint = iocb->ki_hint;
        bio.bi_private = current;
        bio.bi_end_io = blkdev_bio_end_io_simple;
+       bio.bi_ioprio = iocb->ki_ioprio;
 
        ret = bio_iov_iter_get_pages(&bio, iter);
        if (unlikely(ret))
@@ -355,6 +356,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                bio->bi_write_hint = iocb->ki_hint;
                bio->bi_private = dio;
                bio->bi_end_io = blkdev_bio_end_io;
+               bio->bi_ioprio = iocb->ki_ioprio;
 
                ret = bio_iov_iter_get_pages(bio, iter);
                if (unlikely(ret)) {
index 206539d369a84595d17ad95bccc3f388124774a4..7d1e9f45f098c76647914d6bc4a9033e653ae20f 100644 (file)
@@ -1046,6 +1046,7 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
                bio_set_dev(bio, iomap->bdev);
                bio->bi_iter.bi_sector = iomap_sector(iomap, pos);
                bio->bi_write_hint = dio->iocb->ki_hint;
+               bio->bi_ioprio = dio->iocb->ki_ioprio;
                bio->bi_private = dio;
                bio->bi_end_io = iomap_dio_bio_end_io;
 
index 77333ed3a4880b27ac4ebb7bfb8f34c2faedae3a..7207de8c4e9aea1e653f804e29cbe6ed7f989aca 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/delayed_call.h>
 #include <linux/uuid.h>
 #include <linux/errseq.h>
+#include <linux/ioprio.h>
 
 #include <asm/byteorder.h>
 #include <uapi/linux/fs.h>
@@ -299,7 +300,8 @@ struct kiocb {
        void (*ki_complete)(struct kiocb *iocb, long ret, long ret2);
        void                    *private;
        int                     ki_flags;
-       enum rw_hint            ki_hint;
+       u16                     ki_hint;
+       u16                     ki_ioprio; /* See linux/ioprio.h */
 } __randomize_layout;
 
 static inline bool is_sync_kiocb(struct kiocb *kiocb)
@@ -1934,12 +1936,22 @@ static inline enum rw_hint file_write_hint(struct file *file)
 
 static inline int iocb_flags(struct file *file);
 
+static inline u16 ki_hint_validate(enum rw_hint hint)
+{
+       typeof(((struct kiocb *)0)->ki_hint) max_hint = -1;
+
+       if (hint <= max_hint)
+               return hint;
+       return 0;
+}
+
 static inline void init_sync_kiocb(struct kiocb *kiocb, struct file *filp)
 {
        *kiocb = (struct kiocb) {
                .ki_filp = filp,
                .ki_flags = iocb_flags(filp),
-               .ki_hint = file_write_hint(filp),
+               .ki_hint = ki_hint_validate(file_write_hint(filp)),
+               .ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0),
        };
 }
 
index 627efac73e6dce046d6c4d5bdab683ae13bbed5f..9e30ed6443dbc20b8db1afd42f86a39860a6a13d 100644 (file)
@@ -77,4 +77,13 @@ extern int ioprio_best(unsigned short aprio, unsigned short bprio);
 
 extern int set_task_ioprio(struct task_struct *task, int ioprio);
 
+#ifdef CONFIG_BLOCK
+extern int ioprio_check_cap(int ioprio);
+#else
+static inline int ioprio_check_cap(int ioprio)
+{
+       return -ENOTBLK;
+}
+#endif /* CONFIG_BLOCK */
+
 #endif
index ed0185945bb2e8c23d8f7b0fc069f7c0babaf761..75846164290e9acaa9b2fbead09bdebc5422104c 100644 (file)
@@ -53,6 +53,7 @@ enum {
  *                   is valid.
  */
 #define IOCB_FLAG_RESFD                (1 << 0)
+#define IOCB_FLAG_IOPRIO       (1 << 1)
 
 /* read() from /dev/aio returns these structures. */
 struct io_event {