Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=92dfe8d266eaf35a50607a0e0dcf525e1d367c80
Commit:     92dfe8d266eaf35a50607a0e0dcf525e1d367c80
Parent:     511105b3d7c2440ee84fc3f90d200569aac88162
Author:     David Chinner <[EMAIL PROTECTED]>
AuthorDate: Thu May 24 15:22:19 2007 +1000
Committer:  Tim Shimmin <[EMAIL PROTECTED]>
CommitDate: Sat Jul 14 15:23:40 2007 +1000

    [XFS] Make hole punching at EOF atomic.
    
    If hole punching at EOF is done as two steps (i.e. truncate then extend)
    the file is in a transient state between the two steps where an
    application can see the incorrect file size. Punching a hole to EOF needs
    to be treated in teh same way as all other hole punching cases so that the
    file size is never seen to change.
    
    SGI-PV: 962012
    SGI-Modid: xfs-linux-melb:xfs-kern:28641a
    
    Signed-off-by: David Chinner <[EMAIL PROTECTED]>
    Signed-off-by: Vlad Apostolov <[EMAIL PROTECTED]>
    Signed-off-by: Tim Shimmin <[EMAIL PROTECTED]>
---
 fs/xfs/xfs_rw.h       |   14 +++++++++++---
 fs/xfs/xfs_vnodeops.c |   28 ++++++++++++++++++----------
 2 files changed, 29 insertions(+), 13 deletions(-)

diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h
index 188b296..ba74000 100644
--- a/fs/xfs/xfs_rw.h
+++ b/fs/xfs/xfs_rw.h
@@ -72,6 +72,12 @@ xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb)
 }
 
 /*
+ * Flags for xfs_free_eofblocks
+ */
+#define XFS_FREE_EOF_LOCK      (1<<0)
+#define XFS_FREE_EOF_NOLOCK    (1<<1)
+
+/*
  * Prototypes for functions in xfs_rw.c.
  */
 extern int xfs_write_clear_setuid(struct xfs_inode *ip);
@@ -91,10 +97,12 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount 
*mp,
 extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
 extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock);
 extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags,
-                      cred_t *credp);
+                       cred_t *credp);
 extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf,
-                                xfs_off_t offset, cred_t *credp, int flags);
+                       xfs_off_t offset, cred_t *credp, int flags);
 extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state,
-                          cred_t *credp);
+                       cred_t *credp);
+extern int xfs_free_eofblocks(struct xfs_mount *mp, struct xfs_inode *ip,
+                       int flags);
 
 #endif /* __XFS_RW_H__ */
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 70bc82f..6420ca8 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -1201,13 +1201,15 @@ xfs_fsync(
 }
 
 /*
- * This is called by xfs_inactive to free any blocks beyond eof,
- * when the link count isn't zero.
+ * This is called by xfs_inactive to free any blocks beyond eof
+ * when the link count isn't zero and by xfs_dm_punch_hole() when
+ * punching a hole to EOF.
  */
-STATIC int
-xfs_inactive_free_eofblocks(
+int
+xfs_free_eofblocks(
        xfs_mount_t     *mp,
-       xfs_inode_t     *ip)
+       xfs_inode_t     *ip,
+       int             flags)
 {
        xfs_trans_t     *tp;
        int             error;
@@ -1216,6 +1218,7 @@ xfs_inactive_free_eofblocks(
        xfs_filblks_t   map_len;
        int             nimaps;
        xfs_bmbt_irec_t imap;
+       int             use_iolock = (flags & XFS_FREE_EOF_LOCK);
 
        /*
         * Figure out if there are any blocks beyond the end
@@ -1256,11 +1259,13 @@ xfs_inactive_free_eofblocks(
                 * cache and we can't
                 * do that within a transaction.
                 */
-               xfs_ilock(ip, XFS_IOLOCK_EXCL);
+               if (use_iolock)
+                       xfs_ilock(ip, XFS_IOLOCK_EXCL);
                error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
                                    ip->i_size);
                if (error) {
-                       xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+                       if (use_iolock)
+                               xfs_iunlock(ip, XFS_IOLOCK_EXCL);
                        return error;
                }
 
@@ -1297,7 +1302,8 @@ xfs_inactive_free_eofblocks(
                        error = xfs_trans_commit(tp,
                                                XFS_TRANS_RELEASE_LOG_RES);
                }
-               xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL);
+               xfs_iunlock(ip, (use_iolock ? (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)
+                                           : XFS_ILOCK_EXCL));
        }
        return error;
 }
@@ -1573,7 +1579,8 @@ xfs_release(
                     (ip->i_df.if_flags & XFS_IFEXTENTS))  &&
                    (!(ip->i_d.di_flags &
                                (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)))) {
-                       if ((error = xfs_inactive_free_eofblocks(mp, ip)))
+                       error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
+                       if (error)
                                return error;
                        /* Update linux inode block count after free above */
                        vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
@@ -1654,7 +1661,8 @@ xfs_inactive(
                     (!(ip->i_d.di_flags &
                                (XFS_DIFLAG_PREALLOC | XFS_DIFLAG_APPEND)) ||
                      (ip->i_delayed_blks != 0)))) {
-                       if ((error = xfs_inactive_free_eofblocks(mp, ip)))
+                       error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_LOCK);
+                       if (error)
                                return VN_INACTIVE_CACHE;
                        /* Update linux inode block count after free above */
                        vn_to_inode(vp)->i_blocks = XFS_FSB_TO_BB(mp,
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to