aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_mount.c
diff options
context:
space:
mode:
authorYingping Lu <yingping@sgi.com>2006-06-09 00:55:18 -0400
committerNathan Scott <nathans@sgi.com>2006-06-09 00:55:18 -0400
commitd210a28cd851082cec9b282443f8cc0e6fc09830 (patch)
tree77b8c843d4cb7e6095b607570c5fd16702e50592 /fs/xfs/xfs_mount.c
parentd3446eac3f50dade2f09ed212b112609ee78fb33 (diff)
[XFS] In actual allocation of file system blocks and freeing extents, the
transaction within each such operation may involve multiple locking of AGF buffer. While the freeing extent function has sorted the extents based on AGF number before entering into transaction, however, when the file system space is very limited, the allocation of space would try every AGF to get space allocated, this could potentially cause out-of-order locking, thus deadlock could happen. This fix mitigates the scarce space for allocation by setting aside a few blocks without reservation, and avoid deadlock by maintaining ascending order of AGF locking. SGI-PV: 947395 SGI-Modid: xfs-linux-melb:xfs-kern:210801a Signed-off-by: Yingping Lu <yingping@sgi.com> Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r--fs/xfs/xfs_mount.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index c0b1c2906880..4b7be49cc4de 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1254,6 +1254,26 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
1254 1254
1255 xfs_trans_log_buf(tp, bp, first, last); 1255 xfs_trans_log_buf(tp, bp, first, last);
1256} 1256}
1257
1258/*
1259 * In order to avoid ENOSPC-related deadlock caused by
1260 * out-of-order locking of AGF buffer (PV 947395), we place
1261 * constraints on the relationship among actual allocations for
1262 * data blocks, freelist blocks, and potential file data bmap
1263 * btree blocks. However, these restrictions may result in no
1264 * actual space allocated for a delayed extent, for example, a data
1265 * block in a certain AG is allocated but there is no additional
1266 * block for the additional bmap btree block due to a split of the
1267 * bmap btree of the file. The result of this may lead to an
1268 * infinite loop in xfssyncd when the file gets flushed to disk and
1269 * all delayed extents need to be actually allocated. To get around
1270 * this, we explicitly set aside a few blocks which will not be
1271 * reserved in delayed allocation. Considering the minimum number of
1272 * needed freelist blocks is 4 fsbs, a potential split of file's bmap
1273 * btree requires 1 fsb, so we set the number of set-aside blocks to 8.
1274*/
1275#define SET_ASIDE_BLOCKS 8
1276
1257/* 1277/*
1258 * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply 1278 * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply
1259 * a delta to a specified field in the in-core superblock. Simply 1279 * a delta to a specified field in the in-core superblock. Simply
@@ -1298,7 +1318,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
1298 return 0; 1318 return 0;
1299 case XFS_SBS_FDBLOCKS: 1319 case XFS_SBS_FDBLOCKS:
1300 1320
1301 lcounter = (long long)mp->m_sb.sb_fdblocks; 1321 lcounter = (long long)mp->m_sb.sb_fdblocks - SET_ASIDE_BLOCKS;
1302 res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); 1322 res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
1303 1323
1304 if (delta > 0) { /* Putting blocks back */ 1324 if (delta > 0) { /* Putting blocks back */
@@ -1332,7 +1352,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
1332 } 1352 }
1333 } 1353 }
1334 1354
1335 mp->m_sb.sb_fdblocks = lcounter; 1355 mp->m_sb.sb_fdblocks = lcounter + SET_ASIDE_BLOCKS;
1336 return 0; 1356 return 0;
1337 case XFS_SBS_FREXTENTS: 1357 case XFS_SBS_FREXTENTS:
1338 lcounter = (long long)mp->m_sb.sb_frextents; 1358 lcounter = (long long)mp->m_sb.sb_frextents;