From: Jeff Mahoney <jeffm@suse.com>
Subject: xfs/dmapi: Re-add flags for xfs_free_eofblocks
Patch-mainline: If dmapi ever gets upstream
References: bnc#582872

 2.6.33 removed the NOLOCK flag from xfs_free_eofblocks. xfs_dm_punch_hole
 needs it because it already holds the iolock for the vnode it's operating
 on. This patch restores the flag to avoid a pretty obvious deadlock in
 dmapi.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 fs/xfs/dmapi/xfs_dm.c |    2 +-
 fs/xfs/xfs_rw.h       |    6 ++++++
 fs/xfs/xfs_vnodeops.c |   10 +++-------
 3 files changed, 10 insertions(+), 8 deletions(-)

--- a/fs/xfs/dmapi/xfs_dm.c
+++ b/fs/xfs/dmapi/xfs_dm.c
@@ -2481,7 +2481,7 @@ xfs_dm_punch_hole(
 	 * leaving them around if we are migrating the file....
 	 */
 	if (!error && (len == 0)) {
-		error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_NOLOCK);
+		error = xfs_free_eofblocks(mp, ip, XFS_FREE_EOF_HASLOCK);
 	}
 
 	/*
--- a/fs/xfs/xfs_rw.h
+++ b/fs/xfs/xfs_rw.h
@@ -52,6 +52,12 @@ extern xfs_extlen_t xfs_get_extsz_hint(s
 /*
  * Prototypes for functions in xfs_vnodeops.c.
  */
+
+/*
+ * Flags for xfs_free_eofblocks
+ */
+#define XFS_FREE_EOF_TRYLOCK   (1<<0)
+#define XFS_FREE_EOF_HASLOCK   (1<<1)
 extern int xfs_free_eofblocks(struct xfs_mount *mp, struct xfs_inode *ip,
                        int flags);
 
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -709,11 +709,6 @@ xfs_fsync(
 }
 
 /*
- * Flags for xfs_free_eofblocks
- */
-#define XFS_FREE_EOF_TRYLOCK	(1<<0)
-
-/*
  * 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.
@@ -777,14 +772,15 @@ xfs_free_eofblocks(
 				xfs_trans_cancel(tp, 0);
 				return 0;
 			}
-		} else {
+		} else if (!(flags & XFS_FREE_EOF_HASLOCK)){
 			xfs_ilock(ip, XFS_IOLOCK_EXCL);
 		}
 		error = xfs_itruncate_start(ip, XFS_ITRUNC_DEFINITE,
 				    ip->i_size);
 		if (error) {
 			xfs_trans_cancel(tp, 0);
-			xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+			if (!(flags & XFS_FREE_EOF_HASLOCK))
+				xfs_iunlock(ip, XFS_IOLOCK_EXCL);
 			return error;
 		}
 
