ocfs2: take ip_alloc_sem during entire truncate
authorMark Fasheh <mark.fasheh@oracle.com>
Wed, 9 May 2007 20:40:18 +0000 (13:40 -0700)
committerMark Fasheh <mark.fasheh@oracle.com>
Wed, 11 Jul 2007 00:19:57 +0000 (17:19 -0700)
Use of the alloc sem during truncate was too narrow - we want to protect
the i_size change and page truncation against mmap now.

Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
fs/ocfs2/alloc.c
fs/ocfs2/file.c

index 19712a7d145feeeded8e6b21bfcd9ec7ac2a2349..02b6e7af8edbdd077d8e567506e2fbcd56519d9f 100644 (file)
@@ -3631,8 +3631,6 @@ int ocfs2_commit_truncate(struct ocfs2_super *osb,
 
        mlog_entry_void();
 
-       down_write(&OCFS2_I(inode)->ip_alloc_sem);
-
        new_highest_cpos = ocfs2_clusters_for_bytes(osb->sb,
                                                     i_size_read(inode));
 
@@ -3754,7 +3752,6 @@ start:
        goto start;
 
 bail:
-       up_write(&OCFS2_I(inode)->ip_alloc_sem);
 
        ocfs2_schedule_truncate_log_flush(osb, 1);
 
index 4979b667571734c151a88b2a03f01db5e2b8c761..566f9b70ec9122567c986455fcd22f5f888bead9 100644 (file)
@@ -326,9 +326,6 @@ static int ocfs2_truncate_file(struct inode *inode,
                   (unsigned long long)OCFS2_I(inode)->ip_blkno,
                   (unsigned long long)new_i_size);
 
-       unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
-       truncate_inode_pages(inode->i_mapping, new_i_size);
-
        fe = (struct ocfs2_dinode *) di_bh->b_data;
        if (!OCFS2_IS_VALID_DINODE(fe)) {
                OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe);
@@ -363,16 +360,23 @@ static int ocfs2_truncate_file(struct inode *inode,
        if (new_i_size == le64_to_cpu(fe->i_size))
                goto bail;
 
+       down_write(&OCFS2_I(inode)->ip_alloc_sem);
+
        /* This forces other nodes to sync and drop their pages. Do
         * this even if we have a truncate without allocation change -
         * ocfs2 cluster sizes can be much greater than page size, so
         * we have to truncate them anyway.  */
        status = ocfs2_data_lock(inode, 1);
        if (status < 0) {
+               up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
                mlog_errno(status);
                goto bail;
        }
 
+       unmap_mapping_range(inode->i_mapping, new_i_size + PAGE_SIZE - 1, 0, 1);
+       truncate_inode_pages(inode->i_mapping, new_i_size);
+
        /* alright, we're going to need to do a full blown alloc size
         * change. Orphan the inode so that recovery can complete the
         * truncate if necessary. This does the task of marking
@@ -399,6 +403,8 @@ static int ocfs2_truncate_file(struct inode *inode,
 bail_unlock_data:
        ocfs2_data_unlock(inode, 1);
 
+       up_write(&OCFS2_I(inode)->ip_alloc_sem);
+
 bail:
 
        mlog_exit(status);