This patch fixes a tiny race in unaligned aio+dio that leads to a hang.

Commit a11f7e63c59810a81494d4c4b028af707d4c7ca4 serialized unaligned
aio+dio writes. However the serialize code in end_io() was not
differentiating between writes and reads and thus allowing reads to
interfere with the serialization accounting for writes. This patch
seperates the handler functions to avoid this issue.

Signed-off-by: Sunil Mushran <sunil.mush...@oracle.com>
---
 fs/ocfs2/aops.c |   44 ++++++++++++++++++++++++++++++++------------
 1 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 78b68af..3783ba3 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -558,20 +558,15 @@ bail:
 }
 
 /*
- * ocfs2_dio_end_io is called by the dio core when a dio is finished.  We're
- * particularly interested in the aio/dio case.  We use the rw_lock DLM lock
- * to protect io on one node from truncation on another.
+ * ocfs2_dio_end_io_[read|write] is called by the dio core when a dio is
+ * finished.  We're 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,
-                            loff_t offset,
-                            ssize_t bytes,
-                            void *private,
-                            int ret,
-                            bool is_async)
+static void ocfs2_dio_end_io(struct kiocb *iocb, loff_t offset, ssize_t bytes,
+                            void *private, int ret, bool is_async, int rw)
 {
        struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
        int level;
-       wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
 
        /* this io's submitter should not have unlocked this before we could */
        BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
@@ -579,7 +574,9 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
        if (ocfs2_iocb_is_sem_locked(iocb))
                ocfs2_iocb_clear_sem_locked(iocb);
 
-       if (ocfs2_iocb_is_unaligned_aio(iocb)) {
+       if (rw == WRITE && ocfs2_iocb_is_unaligned_aio(iocb)) {
+               wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
+
                ocfs2_iocb_clear_unaligned_aio(iocb);
 
                if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) &&
@@ -598,6 +595,23 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
        inode_dio_done(inode);
 }
 
+static void ocfs2_dio_end_io_write(struct kiocb *iocb, loff_t offset,
+                                  ssize_t bytes, void *private, int ret,
+                                  bool is_async)
+{
+
+       return ocfs2_dio_end_io(iocb, offset, bytes, private, ret,
+                               is_async, WRITE);
+}
+
+static void ocfs2_dio_end_io_read(struct kiocb *iocb, loff_t offset,
+                                 ssize_t bytes, void *private, int ret,
+                                 bool is_async)
+{
+       return ocfs2_dio_end_io(iocb, offset, bytes, private, ret,
+                               is_async, READ);
+}
+
 /*
  * ocfs2_invalidatepage() and ocfs2_releasepage() are shamelessly stolen
  * from ext3.  PageChecked() bits have been removed as OCFS2 does not
@@ -627,6 +641,7 @@ static ssize_t ocfs2_direct_IO(int rw,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_path.dentry->d_inode->i_mapping->host;
+       dio_iodone_t *end_io;
 
        /*
         * Fallback to buffered I/O if we see an inode without
@@ -639,10 +654,15 @@ static ssize_t ocfs2_direct_IO(int rw,
        if (i_size_read(inode) <= offset)
                return 0;
 
+       if (rw == WRITE)
+               end_io = ocfs2_dio_end_io_write;
+       else
+               end_io = ocfs2_dio_end_io_read;
+
        return __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev,
                                    iov, offset, nr_segs,
                                    ocfs2_direct_IO_get_blocks,
-                                   ocfs2_dio_end_io, NULL, 0);
+                                   end_io, NULL, 0);
 }
 
 static void ocfs2_figure_cluster_boundaries(struct ocfs2_super *osb,
-- 
1.7.7.6


_______________________________________________
Ocfs2-devel mailing list
Ocfs2-devel@oss.oracle.com
http://oss.oracle.com/mailman/listinfo/ocfs2-devel

Reply via email to