@@ -2396,6 +2396,35 @@
return 0;
}
+/*
+ * TODO: Make this into a generic get_blocks function.
+ *
+ * In ocfs2, ip_alloc_sem is used to protect allocation changes on the node.
+ * In direct IO, we add ip_alloc_sem to protect date consistent between
+ * direct-io and ocfs2_truncate_file race (buffer io use ip_alloc_sem
+ * already). Although inode->i_mutex lock is used to avoid concurrency of
+ * above situation, i think ip_alloc_sem is still needed because protect
+ * allocation changes is significant.
+ *
+ * This function is called directly from get_more_blocks in direct-io.c.
+ *
+ * called like this: dio->get_blocks(dio->inode, fs_startblk,
+ * fs_count, map_bh, dio->rw == READ);
+ */
+static int ocfs2_dio_read_get_block(struct inode *inode, sector_t iblock,
+ struct buffer_head *bh_result, int create)
+{
+ struct ocfs2_inode_info *oi = OCFS2_I(inode);
+ int ret = 0;
+
+ down_read(&oi->ip_alloc_sem);
+ /* This is the fast path for direct-io reading. */
+ ret = ocfs2_get_block(inode, iblock, bh_result, create);
+ up_read(&oi->ip_alloc_sem);
+
+ return ret;
+}
+
static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
{
struct file *file = iocb->ki_filp;
@@ -2416,7 +2445,7 @@
return 0;
if (iov_iter_rw(iter) == READ)
- get_block = ocfs2_get_block;
+ get_block = ocfs2_dio_read_get_block;
else
get_block = ocfs2_dio_get_block;