[GFS2] Alter direct I/O path
[pandora-kernel.git] / fs / gfs2 / ops_address.c
index 031270a..d33f6aa 100644 (file)
@@ -589,8 +589,9 @@ static void gfs2_invalidatepage(struct page *page, unsigned long offset)
        return;
 }
 
-static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov,
-                                   loff_t offset, unsigned long nr_segs)
+static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
+                             const struct iovec *iov, loff_t offset,
+                             unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
@@ -598,8 +599,10 @@ static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov,
        struct gfs2_holder gh;
        int rv;
 
+       if (rw == READ)
+               mutex_lock(&inode->i_mutex);
        /*
-        * Shared lock, even though its write, since we do no allocation
+        * Shared lock, even if its a write, since we do no allocation
         * on this path. All we need change is atime.
         */
        gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
@@ -607,6 +610,9 @@ static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov,
        if (rv)
                goto out;
 
+       if (offset > i_size_read(inode))
+               goto out;
+
        /*
         * Should we return an error here? I can't see that O_DIRECT for
         * a journaled file makes any sense. For now we'll silently fall
@@ -619,47 +625,19 @@ static ssize_t gfs2_direct_IO_write(struct kiocb *iocb, const struct iovec *iov,
        if (gfs2_is_stuffed(ip))
                goto out;
 
-       rv = __blockdev_direct_IO(WRITE, iocb, inode, inode->i_sb->s_bdev,
-                                 iov, offset, nr_segs, gfs2_get_block,
-                                 NULL, DIO_OWN_LOCKING);
+       rv = blockdev_direct_IO_own_locking(rw, iocb, inode,
+                                           inode->i_sb->s_bdev,
+                                           iov, offset, nr_segs,
+                                           gfs2_get_block, NULL);
 out:
        gfs2_glock_dq_m(1, &gh);
        gfs2_holder_uninit(&gh);
+       if (rw == READ)
+               mutex_unlock(&inode->i_mutex);
 
        return rv;
 }
 
-/**
- * gfs2_direct_IO
- *
- * This is called with a shared lock already held for the read path.
- * Currently, no locks are held when the write path is called.
- */
-static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
-                             const struct iovec *iov, loff_t offset,
-                             unsigned long nr_segs)
-{
-       struct file *file = iocb->ki_filp;
-       struct inode *inode = file->f_mapping->host;
-       struct gfs2_inode *ip = GFS2_I(inode);
-       struct gfs2_sbd *sdp = GFS2_SB(inode);
-       int ret;
-
-       if (rw == WRITE)
-               return gfs2_direct_IO_write(iocb, iov, offset, nr_segs);
-
-       if (gfs2_assert_warn(sdp, gfs2_glock_is_locked_by_me(ip->i_gl)) ||
-           gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
-               return -EINVAL;
-
-       mutex_lock(&inode->i_mutex);
-       ret = __blockdev_direct_IO(READ, iocb, inode, inode->i_sb->s_bdev, iov,
-                                  offset, nr_segs, gfs2_get_block, NULL,
-                                  DIO_OWN_LOCKING);
-       mutex_unlock(&inode->i_mutex);
-       return ret;
-}
-
 /**
  * stuck_releasepage - We're stuck in gfs2_releasepage().  Print stuff out.
  * @bh: the buffer we're stuck on
@@ -765,7 +743,7 @@ int gfs2_releasepage(struct page *page, gfp_t gfp_mask)
        }
        while (bh != head);
 
- out:
+out:
        return try_to_free_buffers(page);
 }