diff options
author | Darrick J. Wong <darrick.wong@oracle.com> | 2016-10-03 09:11:44 -0700 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2016-10-05 16:26:27 -0700 |
commit | 84d6961910ea7b3ae8d8338f5b4df25dea68cee9 (patch) | |
tree | f9c9c9f6f34bce9ff3b035df350cfe70e16b24f1 /fs/xfs/xfs_mount.c | |
parent | f7ca35227253dc8244fd908140b06010e67a31e5 (diff) | |
download | linux-84d6961910ea7b3ae8d8338f5b4df25dea68cee9.tar.gz linux-84d6961910ea7b3ae8d8338f5b4df25dea68cee9.tar.bz2 linux-84d6961910ea7b3ae8d8338f5b4df25dea68cee9.zip |
xfs: preallocate blocks for worst-case btree expansion
To gracefully handle the situation where a CoW operation turns a
single refcount extent into a lot of tiny ones and then run out of
space when a tree split has to happen, use the per-AG reserved block
pool to pre-allocate all the space we'll ever need for a maximal
btree. For a 4K block size, this only costs an overhead of 0.3% of
available disk space.
When reflink is enabled, we have an unfortunate problem with rmap --
since we can share a block billions of times, this means that the
reverse mapping btree can expand basically infinitely. When an AG is
so full that there are no free blocks with which to expand the rmapbt,
the filesystem will shut down hard.
This is rather annoying to the user, so use the AG reservation code to
reserve a "reasonable" amount of space for rmap. We'll prevent
reflinks and CoW operations if we think we're getting close to
exhausting an AG's free space rather than shutting down, but this
permanent reservation should be enough for "most" users. Hopefully.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
[hch@lst.de: ensure that we invalidate the freed btree buffer]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 099c00ecb078..40fedc00b30d 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -995,10 +995,17 @@ xfs_mountfs( xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); goto out_quota; } + + /* Reserve AG blocks for future btree expansion. */ + error = xfs_fs_reserve_ag_blocks(mp); + if (error && error != -ENOSPC) + goto out_agresv; } return 0; + out_agresv: + xfs_fs_unreserve_ag_blocks(mp); out_quota: xfs_qm_unmount_quotas(mp); out_rtunmount: @@ -1043,6 +1050,7 @@ xfs_unmountfs( cancel_delayed_work_sync(&mp->m_eofblocks_work); + xfs_fs_unreserve_ag_blocks(mp); xfs_qm_unmount_quotas(mp); xfs_rtunmount_inodes(mp); IRELE(mp->m_rootip); |