]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/ocfs2/aops.c
ocfs2: Remove data locks
[linux-2.6-omap-h63xx.git] / fs / ocfs2 / aops.c
index c69c1b300155d31aecce94278f52ac8e84b2b537..5fc27cfaee50827136d661967cc6d0744107c9f1 100644 (file)
@@ -305,21 +305,12 @@ static int ocfs2_readpage(struct file *file, struct page *page)
                goto out_alloc;
        }
 
-       ret = ocfs2_data_lock_with_page(inode, 0, page);
-       if (ret != 0) {
-               if (ret == AOP_TRUNCATED_PAGE)
-                       unlock = 0;
-               mlog_errno(ret);
-               goto out_alloc;
-       }
-
        if (oi->ip_dyn_features & OCFS2_INLINE_DATA_FL)
                ret = ocfs2_readpage_inline(inode, page);
        else
                ret = block_read_full_page(page, ocfs2_get_block);
        unlock = 0;
 
-       ocfs2_data_unlock(inode, 0);
 out_alloc:
        up_read(&OCFS2_I(inode)->ip_alloc_sem);
 out_meta_unlock:
@@ -638,34 +629,12 @@ static ssize_t ocfs2_direct_IO(int rw,
        if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
                return 0;
 
-       if (!ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb))) {
-               /*
-                * We get PR data locks even for O_DIRECT.  This
-                * allows concurrent O_DIRECT I/O but doesn't let
-                * O_DIRECT with extending and buffered zeroing writes
-                * race.  If they did race then the buffered zeroing
-                * could be written back after the O_DIRECT I/O.  It's
-                * one thing to tell people not to mix buffered and
-                * O_DIRECT writes, but expecting them to understand
-                * that file extension is also an implicit buffered
-                * write is too much.  By getting the PR we force
-                * writeback of the buffered zeroing before
-                * proceeding.
-                */
-               ret = ocfs2_data_lock(inode, 0);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-               ocfs2_data_unlock(inode, 0);
-       }
-
        ret = blockdev_direct_IO_no_locking(rw, iocb, inode,
                                            inode->i_sb->s_bdev, iov, offset,
                                            nr_segs, 
                                            ocfs2_direct_IO_get_blocks,
                                            ocfs2_dio_end_io);
-out:
+
        mlog_exit(ret);
        return ret;
 }
@@ -728,6 +697,27 @@ static void ocfs2_clear_page_regions(struct page *page,
        kunmap_atomic(kaddr, KM_USER0);
 }
 
+/*
+ * Nonsparse file systems fully allocate before we get to the write
+ * code. This prevents ocfs2_write() from tagging the write as an
+ * allocating one, which means ocfs2_map_page_blocks() might try to
+ * read-in the blocks at the tail of our file. Avoid reading them by
+ * testing i_size against each block offset.
+ */
+static int ocfs2_should_read_blk(struct inode *inode, struct page *page,
+                                unsigned int block_start)
+{
+       u64 offset = page_offset(page) + block_start;
+
+       if (ocfs2_sparse_alloc(OCFS2_SB(inode->i_sb)))
+               return 1;
+
+       if (i_size_read(inode) > offset)
+               return 1;
+
+       return 0;
+}
+
 /*
  * Some of this taken from block_prepare_write(). We already have our
  * mapping by now though, and the entire write will be allocating or
@@ -781,6 +771,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno,
                                set_buffer_uptodate(bh);
                } else if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
                           !buffer_new(bh) &&
+                          ocfs2_should_read_blk(inode, page, block_start) &&
                           (block_start < from || block_end > to)) {
                        ll_rw_block(READ, 1, &bh);
                        *wait_bh++=bh;
@@ -1492,7 +1483,7 @@ int ocfs2_size_fits_inline_data(struct buffer_head *di_bh, u64 new_size)
 {
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
 
-       if (new_size < le16_to_cpu(di->id2.i_data.id_count))
+       if (new_size <= le16_to_cpu(di->id2.i_data.id_count))
                return 1;
        return 0;
 }
@@ -1747,25 +1738,17 @@ static int ocfs2_write_begin(struct file *file, struct address_space *mapping,
         */
        down_write(&OCFS2_I(inode)->ip_alloc_sem);
 
-       ret = ocfs2_data_lock(inode, 1);
-       if (ret) {
-               mlog_errno(ret);
-               goto out_fail;
-       }
-
        ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep,
                                       fsdata, di_bh, NULL);
        if (ret) {
                mlog_errno(ret);
-               goto out_fail_data;
+               goto out_fail;
        }
 
        brelse(di_bh);
 
        return 0;
 
-out_fail_data:
-       ocfs2_data_unlock(inode, 1);
 out_fail:
        up_write(&OCFS2_I(inode)->ip_alloc_sem);
 
@@ -1886,7 +1869,6 @@ static int ocfs2_write_end(struct file *file, struct address_space *mapping,
 
        ret = ocfs2_write_end_nolock(mapping, pos, len, copied, page, fsdata);
 
-       ocfs2_data_unlock(inode, 1);
        up_write(&OCFS2_I(inode)->ip_alloc_sem);
        ocfs2_meta_unlock(inode, 1);