]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
direct-io: always call ->end_io if non-NULL
authorChristoph Hellwig <hch@lst.de>
Fri, 28 Apr 2017 01:27:09 +0000 (18:27 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Sun, 28 May 2017 02:44:15 +0000 (19:44 -0700)
This way we can pass back errors to the file system, and allow for
cleanup required for all direct I/O invocations.

Also allow the ->end_io handlers to return errors on their own, so that
I/O completion errors can be passed on to the callers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
(cherry-picked commit from 187372a3b9faff68ed61c291d0135e6739e0dbdf)

Orabug: 24393811
Conflicts:
    The change in the return type of the function dio_iodone_t
broke the KABI. Hence, the original function return type is wrapped
around under the flag __GENKSYMS__

Signed-off-by: Ashok Vairavan <ashok.vairavan@oracle.com>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/dax.c
fs/direct-io.c
fs/ext4/inode.c
fs/ocfs2/aops.c
fs/xfs/xfs_aops.c
include/linux/fs.h

index 5c548d821a2a67835891e91a0606154fca2648e3..2ba28af71b80c0ec749de9042b447d073ee4fe94 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -264,8 +264,13 @@ ssize_t dax_do_io(struct kiocb *iocb, struct inode *inode,
        if ((flags & DIO_LOCKING) && iov_iter_rw(iter) == READ)
                mutex_unlock(&inode->i_mutex);
 
-       if ((retval > 0) && end_io)
-               end_io(iocb, pos, retval, bh.b_private);
+       if (end_io) {
+               int err;
+
+               err = end_io(iocb, pos, retval, bh.b_private);
+               if (err)
+                       retval = err;
+       }
 
        if (!(flags & DIO_SKIP_DIO_COUNT))
                inode_dio_end(inode);
index 9434d6a08119c424a6db64dc1669cab093f530b6..4664f5a2dac478772676759174baa9eeab93a147 100644 (file)
@@ -251,8 +251,13 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret,
        if (ret == 0)
                ret = transferred;
 
-       if (dio->end_io && dio->result)
-               dio->end_io(dio->iocb, offset, transferred, dio->private);
+       if (dio->end_io) {
+               int err;
+
+               err = dio->end_io(dio->iocb, offset, ret, dio->private);
+               if (err)
+                       ret = err;
+       }
 
        if (!(dio->flags & DIO_SKIP_DIO_COUNT))
                inode_dio_end(dio->inode);
index c3f8fc88707b01ca0b9295ffc666fc852592e1d6..bb22f8176a3077767d2992daeaa69529e92f8052 100644 (file)
@@ -3095,14 +3095,17 @@ int ext4_get_block_dax(struct inode *inode, sector_t iblock,
        return _ext4_get_block(inode, iblock, bh_result, flags);
 }
 
-static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
+static int ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
                            ssize_t size, void *private)
 {
         ext4_io_end_t *io_end = iocb->private;
 
+       if (size <= 0)
+               return 0;
+
        /* if not async direct IO just return */
        if (!io_end)
-               return;
+               return 0;
 
        ext_debug("ext4_end_io_dio(): io_end 0x%p "
                  "for inode %lu, iocb 0x%p, offset %llu, size %zd\n",
@@ -3113,6 +3116,8 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
        io_end->offset = offset;
        io_end->size = size;
        ext4_put_io_end(io_end);
+
+       return 0;
 }
 
 /*
index e378c5135334c37d6821e23a0c3a28ee41b44bd3..3a793bc4ad58ec6efc3f3e8fbaaeaffe72825323 100644 (file)
@@ -608,7 +608,7 @@ bail:
  * particularly interested in the aio/dio case.  We use the rw_lock DLM lock
  * to protect io on one node from truncation on another.
  */
-static void ocfs2_dio_end_io(struct kiocb *iocb,
+static int ocfs2_dio_end_io(struct kiocb *iocb,
                             loff_t offset,
                             ssize_t bytes,
                             void *private)
@@ -617,6 +617,9 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
        int level;
        wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
 
+       if (bytes <= 0)
+               return 0;
+
        /* this io's submitter should not have unlocked this before we could */
        BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
 
@@ -636,6 +639,8 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
 
        level = ocfs2_iocb_rw_locked_level(iocb);
        ocfs2_rw_unlock(inode, level);
+
+       return 0;
 }
 
 static int ocfs2_releasepage(struct page *page, gfp_t wait)
index 42624303277ba1403d6c21fc2d4b1974f7c753ce..89934e6665fa6e0c1fd0b9a397085f182f2bccea 100644 (file)
@@ -1649,7 +1649,7 @@ out_end_io:
  * case the completion can be called in interrupt context, whereas if we have an
  * ioend we will always be called in task context (i.e. from a workqueue).
  */
-STATIC void
+STATIC int
 xfs_end_io_direct_write(
        struct kiocb            *iocb,
        loff_t                  offset,
@@ -1659,15 +1659,19 @@ xfs_end_io_direct_write(
        struct inode            *inode = file_inode(iocb->ki_filp);
        struct xfs_ioend        *ioend = private;
 
+       if (size <= 0)
+               return 0;
+
        trace_xfs_gbmap_direct_endio(XFS_I(inode), offset, size,
                                     ioend ? ioend->io_type : 0, NULL);
 
        if (!ioend) {
                ASSERT(offset + size <= i_size_read(inode));
-               return;
+               return 0;
        }
 
        __xfs_end_io_direct_write(inode, ioend, offset, size);
+       return 0;
 }
 
 static inline ssize_t
@@ -1676,10 +1680,7 @@ xfs_vm_do_dio(
        struct kiocb            *iocb,
        struct iov_iter         *iter,
        loff_t                  offset,
-       void                    (*endio)(struct kiocb   *iocb,
-                                        loff_t         offset,
-                                        ssize_t        size,
-                                        void           *private),
+       dio_iodone_t            endio,
        int                     flags)
 {
        struct block_device     *bdev;
index 8308813f5c12ccc1983ce3cf06be5aa2fa23af08..ab0abde661134adc14fed554ee6efacc58f96a14 100644 (file)
@@ -67,8 +67,13 @@ extern int sysctl_protected_hardlinks;
 struct buffer_head;
 typedef int (get_block_t)(struct inode *inode, sector_t iblock,
                        struct buffer_head *bh_result, int create);
+#ifdef __GENKSYMS__
 typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
                        ssize_t bytes, void *private);
+#else
+typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
+                       ssize_t bytes, void *private);
+#endif
 typedef void (dax_iodone_t)(struct buffer_head *bh_map, int uptodate);
 
 #define MAY_EXEC               0x00000001