summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-01-06 16:25:40 -0800
committerDarrick J. Wong <djwong@kernel.org>2021-03-25 17:08:45 -0700
commitd02e2f584e3d63f0b1c64d91bca39646a5dabb51 (patch)
tree3e3cb4d71c61189a47d58c3fbe084ddc2bb7237a /fs
parent9693edf89043234cd3a062294740d0ee9e9b72e9 (diff)
xfs: check that the rtrmapbt maxlevels doesn't increase when growing fs
The size of filesystem transaction reservations depends on the maximum height (maxlevels) of the realtime btrees. Since we don't want a grow operation to increase the reservation size enough that we'll fail the minimum log size checks on the next mount, constrain growfs operations if they would cause an increase in those maxlevels. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_fsops.c7
-rw-r--r--fs/xfs/xfs_rtalloc.c31
-rw-r--r--fs/xfs/xfs_rtalloc.h4
3 files changed, 40 insertions, 2 deletions
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 9c7c104e47fa..81cb9d25e064 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -21,6 +21,7 @@
#include "xfs_ag_resv.h"
#include "xfs_inode.h"
#include "xfs_icache.h"
+#include "xfs_rtalloc.h"
/*
* growfs operations
@@ -43,7 +44,11 @@ xfs_growfs_data_private(
nb = in->newblocks;
if (nb < mp->m_sb.sb_dblocks)
return -EINVAL;
- if ((error = xfs_sb_validate_fsb_count(&mp->m_sb, nb)))
+ error = xfs_sb_validate_fsb_count(&mp->m_sb, nb);
+ if (error)
+ return error;
+ error = xfs_growfs_check_rt_maxlevels(mp, nb, mp->m_sb.sb_rblocks);
+ if (error)
return error;
error = xfs_buf_read_uncached(mp->m_ddev_targp,
XFS_FSB_TO_BB(mp, nb) - XFS_FSS_TO_BB(mp, 1),
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 77e4608ff248..3af98a1d0ad9 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -27,6 +27,7 @@
#include "xfs_ag_resv.h"
#include "xfs_error.h"
#include "xfs_quota.h"
+#include "xfs_rtrmap_btree.h"
/*
* Read and return the summary information for a given extent size,
@@ -905,6 +906,29 @@ xfs_alloc_rsum_cache(
*/
/*
+ * Transaction reservation sizes depend on the realtime btree maxlevels, which
+ * is in turn computed from the size of the data device (where the btrees live)
+ * and the size of the rt volume. Make sure they don't increase, which could
+ * cause us to fail minimum log size checks at the next mount.
+ */
+int
+xfs_growfs_check_rt_maxlevels(
+ struct xfs_mount *mp,
+ xfs_rfsblock_t dblocks,
+ xfs_rfsblock_t rblocks)
+{
+ unsigned int new;
+
+ if (xfs_sb_version_hasrtrmapbt(&mp->m_sb)) {
+ new = xfs_rtrmapbt_compute_maxlevels(mp, dblocks, rblocks);
+ if (new > mp->m_rtrmap_maxlevels)
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
* Grow the realtime area of the filesystem.
*/
int
@@ -940,7 +964,12 @@ xfs_growfs_rt(
(nrblocks = in->newblocks) <= sbp->sb_rblocks ||
(sbp->sb_rblocks && (in->extsize != sbp->sb_rextsize)))
return -EINVAL;
- if ((error = xfs_sb_validate_fsb_count(sbp, nrblocks)))
+ error = xfs_sb_validate_fsb_count(sbp, nrblocks);
+ if (error)
+ return error;
+ error = xfs_growfs_check_rt_maxlevels(mp, mp->m_sb.sb_dblocks,
+ nrblocks);
+ if (error)
return error;
/*
* Read in the last block of the device, make sure it exists.
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index eac720cc7e98..2019c6822977 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -91,6 +91,9 @@ xfs_rtpick_extent(
xfs_extlen_t len, /* allocation length (rtextents) */
xfs_rtblock_t *pick); /* result rt extent */
+int xfs_growfs_check_rt_maxlevels(struct xfs_mount *mp, xfs_rfsblock_t dblocks,
+ xfs_rfsblock_t rblocks);
+
/*
* Grow the realtime area of the filesystem.
*/
@@ -150,6 +153,7 @@ void xfs_rtunlock(struct xfs_mount *mp, unsigned int lock_flags);
# define xfs_rtallocate_extent(t,b,min,max,l,f,p,rb) (ENOSYS)
# define xfs_rtfree_extent(t,b,l) (ENOSYS)
# define xfs_rtpick_extent(m,t,l,rb) (ENOSYS)
+# define xfs_growfs_check_rt_maxlevels(m,d,r) (0)
# define xfs_growfs_rt(mp,in) (ENOSYS)
# define xfs_rtalloc_query_range(t,l,h,f,p) (ENOSYS)
# define xfs_rtalloc_query_all(t,f,p) (ENOSYS)