|
@@ -594,6 +594,36 @@ static void gfs2_invalidatepage(struct page *page, unsigned long offset)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * gfs2_ok_for_dio - check that dio is valid on this file
|
|
|
+ * @ip: The inode
|
|
|
+ * @rw: READ or WRITE
|
|
|
+ * @offset: The offset at which we are reading or writing
|
|
|
+ *
|
|
|
+ * Returns: 0 (to ignore the i/o request and thus fall back to buffered i/o)
|
|
|
+ * 1 (to accept the i/o request)
|
|
|
+ */
|
|
|
+static int gfs2_ok_for_dio(struct gfs2_inode *ip, int rw, loff_t offset)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * 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
|
|
|
+ * back to buffered I/O, likewise we do the same for stuffed
|
|
|
+ * files since they are (a) small and (b) unaligned.
|
|
|
+ */
|
|
|
+ if (gfs2_is_jdata(ip))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (gfs2_is_stuffed(ip))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (offset > i_size_read(&ip->i_inode))
|
|
|
+ return 0;
|
|
|
+ return 1;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
|
|
|
const struct iovec *iov, loff_t offset,
|
|
|
unsigned long nr_segs)
|
|
@@ -604,42 +634,28 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb,
|
|
|
struct gfs2_holder gh;
|
|
|
int rv;
|
|
|
|
|
|
- if (rw == READ)
|
|
|
- mutex_lock(&inode->i_mutex);
|
|
|
/*
|
|
|
- * Shared lock, even if its a write, since we do no allocation
|
|
|
- * on this path. All we need change is atime.
|
|
|
+ * Deferred lock, even if its a write, since we do no allocation
|
|
|
+ * on this path. All we need change is atime, and this lock mode
|
|
|
+ * ensures that other nodes have flushed their buffered read caches
|
|
|
+ * (i.e. their page cache entries for this inode). We do not,
|
|
|
+ * unfortunately have the option of only flushing a range like
|
|
|
+ * the VFS does.
|
|
|
*/
|
|
|
- gfs2_holder_init(ip->i_gl, LM_ST_SHARED, GL_ATIME, &gh);
|
|
|
+ gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, GL_ATIME, &gh);
|
|
|
rv = gfs2_glock_nq_atime(&gh);
|
|
|
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
|
|
|
- * back to buffered I/O, likewise we do the same for stuffed
|
|
|
- * files since they are (a) small and (b) unaligned.
|
|
|
- */
|
|
|
- if (gfs2_is_jdata(ip))
|
|
|
- goto out;
|
|
|
-
|
|
|
- if (gfs2_is_stuffed(ip))
|
|
|
- goto out;
|
|
|
-
|
|
|
- rv = blockdev_direct_IO_own_locking(rw, iocb, inode,
|
|
|
- inode->i_sb->s_bdev,
|
|
|
- iov, offset, nr_segs,
|
|
|
- gfs2_get_block_direct, NULL);
|
|
|
+ return rv;
|
|
|
+ rv = gfs2_ok_for_dio(ip, rw, offset);
|
|
|
+ if (rv != 1)
|
|
|
+ goto out; /* dio not valid, fall back to buffered i/o */
|
|
|
+
|
|
|
+ rv = blockdev_direct_IO_no_locking(rw, iocb, inode, inode->i_sb->s_bdev,
|
|
|
+ iov, offset, nr_segs,
|
|
|
+ gfs2_get_block_direct, NULL);
|
|
|
out:
|
|
|
gfs2_glock_dq_m(1, &gh);
|
|
|
gfs2_holder_uninit(&gh);
|
|
|
- if (rw == READ)
|
|
|
- mutex_unlock(&inode->i_mutex);
|
|
|
-
|
|
|
return rv;
|
|
|
}
|
|
|
|