aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_icache.c13
-rw-r--r--fs/xfs/xfs_icache.h2
2 files changed, 14 insertions, 1 deletions
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 08ba4c6e1359..6e522ff5a006 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1211,6 +1211,9 @@ xfs_inode_free_eofblocks(
1211{ 1211{
1212 int ret; 1212 int ret;
1213 struct xfs_eofblocks *eofb = args; 1213 struct xfs_eofblocks *eofb = args;
1214 bool need_iolock = true;
1215
1216 ASSERT(!eofb || (eofb && eofb->eof_scan_owner != 0));
1214 1217
1215 if (!xfs_can_free_eofblocks(ip, false)) { 1218 if (!xfs_can_free_eofblocks(ip, false)) {
1216 /* inode could be preallocated or append-only */ 1219 /* inode could be preallocated or append-only */
@@ -1235,9 +1238,17 @@ xfs_inode_free_eofblocks(
1235 if (eofb->eof_flags & XFS_EOF_FLAGS_MINFILESIZE && 1238 if (eofb->eof_flags & XFS_EOF_FLAGS_MINFILESIZE &&
1236 XFS_ISIZE(ip) < eofb->eof_min_file_size) 1239 XFS_ISIZE(ip) < eofb->eof_min_file_size)
1237 return 0; 1240 return 0;
1241
1242 /*
1243 * A scan owner implies we already hold the iolock. Skip it in
1244 * xfs_free_eofblocks() to avoid deadlock. This also eliminates
1245 * the possibility of EAGAIN being returned.
1246 */
1247 if (eofb->eof_scan_owner == ip->i_ino)
1248 need_iolock = false;
1238 } 1249 }
1239 1250
1240 ret = xfs_free_eofblocks(ip->i_mount, ip, true); 1251 ret = xfs_free_eofblocks(ip->i_mount, ip, need_iolock);
1241 1252
1242 /* don't revisit the inode if we're not waiting */ 1253 /* don't revisit the inode if we're not waiting */
1243 if (ret == -EAGAIN && !(flags & SYNC_WAIT)) 1254 if (ret == -EAGAIN && !(flags & SYNC_WAIT))
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index 6250430d609c..98687af6a99d 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -27,6 +27,7 @@ struct xfs_eofblocks {
27 kgid_t eof_gid; 27 kgid_t eof_gid;
28 prid_t eof_prid; 28 prid_t eof_prid;
29 __u64 eof_min_file_size; 29 __u64 eof_min_file_size;
30 xfs_ino_t eof_scan_owner;
30}; 31};
31 32
32#define SYNC_WAIT 0x0001 /* wait for i/o to complete */ 33#define SYNC_WAIT 0x0001 /* wait for i/o to complete */
@@ -84,6 +85,7 @@ xfs_fs_eofblocks_from_user(
84 dst->eof_flags = src->eof_flags; 85 dst->eof_flags = src->eof_flags;
85 dst->eof_prid = src->eof_prid; 86 dst->eof_prid = src->eof_prid;
86 dst->eof_min_file_size = src->eof_min_file_size; 87 dst->eof_min_file_size = src->eof_min_file_size;
88 dst->eof_scan_owner = NULLFSINO;
87 89
88 dst->eof_uid = INVALID_UID; 90 dst->eof_uid = INVALID_UID;
89 if (src->eof_flags & XFS_EOF_FLAGS_UID) { 91 if (src->eof_flags & XFS_EOF_FLAGS_UID) {