diff options
-rw-r--r-- | fs/xfs/xfs_icache.c | 13 | ||||
-rw-r--r-- | fs/xfs/xfs_icache.h | 2 |
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) { |