Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-block.git] / io_uring / rw.c
index 0028e95e6633af0ad2e40caf9a29c7258206d6c7..b20ba87e4926f03cf21999ae08b0dbd80a199e89 100644 (file)
@@ -215,7 +215,7 @@ static void io_complete_rw(struct kiocb *kiocb, long res)
                return;
        io_req_set_res(req, res, 0);
        req->io_task_work.func = io_req_task_complete;
-       io_req_task_prio_work_add(req);
+       io_req_task_work_add(req);
 }
 
 static void io_complete_rw_iopoll(struct kiocb *kiocb, long res)
@@ -273,73 +273,6 @@ static int kiocb_done(struct io_kiocb *req, ssize_t ret,
        return IOU_ISSUE_SKIP_COMPLETE;
 }
 
-static int __io_import_fixed(struct io_kiocb *req, int ddir,
-                            struct iov_iter *iter, struct io_mapped_ubuf *imu)
-{
-       struct io_rw *rw = io_kiocb_to_cmd(req);
-       size_t len = rw->len;
-       u64 buf_end, buf_addr = rw->addr;
-       size_t offset;
-
-       if (unlikely(check_add_overflow(buf_addr, (u64)len, &buf_end)))
-               return -EFAULT;
-       /* not inside the mapped region */
-       if (unlikely(buf_addr < imu->ubuf || buf_end > imu->ubuf_end))
-               return -EFAULT;
-
-       /*
-        * May not be a start of buffer, set size appropriately
-        * and advance us to the beginning.
-        */
-       offset = buf_addr - imu->ubuf;
-       iov_iter_bvec(iter, ddir, imu->bvec, imu->nr_bvecs, offset + len);
-
-       if (offset) {
-               /*
-                * Don't use iov_iter_advance() here, as it's really slow for
-                * using the latter parts of a big fixed buffer - it iterates
-                * over each segment manually. We can cheat a bit here, because
-                * we know that:
-                *
-                * 1) it's a BVEC iter, we set it up
-                * 2) all bvecs are PAGE_SIZE in size, except potentially the
-                *    first and last bvec
-                *
-                * So just find our index, and adjust the iterator afterwards.
-                * If the offset is within the first bvec (or the whole first
-                * bvec, just use iov_iter_advance(). This makes it easier
-                * since we can just skip the first segment, which may not
-                * be PAGE_SIZE aligned.
-                */
-               const struct bio_vec *bvec = imu->bvec;
-
-               if (offset <= bvec->bv_len) {
-                       iov_iter_advance(iter, offset);
-               } else {
-                       unsigned long seg_skip;
-
-                       /* skip first vec */
-                       offset -= bvec->bv_len;
-                       seg_skip = 1 + (offset >> PAGE_SHIFT);
-
-                       iter->bvec = bvec + seg_skip;
-                       iter->nr_segs -= seg_skip;
-                       iter->count -= bvec->bv_len + offset;
-                       iter->iov_offset = offset & ~PAGE_MASK;
-               }
-       }
-
-       return 0;
-}
-
-static int io_import_fixed(struct io_kiocb *req, int rw, struct iov_iter *iter,
-                          unsigned int issue_flags)
-{
-       if (WARN_ON_ONCE(!req->imu))
-               return -EFAULT;
-       return __io_import_fixed(req, rw, iter, req->imu);
-}
-
 #ifdef CONFIG_COMPAT
 static ssize_t io_compat_import(struct io_kiocb *req, struct iovec *iov,
                                unsigned int issue_flags)
@@ -426,7 +359,7 @@ static struct iovec *__io_import_iovec(int ddir, struct io_kiocb *req,
        ssize_t ret;
 
        if (opcode == IORING_OP_READ_FIXED || opcode == IORING_OP_WRITE_FIXED) {
-               ret = io_import_fixed(req, ddir, iter, issue_flags);
+               ret = io_import_fixed(ddir, iter, req->imu, rw->addr, rw->len);
                if (ret)
                        return ERR_PTR(ret);
                return NULL;
@@ -708,17 +641,12 @@ static inline int io_iter_do_read(struct io_rw *rw, struct iov_iter *iter)
                return -EINVAL;
 }
 
-static bool need_read_all(struct io_kiocb *req)
+static bool need_complete_io(struct io_kiocb *req)
 {
        return req->flags & REQ_F_ISREG ||
                S_ISBLK(file_inode(req->file)->i_mode);
 }
 
-static inline bool io_req_ffs_set(struct io_kiocb *req)
-{
-       return req->flags & REQ_F_FIXED_FILE;
-}
-
 static int io_rw_init_file(struct io_kiocb *req, fmode_t mode)
 {
        struct io_rw *rw = io_kiocb_to_cmd(req);
@@ -733,7 +661,7 @@ static int io_rw_init_file(struct io_kiocb *req, fmode_t mode)
        if (!io_req_ffs_set(req))
                req->flags |= io_file_get_flags(file) << REQ_F_SUPPORT_NOWAIT_BIT;
 
-       kiocb->ki_flags = iocb_flags(file);
+       kiocb->ki_flags = file->f_iocb_flags;
        ret = kiocb_set_rw_flags(kiocb, rw->flags);
        if (unlikely(ret))
                return ret;
@@ -847,7 +775,7 @@ int io_read(struct io_kiocb *req, unsigned int issue_flags)
                        kfree(iovec);
                return IOU_ISSUE_SKIP_COMPLETE;
        } else if (ret == req->cqe.res || ret <= 0 || !force_nonblock ||
-                  (req->flags & REQ_F_NOWAIT) || !need_read_all(req)) {
+                  (req->flags & REQ_F_NOWAIT) || !need_complete_io(req)) {
                /* read all, failed, already did sync or don't want to retry */
                goto done;
        }
@@ -942,9 +870,10 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
                if (unlikely(!io_file_supports_nowait(req)))
                        goto copy_iov;
 
-               /* file path doesn't support NOWAIT for non-direct_IO */
-               if (force_nonblock && !(kiocb->ki_flags & IOCB_DIRECT) &&
-                   (req->flags & REQ_F_ISREG))
+               /* File path supports NOWAIT for non-direct_IO only for block devices. */
+               if (!(kiocb->ki_flags & IOCB_DIRECT) &&
+                       !(kiocb->ki_filp->f_mode & FMODE_BUF_WASYNC) &&
+                       (req->flags & REQ_F_ISREG))
                        goto copy_iov;
 
                kiocb->ki_flags |= IOCB_NOWAIT;
@@ -1000,13 +929,41 @@ int io_write(struct io_kiocb *req, unsigned int issue_flags)
                /* IOPOLL retry should happen for io-wq threads */
                if (ret2 == -EAGAIN && (req->ctx->flags & IORING_SETUP_IOPOLL))
                        goto copy_iov;
+
+               if (ret2 != req->cqe.res && ret2 >= 0 && need_complete_io(req)) {
+                       struct io_async_rw *rw;
+
+                       trace_io_uring_short_write(req->ctx, kiocb->ki_pos - ret2,
+                                               req->cqe.res, ret2);
+
+                       /* This is a partial write. The file pos has already been
+                        * updated, setup the async struct to complete the request
+                        * in the worker. Also update bytes_done to account for
+                        * the bytes already written.
+                        */
+                       iov_iter_save_state(&s->iter, &s->iter_state);
+                       ret = io_setup_async_rw(req, iovec, s, true);
+
+                       rw = req->async_data;
+                       if (rw)
+                               rw->bytes_done += ret2;
+
+                       if (kiocb->ki_flags & IOCB_WRITE)
+                               kiocb_end_write(req);
+                       return ret ? ret : -EAGAIN;
+               }
 done:
                ret = kiocb_done(req, ret2, issue_flags);
        } else {
 copy_iov:
                iov_iter_restore(&s->iter, &s->iter_state);
                ret = io_setup_async_rw(req, iovec, s, false);
-               return ret ?: -EAGAIN;
+               if (!ret) {
+                       if (kiocb->ki_flags & IOCB_WRITE)
+                               kiocb_end_write(req);
+                       return -EAGAIN;
+               }
+               return ret;
        }
        /* it's reportedly faster than delegating the null check to kfree() */
        if (iovec)