import xfsprogs-5.0.0-8.el8
This commit is contained in:
parent
aaad17a429
commit
2382ea8b28
@ -0,0 +1,35 @@
|
|||||||
|
From 0d7b09ac95e4cde766a534fdb7ea8dd46451ad53 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Fri, 4 Dec 2020 12:17:12 -0500
|
||||||
|
Subject: [PATCH] xfs_quota: document how the default quota is stored
|
||||||
|
|
||||||
|
Nowhere in the man page is the default quota described; what it
|
||||||
|
does or where it is stored. Add some brief information about this.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
man/man8/xfs_quota.8 | 6 ++++++
|
||||||
|
1 file changed, 6 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/man/man8/xfs_quota.8 b/man/man8/xfs_quota.8
|
||||||
|
index dd0479cd..6ead7ee9 100644
|
||||||
|
--- a/man/man8/xfs_quota.8
|
||||||
|
+++ b/man/man8/xfs_quota.8
|
||||||
|
@@ -178,6 +178,12 @@ to a file on
|
||||||
|
where the user's quota has not been exceeded.
|
||||||
|
Then after rectifying the quota situation, the file can be moved back to the
|
||||||
|
filesystem it belongs on.
|
||||||
|
+.SS Default Quotas
|
||||||
|
+The XFS quota subsystem allows a default quota to be enforced
|
||||||
|
+for any user, group or project which does not have a quota limit
|
||||||
|
+explicitly set.
|
||||||
|
+These limits are stored in and displayed as ID 0's limits, although they
|
||||||
|
+do not actually limit ID 0.
|
||||||
|
.SH USER COMMANDS
|
||||||
|
.TP
|
||||||
|
.B print
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
@ -0,0 +1,92 @@
|
|||||||
|
xfs_repair: Use proper min/max values in compute_level_geometry
|
||||||
|
|
||||||
|
When compute_level_geometry was added it exclusively uses
|
||||||
|
m_alloc_mnr/m_alloc_mxr but the rmap btree should be using
|
||||||
|
m_rmap_mnr/m_rmap_mxr. Pass those in directly to fix the
|
||||||
|
problem.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
---
|
||||||
|
|
||||||
|
diff --git a/repair/phase5.c b/repair/phase5.c
|
||||||
|
index 0b8a55ff..dff342c8 100644
|
||||||
|
--- a/repair/phase5.c
|
||||||
|
+++ b/repair/phase5.c
|
||||||
|
@@ -355,12 +355,12 @@ compute_level_geometry(
|
||||||
|
struct bt_stat_level *lptr,
|
||||||
|
uint64_t nr_this_level,
|
||||||
|
int slack,
|
||||||
|
- bool leaf)
|
||||||
|
+ uint maxrecs,
|
||||||
|
+ uint minrecs)
|
||||||
|
{
|
||||||
|
- unsigned int maxrecs = mp->m_alloc_mxr[!leaf];
|
||||||
|
unsigned int desired_npb;
|
||||||
|
|
||||||
|
- desired_npb = max(mp->m_alloc_mnr[!leaf], maxrecs - slack);
|
||||||
|
+ desired_npb = max(minrecs, maxrecs - slack);
|
||||||
|
lptr->num_recs_tot = nr_this_level;
|
||||||
|
lptr->num_blocks = max(1ULL, nr_this_level / desired_npb);
|
||||||
|
|
||||||
|
@@ -410,7 +410,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
|
||||||
|
* of the tree and set up the cursor for the leaf level
|
||||||
|
* (note that the same code is duplicated further down)
|
||||||
|
*/
|
||||||
|
- compute_level_geometry(mp, lptr, num_extents, 2, true);
|
||||||
|
+ compute_level_geometry(mp, lptr, num_extents, 2,
|
||||||
|
+ mp->m_alloc_mxr[0], mp->m_alloc_mnr[0]);
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
#ifdef XR_BLD_FREE_TRACE
|
||||||
|
@@ -429,7 +430,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
|
||||||
|
lptr = &btree_curs->level[level];
|
||||||
|
|
||||||
|
compute_level_geometry(mp, lptr,
|
||||||
|
- p_lptr->num_blocks, 0, false);
|
||||||
|
+ p_lptr->num_blocks, 0,
|
||||||
|
+ mp->m_alloc_mxr[1], mp->m_alloc_mnr[1]);
|
||||||
|
#ifdef XR_BLD_FREE_TRACE
|
||||||
|
fprintf(stderr, "%s %d %d %d %d %d\n", __func__,
|
||||||
|
level,
|
||||||
|
@@ -509,7 +511,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
|
||||||
|
* of the number of extents changing
|
||||||
|
*/
|
||||||
|
old_blocks = btree_curs->level[0].num_blocks;
|
||||||
|
- compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2, true);
|
||||||
|
+ compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2,
|
||||||
|
+ mp->m_alloc_mxr[0], mp->m_alloc_mnr[0]);
|
||||||
|
extra_blocks = 0;
|
||||||
|
|
||||||
|
if (old_blocks != btree_curs->level[0].num_blocks) {
|
||||||
|
@@ -578,7 +581,8 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno,
|
||||||
|
lptr = &btree_curs->level[level++];
|
||||||
|
|
||||||
|
compute_level_geometry(mp, lptr,
|
||||||
|
- p_lptr->num_blocks, 0, false);
|
||||||
|
+ p_lptr->num_blocks, 0,
|
||||||
|
+ mp->m_alloc_mxr[1], mp->m_alloc_mnr[1]);
|
||||||
|
}
|
||||||
|
ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
ASSERT(lptr->num_blocks == 1);
|
||||||
|
@@ -1399,7 +1403,8 @@ init_rmapbt_cursor(
|
||||||
|
* metadata AG entries without too many splits.
|
||||||
|
*/
|
||||||
|
compute_level_geometry(mp, lptr, num_recs,
|
||||||
|
- num_recs > mp->m_rmap_mxr[0] ? 10 : 0, true);
|
||||||
|
+ num_recs > mp->m_rmap_mxr[0] ? 10 : 0,
|
||||||
|
+ mp->m_rmap_mxr[0], mp->m_rmap_mnr[0]);
|
||||||
|
blocks_allocated = lptr->num_blocks;
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
@@ -1408,7 +1413,8 @@ init_rmapbt_cursor(
|
||||||
|
lptr = &btree_curs->level[level++];
|
||||||
|
|
||||||
|
compute_level_geometry(mp, lptr,
|
||||||
|
- p_lptr->num_blocks, 0, false);
|
||||||
|
+ p_lptr->num_blocks, 0,
|
||||||
|
+ mp->m_rmap_mxr[1], mp->m_rmap_mnr[1]);
|
||||||
|
blocks_allocated += lptr->num_blocks;
|
||||||
|
}
|
||||||
|
ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
|
||||||
|
|
@ -0,0 +1,227 @@
|
|||||||
|
From 36dc471cc9bb17868b79cf8dea8151b207387539 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Tue, 26 May 2020 14:36:26 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: allow individual timer extension
|
||||||
|
|
||||||
|
The only grace period which can be set via xfs_quota today is for id 0,
|
||||||
|
i.e. the default grace period for all users. However, setting an
|
||||||
|
individual grace period is useful; for example:
|
||||||
|
|
||||||
|
Alice has a soft quota of 100 inodes, and a hard quota of 200 inodes
|
||||||
|
Alice uses 150 inodes, and enters a short grace period
|
||||||
|
Alice really needs to use those 150 inodes past the grace period
|
||||||
|
The administrator extends Alice's grace period until next Monday
|
||||||
|
|
||||||
|
vfs quota users such as ext4 can do this today, with setquota -T
|
||||||
|
|
||||||
|
xfs_quota can now accept an optional user id or name (symmetric with
|
||||||
|
how warn limits are specified), in which case that user's grace period
|
||||||
|
is extended to expire the given amount of time from now().
|
||||||
|
|
||||||
|
To maintain compatibility with old command lines, if none of
|
||||||
|
[-d|id|name] are specified, default limits are set as before.
|
||||||
|
|
||||||
|
(kernelspace requires updates to enable all this as well.)
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
man/man8/xfs_quota.8 | 36 +++++++++++++++++--
|
||||||
|
quota/edit.c | 83 +++++++++++++++++++++++++++++++++++++-------
|
||||||
|
2 files changed, 104 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/man/man8/xfs_quota.8
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/man/man8/xfs_quota.8
|
||||||
|
+++ xfsprogs-5.0.0/man/man8/xfs_quota.8
|
||||||
|
@@ -460,14 +460,46 @@ must be specified.
|
||||||
|
.B \-bir
|
||||||
|
]
|
||||||
|
.I value
|
||||||
|
+[
|
||||||
|
+.B -d
|
||||||
|
+|
|
||||||
|
+.I id
|
||||||
|
+|
|
||||||
|
+.I name
|
||||||
|
+]
|
||||||
|
.br
|
||||||
|
Allows the quota enforcement timeout (i.e. the amount of time allowed
|
||||||
|
to pass before the soft limits are enforced as the hard limits) to
|
||||||
|
be modified. The current timeout setting can be displayed using the
|
||||||
|
.B state
|
||||||
|
-command. The value argument is a number of seconds, but units of
|
||||||
|
-\&'minutes', 'hours', 'days', and 'weeks' are also understood
|
||||||
|
+command.
|
||||||
|
+.br
|
||||||
|
+When setting the default timer via the
|
||||||
|
+.B \-d
|
||||||
|
+option, or for
|
||||||
|
+.B id
|
||||||
|
+0, or if no argument is given after
|
||||||
|
+.I value
|
||||||
|
+the
|
||||||
|
+.I value
|
||||||
|
+argument is a number of seconds indicating the relative amount of time after
|
||||||
|
+soft limits are exceeded, before hard limits are enforced.
|
||||||
|
+.br
|
||||||
|
+When setting any other individual timer by
|
||||||
|
+.I id
|
||||||
|
+or
|
||||||
|
+.I name,
|
||||||
|
+the
|
||||||
|
+.I value
|
||||||
|
+is the number of seconds from now, at which time the hard limits will be enforced.
|
||||||
|
+This allows extending the grace time of an individual user who has exceeded soft
|
||||||
|
+limits.
|
||||||
|
+.br
|
||||||
|
+For
|
||||||
|
+.I value,
|
||||||
|
+units of \&'minutes', 'hours', 'days', and 'weeks' are also understood
|
||||||
|
(as are their abbreviations 'm', 'h', 'd', and 'w').
|
||||||
|
+.br
|
||||||
|
.HP
|
||||||
|
.B warn
|
||||||
|
[
|
||||||
|
Index: xfsprogs-5.0.0/quota/edit.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/quota/edit.c
|
||||||
|
+++ xfsprogs-5.0.0/quota/edit.c
|
||||||
|
@@ -419,6 +419,7 @@ restore_f(
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_timer(
|
||||||
|
+ uint32_t id,
|
||||||
|
uint type,
|
||||||
|
uint mask,
|
||||||
|
char *dev,
|
||||||
|
@@ -427,14 +428,43 @@ set_timer(
|
||||||
|
fs_disk_quota_t d;
|
||||||
|
|
||||||
|
memset(&d, 0, sizeof(d));
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * If id is specified we are extending grace time by value
|
||||||
|
+ * Otherwise we are setting the default grace time
|
||||||
|
+ */
|
||||||
|
+ if (id) {
|
||||||
|
+ time_t now;
|
||||||
|
+
|
||||||
|
+ /* Get quota to find out whether user is past soft limits */
|
||||||
|
+ if (xfsquotactl(XFS_GETQUOTA, dev, type, id, (void *)&d) < 0) {
|
||||||
|
+ exitcode = 1;
|
||||||
|
+ fprintf(stderr, _("%s: cannot get quota: %s\n"),
|
||||||
|
+ progname, strerror(errno));
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ time(&now);
|
||||||
|
+
|
||||||
|
+ /* Only set grace time if user is already past soft limit */
|
||||||
|
+ if (d.d_blk_softlimit && d.d_bcount > d.d_blk_softlimit)
|
||||||
|
+ d.d_btimer = now + value;
|
||||||
|
+ if (d.d_ino_softlimit && d.d_icount > d.d_ino_softlimit)
|
||||||
|
+ d.d_itimer = now + value;
|
||||||
|
+ if (d.d_rtb_softlimit && d.d_rtbcount > d.d_rtb_softlimit)
|
||||||
|
+ d.d_rtbtimer = now + value;
|
||||||
|
+ } else {
|
||||||
|
+ d.d_btimer = value;
|
||||||
|
+ d.d_itimer = value;
|
||||||
|
+ d.d_rtbtimer = value;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
d.d_version = FS_DQUOT_VERSION;
|
||||||
|
d.d_flags = type;
|
||||||
|
d.d_fieldmask = mask;
|
||||||
|
- d.d_itimer = value;
|
||||||
|
- d.d_btimer = value;
|
||||||
|
- d.d_rtbtimer = value;
|
||||||
|
+ d.d_id = id;
|
||||||
|
|
||||||
|
- if (xfsquotactl(XFS_SETQLIM, dev, type, 0, (void *)&d) < 0) {
|
||||||
|
+ if (xfsquotactl(XFS_SETQLIM, dev, type, id, (void *)&d) < 0) {
|
||||||
|
exitcode = 1;
|
||||||
|
fprintf(stderr, _("%s: cannot set timer: %s\n"),
|
||||||
|
progname, strerror(errno));
|
||||||
|
@@ -447,10 +477,15 @@ timer_f(
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
uint value;
|
||||||
|
- int c, type = 0, mask = 0;
|
||||||
|
+ char *name = NULL;
|
||||||
|
+ uint32_t id = 0;
|
||||||
|
+ int c, flags = 0, type = 0, mask = 0;
|
||||||
|
|
||||||
|
- while ((c = getopt(argc, argv, "bgipru")) != EOF) {
|
||||||
|
+ while ((c = getopt(argc, argv, "bdgipru")) != EOF) {
|
||||||
|
switch (c) {
|
||||||
|
+ case 'd':
|
||||||
|
+ flags |= DEFAULTS_FLAG;
|
||||||
|
+ break;
|
||||||
|
case 'b':
|
||||||
|
mask |= FS_DQ_BTIMER;
|
||||||
|
break;
|
||||||
|
@@ -474,23 +509,45 @@ timer_f(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (argc != optind + 1)
|
||||||
|
+ /*
|
||||||
|
+ * Older versions of the command did not accept -d|id|name,
|
||||||
|
+ * so in that case we assume we're setting default timer,
|
||||||
|
+ * and the last arg is the timer value.
|
||||||
|
+ *
|
||||||
|
+ * Otherwise, if the defaults flag is set, we expect 1 more arg for
|
||||||
|
+ * timer value ; if not, 2 more args: 1 for value, one for id/name.
|
||||||
|
+ */
|
||||||
|
+ if (!(flags & DEFAULTS_FLAG) && (argc == optind + 1)) {
|
||||||
|
+ value = cvttime(argv[optind++]);
|
||||||
|
+ } else if (flags & DEFAULTS_FLAG) {
|
||||||
|
+ if (argc != optind + 1)
|
||||||
|
+ return command_usage(&timer_cmd);
|
||||||
|
+ value = cvttime(argv[optind++]);
|
||||||
|
+ } else if (argc == optind + 2) {
|
||||||
|
+ value = cvttime(argv[optind++]);
|
||||||
|
+ name = (flags & DEFAULTS_FLAG) ? "0" : argv[optind++];
|
||||||
|
+ } else
|
||||||
|
return command_usage(&timer_cmd);
|
||||||
|
|
||||||
|
- value = cvttime(argv[optind++]);
|
||||||
|
|
||||||
|
+ /* if none of -bir specified, set them all */
|
||||||
|
if (!mask)
|
||||||
|
mask = FS_DQ_TIMER_MASK;
|
||||||
|
|
||||||
|
if (!type) {
|
||||||
|
type = XFS_USER_QUOTA;
|
||||||
|
} else if (type != XFS_GROUP_QUOTA &&
|
||||||
|
- type != XFS_PROJ_QUOTA &&
|
||||||
|
- type != XFS_USER_QUOTA) {
|
||||||
|
+ type != XFS_PROJ_QUOTA &&
|
||||||
|
+ type != XFS_USER_QUOTA) {
|
||||||
|
return command_usage(&timer_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
- set_timer(type, mask, fs_path->fs_name, value);
|
||||||
|
+ if (name)
|
||||||
|
+ id = id_from_string(name, type);
|
||||||
|
+
|
||||||
|
+ if (id >= 0)
|
||||||
|
+ set_timer(id, type, mask, fs_path->fs_name, value);
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -616,9 +673,9 @@ edit_init(void)
|
||||||
|
|
||||||
|
timer_cmd.name = "timer";
|
||||||
|
timer_cmd.cfunc = timer_f;
|
||||||
|
- timer_cmd.argmin = 2;
|
||||||
|
+ timer_cmd.argmin = 1;
|
||||||
|
timer_cmd.argmax = -1;
|
||||||
|
- timer_cmd.args = _("[-bir] [-g|-p|-u] value");
|
||||||
|
+ timer_cmd.args = _("[-bir] [-g|-p|-u] value [-d|id|name]");
|
||||||
|
timer_cmd.oneline = _("set quota enforcement timeouts");
|
||||||
|
timer_cmd.help = timer_help;
|
||||||
|
timer_cmd.flags = CMD_FLAG_FOREIGN_OK;
|
@ -0,0 +1,69 @@
|
|||||||
|
From eaa5b0b79bcf2eb36f7a5e1a5b7171ad5ced7bac Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:33:36 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: fix unsigned int id comparisons
|
||||||
|
|
||||||
|
Fix compiler warnings about unsigned int comparisons by replacing them
|
||||||
|
with an explicit check for the one possible invalid value (-1U).
|
||||||
|
id_from_string sets exitcode to nonzero when it sees this value, so the
|
||||||
|
call sites don't have to do that.
|
||||||
|
|
||||||
|
Coverity-id: 1463855, 1463856, 1463857
|
||||||
|
Fixes: 67a73d6139d0 ("xfs_quota: refactor code to generate id from name")
|
||||||
|
Fixes: 36dc471cc9bb ("xfs_quota: allow individual timer extension")
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
quota/edit.c | 22 +++++++++++-----------
|
||||||
|
1 file changed, 11 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/quota/edit.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/quota/edit.c
|
||||||
|
+++ xfsprogs-5.0.0/quota/edit.c
|
||||||
|
@@ -307,11 +307,11 @@ limit_f(
|
||||||
|
|
||||||
|
|
||||||
|
id = id_from_string(name, type);
|
||||||
|
- if (id >= 0)
|
||||||
|
- set_limits(id, type, mask, fs_path->fs_name,
|
||||||
|
- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
- else
|
||||||
|
- exitcode = -1;
|
||||||
|
+ if (id == -1)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ set_limits(id, type, mask, fs_path->fs_name,
|
||||||
|
+ &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -545,9 +545,10 @@ timer_f(
|
||||||
|
if (name)
|
||||||
|
id = id_from_string(name, type);
|
||||||
|
|
||||||
|
- if (id >= 0)
|
||||||
|
- set_timer(id, type, mask, fs_path->fs_name, value);
|
||||||
|
+ if (id == -1)
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
+ set_timer(id, type, mask, fs_path->fs_name, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -642,11 +643,10 @@ warn_f(
|
||||||
|
}
|
||||||
|
|
||||||
|
id = id_from_string(name, type);
|
||||||
|
- if (id >= 0)
|
||||||
|
- set_warnings(id, type, mask, fs_path->fs_name, value);
|
||||||
|
- else
|
||||||
|
- exitcode = -1;
|
||||||
|
+ if (id == -1)
|
||||||
|
+ return 0;
|
||||||
|
|
||||||
|
+ set_warnings(id, type, mask, fs_path->fs_name, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,271 @@
|
|||||||
|
From 67a73d6139d0336eb7ced05bd78a26b57f408187 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Tue, 26 May 2020 14:36:04 -0400
|
||||||
|
Subject: [PATCH] xfs_quota: refactor code to generate id from name
|
||||||
|
|
||||||
|
There's boilerplate for setting limits and warnings, where we have
|
||||||
|
a case statement for each of the 3 quota types, and from there call
|
||||||
|
3 different functions to configure each of the 3 types, each of which
|
||||||
|
calls its own version of id to string function...
|
||||||
|
|
||||||
|
Refactor this so that the main function can call a generic id to string
|
||||||
|
conversion routine, and then call a common action. This save a lot of
|
||||||
|
LOC.
|
||||||
|
|
||||||
|
I was looking at allowing xfs to bump out individual grace periods like
|
||||||
|
setquota can do, and this refactoring allows us to add new actions like
|
||||||
|
that without copying all the boilerplate again.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
quota/edit.c | 194 +++++++++++++--------------------------------------
|
||||||
|
1 file changed, 49 insertions(+), 145 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/quota/edit.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/quota/edit.c
|
||||||
|
+++ xfsprogs-5.0.0/quota/edit.c
|
||||||
|
@@ -101,6 +101,40 @@ warn_help(void)
|
||||||
|
"\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
+static uint32_t
|
||||||
|
+id_from_string(
|
||||||
|
+ char *name,
|
||||||
|
+ int type)
|
||||||
|
+{
|
||||||
|
+ uint32_t id = -1;
|
||||||
|
+ const char *type_name = "unknown type";
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
+ case XFS_USER_QUOTA:
|
||||||
|
+ type_name = "user";
|
||||||
|
+ id = uid_from_string(name);
|
||||||
|
+ break;
|
||||||
|
+ case XFS_GROUP_QUOTA:
|
||||||
|
+ type_name = "group";
|
||||||
|
+ id = gid_from_string(name);
|
||||||
|
+ break;
|
||||||
|
+ case XFS_PROJ_QUOTA:
|
||||||
|
+ type_name = "project";
|
||||||
|
+ id = prid_from_string(name);
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ ASSERT(0);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (id == -1) {
|
||||||
|
+ fprintf(stderr, _("%s: invalid %s name: %s\n"),
|
||||||
|
+ type_name, progname, name);
|
||||||
|
+ exitcode = 1;
|
||||||
|
+ }
|
||||||
|
+ return id;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
set_limits(
|
||||||
|
uint32_t id,
|
||||||
|
@@ -135,75 +169,6 @@ set_limits(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-set_user_limits(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint64_t *bsoft,
|
||||||
|
- uint64_t *bhard,
|
||||||
|
- uint64_t *isoft,
|
||||||
|
- uint64_t *ihard,
|
||||||
|
- uint64_t *rtbsoft,
|
||||||
|
- uint64_t *rtbhard)
|
||||||
|
-{
|
||||||
|
- uid_t uid = uid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (uid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid user name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_limits(uid, type, mask, fs_path->fs_name,
|
||||||
|
- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-set_group_limits(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint64_t *bsoft,
|
||||||
|
- uint64_t *bhard,
|
||||||
|
- uint64_t *isoft,
|
||||||
|
- uint64_t *ihard,
|
||||||
|
- uint64_t *rtbsoft,
|
||||||
|
- uint64_t *rtbhard)
|
||||||
|
-{
|
||||||
|
- gid_t gid = gid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (gid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid group name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_limits(gid, type, mask, fs_path->fs_name,
|
||||||
|
- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-set_project_limits(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint64_t *bsoft,
|
||||||
|
- uint64_t *bhard,
|
||||||
|
- uint64_t *isoft,
|
||||||
|
- uint64_t *ihard,
|
||||||
|
- uint64_t *rtbsoft,
|
||||||
|
- uint64_t *rtbhard)
|
||||||
|
-{
|
||||||
|
- prid_t prid = prid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (prid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid project name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_limits(prid, type, mask, fs_path->fs_name,
|
||||||
|
- bsoft, bhard, isoft, ihard, rtbsoft, rtbhard);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* extract number of blocks from an ascii string */
|
||||||
|
static int
|
||||||
|
extractb(
|
||||||
|
@@ -258,6 +223,7 @@ limit_f(
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
+ uint32_t id;
|
||||||
|
uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard;
|
||||||
|
int c, type = 0, mask = 0, flags = 0;
|
||||||
|
uint bsize, ssize, endoptions;
|
||||||
|
@@ -339,20 +305,13 @@ limit_f(
|
||||||
|
return command_usage(&limit_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
- switch (type) {
|
||||||
|
- case XFS_USER_QUOTA:
|
||||||
|
- set_user_limits(name, type, mask,
|
||||||
|
- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
- break;
|
||||||
|
- case XFS_GROUP_QUOTA:
|
||||||
|
- set_group_limits(name, type, mask,
|
||||||
|
- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
- break;
|
||||||
|
- case XFS_PROJ_QUOTA:
|
||||||
|
- set_project_limits(name, type, mask,
|
||||||
|
- &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
+
|
||||||
|
+ id = id_from_string(name, type);
|
||||||
|
+ if (id >= 0)
|
||||||
|
+ set_limits(id, type, mask, fs_path->fs_name,
|
||||||
|
+ &bsoft, &bhard, &isoft, &ihard, &rtbsoft, &rtbhard);
|
||||||
|
+ else
|
||||||
|
+ exitcode = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -561,63 +520,13 @@ set_warnings(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void
|
||||||
|
-set_user_warnings(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint value)
|
||||||
|
-{
|
||||||
|
- uid_t uid = uid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (uid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid user name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_warnings(uid, type, mask, fs_path->fs_name, value);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-set_group_warnings(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint value)
|
||||||
|
-{
|
||||||
|
- gid_t gid = gid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (gid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid group name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_warnings(gid, type, mask, fs_path->fs_name, value);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static void
|
||||||
|
-set_project_warnings(
|
||||||
|
- char *name,
|
||||||
|
- uint type,
|
||||||
|
- uint mask,
|
||||||
|
- uint value)
|
||||||
|
-{
|
||||||
|
- prid_t prid = prid_from_string(name);
|
||||||
|
-
|
||||||
|
- if (prid == -1) {
|
||||||
|
- exitcode = 1;
|
||||||
|
- fprintf(stderr, _("%s: invalid project name: %s\n"),
|
||||||
|
- progname, name);
|
||||||
|
- } else
|
||||||
|
- set_warnings(prid, type, mask, fs_path->fs_name, value);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int
|
||||||
|
warn_f(
|
||||||
|
int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
+ uint32_t id;
|
||||||
|
uint value;
|
||||||
|
int c, flags = 0, type = 0, mask = 0;
|
||||||
|
|
||||||
|
@@ -675,17 +584,12 @@ warn_f(
|
||||||
|
return command_usage(&warn_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
- switch (type) {
|
||||||
|
- case XFS_USER_QUOTA:
|
||||||
|
- set_user_warnings(name, type, mask, value);
|
||||||
|
- break;
|
||||||
|
- case XFS_GROUP_QUOTA:
|
||||||
|
- set_group_warnings(name, type, mask, value);
|
||||||
|
- break;
|
||||||
|
- case XFS_PROJ_QUOTA:
|
||||||
|
- set_project_warnings(name, type, mask, value);
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
+ id = id_from_string(name, type);
|
||||||
|
+ if (id >= 0)
|
||||||
|
+ set_warnings(id, type, mask, fs_path->fs_name, value);
|
||||||
|
+ else
|
||||||
|
+ exitcode = -1;
|
||||||
|
+
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
|||||||
|
From cae4fd291266c32441c6a7fcca49929fe11c391c Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:35:44 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: check for AG btree records that would wrap around
|
||||||
|
|
||||||
|
For AG btree types, make sure that each record's length is not so huge
|
||||||
|
that integer wraparound would happen.
|
||||||
|
|
||||||
|
Found via xfs/358 fuzzing recs[1].blockcount = ones.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
repair/scan.c | 9 ++++++---
|
||||||
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/repair/scan.c b/repair/scan.c
|
||||||
|
index 5c8d8b23..1ddb5763 100644
|
||||||
|
--- a/repair/scan.c
|
||||||
|
+++ b/repair/scan.c
|
||||||
|
@@ -684,7 +684,8 @@ _("%s freespace btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if (len == 0 || !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ if (len == 0 || end <= b ||
|
||||||
|
+ !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -1066,7 +1067,8 @@ _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if (len == 0 || !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ if (len == 0 || end <= b ||
|
||||||
|
+ !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -1353,7 +1355,8 @@ _("leftover CoW extent has invalid startblock in record %u of %s btree block %u/
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- if (len == 0 || !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ if (len == 0 || end <= agb ||
|
||||||
|
+ !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
@ -0,0 +1,124 @@
|
|||||||
|
From 320cc3b263542e692c4978fb327efa591892ab37 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:35:45 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: complain about bad interior btree pointers
|
||||||
|
|
||||||
|
Actually complain about garbage btree node pointers, don't just silently
|
||||||
|
ignore them.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
libxfs/libxfs_api_defs.h | 1 +
|
||||||
|
repair/scan.c | 55 +++++++++++++++++++++++++++++-----------
|
||||||
|
2 files changed, 41 insertions(+), 15 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/libxfs/libxfs_api_defs.h
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/libxfs/libxfs_api_defs.h
|
||||||
|
+++ xfsprogs-5.0.0/libxfs/libxfs_api_defs.h
|
||||||
|
@@ -118,6 +118,7 @@
|
||||||
|
#define xfs_symlink_blocks libxfs_symlink_blocks
|
||||||
|
#define xfs_symlink_hdr_ok libxfs_symlink_hdr_ok
|
||||||
|
|
||||||
|
+#define xfs_verify_agbno libxfs_verify_agbno
|
||||||
|
#define xfs_verify_cksum libxfs_verify_cksum
|
||||||
|
#define xfs_dinode_verify libxfs_dinode_verify
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/repair/scan.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/scan.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/scan.c
|
||||||
|
@@ -743,6 +743,14 @@ _("%s freespace btree block claimed (sta
|
||||||
|
for (i = 0; i < numrecs; i++) {
|
||||||
|
xfs_agblock_t agbno = be32_to_cpu(pp[i]);
|
||||||
|
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agbno)) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("bad btree pointer (%u) in %sbt block %u/%u\n"),
|
||||||
|
+ agbno, name, agno, bno);
|
||||||
|
+ suspect++;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* XXX - put sibling detection right here.
|
||||||
|
* we know our sibling chain is good. So as we go,
|
||||||
|
@@ -752,10 +760,8 @@ _("%s freespace btree block claimed (sta
|
||||||
|
* pointer mismatch, try and extract as much data
|
||||||
|
* as possible.
|
||||||
|
*/
|
||||||
|
- if (agbno != 0 && verify_agbno(mp, agno, agbno)) {
|
||||||
|
- scan_sbtree(agbno, level, agno, suspect, scan_allocbt,
|
||||||
|
- 0, magic, priv, ops);
|
||||||
|
- }
|
||||||
|
+ scan_sbtree(agbno, level, agno, suspect, scan_allocbt, 0,
|
||||||
|
+ magic, priv, ops);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1196,10 +1202,16 @@ advance:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (agbno != 0 && verify_agbno(mp, agno, agbno)) {
|
||||||
|
- scan_sbtree(agbno, level, agno, suspect, scan_rmapbt, 0,
|
||||||
|
- magic, priv, ops);
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agbno)) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("bad btree pointer (%u) in %sbt block %u/%u\n"),
|
||||||
|
+ agbno, name, agno, bno);
|
||||||
|
+ suspect++;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ scan_sbtree(agbno, level, agno, suspect, scan_rmapbt, 0, magic,
|
||||||
|
+ priv, ops);
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
@@ -1416,10 +1428,16 @@ _("extent (%u/%u) len %u claimed, state
|
||||||
|
for (i = 0; i < numrecs; i++) {
|
||||||
|
xfs_agblock_t agbno = be32_to_cpu(pp[i]);
|
||||||
|
|
||||||
|
- if (agbno != 0 && verify_agbno(mp, agno, agbno)) {
|
||||||
|
- scan_sbtree(agbno, level, agno, suspect, scan_refcbt, 0,
|
||||||
|
- magic, priv, ops);
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agbno)) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("bad btree pointer (%u) in %sbt block %u/%u\n"),
|
||||||
|
+ agbno, name, agno, bno);
|
||||||
|
+ suspect++;
|
||||||
|
+ return;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ scan_sbtree(agbno, level, agno, suspect, scan_refcbt, 0, magic,
|
||||||
|
+ priv, ops);
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
if (suspect)
|
||||||
|
@@ -2083,11 +2101,18 @@ _("inode btree block claimed (state %d),
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numrecs; i++) {
|
||||||
|
- if (be32_to_cpu(pp[i]) != 0 && verify_agbno(mp, agno,
|
||||||
|
- be32_to_cpu(pp[i])))
|
||||||
|
- scan_sbtree(be32_to_cpu(pp[i]), level, agno,
|
||||||
|
- suspect, scan_inobt, 0, magic, priv,
|
||||||
|
- ops);
|
||||||
|
+ xfs_agblock_t agbno = be32_to_cpu(pp[i]);
|
||||||
|
+
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agbno)) {
|
||||||
|
+ do_warn(
|
||||||
|
+ _("bad btree pointer (%u) in %sbt block %u/%u\n"),
|
||||||
|
+ agbno, name, agno, bno);
|
||||||
|
+ suspect++;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ scan_sbtree(be32_to_cpu(pp[i]), level, agno, suspect,
|
||||||
|
+ scan_inobt, 0, magic, priv, ops);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,209 @@
|
|||||||
|
From dcd6c2e1490ba5c59c14ca8ea843ca36048888b8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:35:45 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: convert to libxfs_verify_agbno
|
||||||
|
|
||||||
|
Convert the homegrown verify_agbno callers to use the libxfs function,
|
||||||
|
as needed. In some places we drop the "bno != 0" checks because those
|
||||||
|
conditionals are checking btree roots; btree roots should never be
|
||||||
|
zero if the corresponding feature bit is set; and repair skips the if
|
||||||
|
clause entirely if the feature bit is disabled.
|
||||||
|
|
||||||
|
In effect, this strengthens repair to validate that AG btree pointers
|
||||||
|
neither point to the AG headers nor past the end of the AG.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
libxfs/libxfs_api_defs.h | 1 +
|
||||||
|
repair/dinode.c | 11 -----------
|
||||||
|
repair/dinode.h | 5 -----
|
||||||
|
repair/scan.c | 36 +++++++++++++++++++++++-------------
|
||||||
|
4 files changed, 24 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/libxfs/libxfs_api_defs.h
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/libxfs/libxfs_api_defs.h
|
||||||
|
+++ xfsprogs-5.0.0/libxfs/libxfs_api_defs.h
|
||||||
|
@@ -121,6 +121,7 @@
|
||||||
|
#define xfs_verify_agbno libxfs_verify_agbno
|
||||||
|
#define xfs_verify_cksum libxfs_verify_cksum
|
||||||
|
#define xfs_dinode_verify libxfs_dinode_verify
|
||||||
|
+#define xfs_ag_block_count libxfs_ag_block_count
|
||||||
|
|
||||||
|
#define xfs_alloc_ag_max_usable libxfs_alloc_ag_max_usable
|
||||||
|
#define xfs_allocbt_maxrecs libxfs_allocbt_maxrecs
|
||||||
|
Index: xfsprogs-5.0.0/repair/dinode.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/dinode.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/dinode.c
|
||||||
|
@@ -284,17 +284,6 @@ verify_dfsbno_range(xfs_mount_t *mp,
|
||||||
|
return (XR_DFSBNORANGE_VALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
-int
|
||||||
|
-verify_agbno(xfs_mount_t *mp,
|
||||||
|
- xfs_agnumber_t agno,
|
||||||
|
- xfs_agblock_t agbno)
|
||||||
|
-{
|
||||||
|
- xfs_sb_t *sbp = &mp->m_sb;;
|
||||||
|
-
|
||||||
|
- /* range check ag #, ag block. range-checking offset is pointless */
|
||||||
|
- return verify_ag_bno(sbp, agno, agbno) == 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int
|
||||||
|
process_rt_rec(
|
||||||
|
xfs_mount_t *mp,
|
||||||
|
Index: xfsprogs-5.0.0/repair/dinode.h
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/dinode.h
|
||||||
|
+++ xfsprogs-5.0.0/repair/dinode.h
|
||||||
|
@@ -10,11 +10,6 @@ struct blkmap;
|
||||||
|
struct prefetch_args;
|
||||||
|
|
||||||
|
int
|
||||||
|
-verify_agbno(xfs_mount_t *mp,
|
||||||
|
- xfs_agnumber_t agno,
|
||||||
|
- xfs_agblock_t agbno);
|
||||||
|
-
|
||||||
|
-int
|
||||||
|
verify_dfsbno(xfs_mount_t *mp,
|
||||||
|
xfs_fsblock_t fsbno);
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/repair/scan.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/scan.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/scan.c
|
||||||
|
@@ -642,14 +642,14 @@ _("%s freespace btree block claimed (sta
|
||||||
|
len = be32_to_cpu(rp[i].ar_blockcount);
|
||||||
|
end = b + len;
|
||||||
|
|
||||||
|
- if (b == 0 || !verify_agbno(mp, agno, b)) {
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, b)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid start block %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (len == 0 || end <= b ||
|
||||||
|
- !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ !libxfs_verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -914,6 +914,16 @@ rmap_in_order(
|
||||||
|
return offset > lastoffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static inline bool
|
||||||
|
+verify_rmap_agbno(
|
||||||
|
+ struct xfs_mount *mp,
|
||||||
|
+ xfs_agnumber_t agno,
|
||||||
|
+ xfs_agblock_t agbno)
|
||||||
|
+{
|
||||||
|
+ return agbno < libxfs_ag_block_count(mp, agno);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
static void
|
||||||
|
scan_rmapbt(
|
||||||
|
struct xfs_btree_block *block,
|
||||||
|
@@ -1031,14 +1041,14 @@ _("%s rmap btree block claimed (state %d
|
||||||
|
end = key.rm_startblock + key.rm_blockcount;
|
||||||
|
|
||||||
|
/* Make sure agbno & len make sense. */
|
||||||
|
- if (!verify_agbno(mp, agno, b)) {
|
||||||
|
+ if (!verify_rmap_agbno(mp, agno, b)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid start block %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (len == 0 || end <= b ||
|
||||||
|
- !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ !verify_rmap_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -1325,14 +1335,14 @@ _("leftover CoW extent has invalid start
|
||||||
|
}
|
||||||
|
end = agb + len;
|
||||||
|
|
||||||
|
- if (!verify_agbno(mp, agno, agb)) {
|
||||||
|
+ if (!libxfs_verify_agbno(mp, agno, agb)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid start block %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
b, i, name, agno, bno);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (len == 0 || end <= agb ||
|
||||||
|
- !verify_agbno(mp, agno, end - 1)) {
|
||||||
|
+ !libxfs_verify_agbno(mp, agno, end - 1)) {
|
||||||
|
do_warn(
|
||||||
|
_("invalid length %u in record %u of %s btree block %u/%u\n"),
|
||||||
|
len, i, name, agno, bno);
|
||||||
|
@@ -2145,7 +2155,7 @@ scan_agfl(
|
||||||
|
{
|
||||||
|
struct agfl_state *as = priv;
|
||||||
|
|
||||||
|
- if (verify_agbno(mp, as->agno, bno))
|
||||||
|
+ if (libxfs_verify_agbno(mp, as->agno, bno))
|
||||||
|
set_bmap(as->agno, bno, XR_E_FREE);
|
||||||
|
else
|
||||||
|
do_warn(_("bad agbno %u in agfl, agno %d\n"),
|
||||||
|
@@ -2217,7 +2227,7 @@ validate_agf(
|
||||||
|
uint32_t magic;
|
||||||
|
|
||||||
|
bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTB_CRC_MAGIC
|
||||||
|
: XFS_ABTB_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]),
|
||||||
|
@@ -2229,7 +2239,7 @@ validate_agf(
|
||||||
|
}
|
||||||
|
|
||||||
|
bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_ABTC_CRC_MAGIC
|
||||||
|
: XFS_ABTC_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]),
|
||||||
|
@@ -2249,7 +2259,7 @@ validate_agf(
|
||||||
|
priv.last_rec.rm_owner = XFS_RMAP_OWN_UNKNOWN;
|
||||||
|
priv.nr_blocks = 0;
|
||||||
|
bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
scan_sbtree(bno,
|
||||||
|
be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]),
|
||||||
|
agno, 0, scan_rmapbt, 1, XFS_RMAP_CRC_MAGIC,
|
||||||
|
@@ -2267,7 +2277,7 @@ validate_agf(
|
||||||
|
|
||||||
|
if (xfs_sb_version_hasreflink(&mp->m_sb)) {
|
||||||
|
bno = be32_to_cpu(agf->agf_refcount_root);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
struct refc_priv priv;
|
||||||
|
|
||||||
|
memset(&priv, 0, sizeof(priv));
|
||||||
|
@@ -2315,7 +2325,7 @@ validate_agi(
|
||||||
|
uint32_t magic;
|
||||||
|
|
||||||
|
bno = be32_to_cpu(agi->agi_root);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ? XFS_IBT_CRC_MAGIC
|
||||||
|
: XFS_IBT_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agi->agi_level),
|
||||||
|
@@ -2328,7 +2338,7 @@ validate_agi(
|
||||||
|
|
||||||
|
if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
|
||||||
|
bno = be32_to_cpu(agi->agi_free_root);
|
||||||
|
- if (bno != 0 && verify_agbno(mp, agno, bno)) {
|
||||||
|
+ if (libxfs_verify_agbno(mp, agno, bno)) {
|
||||||
|
magic = xfs_sb_version_hascrc(&mp->m_sb) ?
|
||||||
|
XFS_FIBT_CRC_MAGIC : XFS_FIBT_MAGIC;
|
||||||
|
scan_sbtree(bno, be32_to_cpu(agi->agi_free_level),
|
@ -0,0 +1,290 @@
|
|||||||
|
From 6df28d12d7760701c9d11e659e374665c5ffd0b9 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:32:36 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: fix rebuilding btree block less than minrecs
|
||||||
|
|
||||||
|
In production, we found that sometimes xfs_repair phase 5
|
||||||
|
rebuilds freespace node block with pointers less than minrecs
|
||||||
|
and if we trigger xfs_repair again it would report such
|
||||||
|
the following message:
|
||||||
|
|
||||||
|
bad btree nrecs (39, min=40, max=80) in btbno block 0/7882
|
||||||
|
|
||||||
|
The background is that xfs_repair starts to rebuild AGFL
|
||||||
|
after the freespace btree is settled in phase 5 so we may
|
||||||
|
need to leave necessary room in advance for each btree
|
||||||
|
leaves in order to avoid freespace btree split and then
|
||||||
|
result in AGFL rebuild fails. The old mathematics uses
|
||||||
|
ceil(num_extents / maxrecs) to decide the number of node
|
||||||
|
blocks. That would be fine without leaving extra space
|
||||||
|
since minrecs = maxrecs / 2 but if some slack was decreased
|
||||||
|
from maxrecs, the result would be larger than what is
|
||||||
|
expected and cause num_recs_pb less than minrecs, i.e:
|
||||||
|
|
||||||
|
num_extents = 79, adj_maxrecs = 80 - 2 (slack) = 78
|
||||||
|
|
||||||
|
so we'd get
|
||||||
|
|
||||||
|
num_blocks = ceil(79 / 78) = 2,
|
||||||
|
num_recs_pb = 79 / 2 = 39, which is less than
|
||||||
|
minrecs = 80 / 2 = 40
|
||||||
|
|
||||||
|
OTOH, btree bulk loading code behaves in a different way.
|
||||||
|
As in xfs_btree_bload_level_geometry it wrote
|
||||||
|
|
||||||
|
num_blocks = floor(num_extents / maxrecs)
|
||||||
|
|
||||||
|
which will never go below minrecs. And when it goes above
|
||||||
|
maxrecs, just increment num_blocks and recalculate so we
|
||||||
|
can get the reasonable results.
|
||||||
|
|
||||||
|
Later, btree bulk loader will replace the current repair code.
|
||||||
|
But we may still want to look for a backportable solution
|
||||||
|
for stable versions. Hence, keep the same logic to avoid
|
||||||
|
the freespace as well as rmap btree minrecs underflow for now.
|
||||||
|
|
||||||
|
Cc: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Cc: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Cc: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
Fixes: 9851fd79bfb1 ("repair: AGFL rebuild fails if btree split required")
|
||||||
|
Signed-off-by: Gao Xiang <hsiangkao@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
repair/phase5.c | 152 ++++++++++++++++++++----------------------------
|
||||||
|
1 file changed, 63 insertions(+), 89 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/repair/phase5.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/phase5.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/phase5.c
|
||||||
|
@@ -346,11 +346,32 @@ finish_cursor(bt_status_t *curs)
|
||||||
|
* failure at runtime. Hence leave a couple of records slack space in
|
||||||
|
* each block to allow immediate modification of the tree without
|
||||||
|
* requiring splits to be done.
|
||||||
|
- *
|
||||||
|
- * XXX(hch): any reason we don't just look at mp->m_alloc_mxr?
|
||||||
|
*/
|
||||||
|
-#define XR_ALLOC_BLOCK_MAXRECS(mp, level) \
|
||||||
|
- (libxfs_allocbt_maxrecs((mp), (mp)->m_sb.sb_blocksize, (level) == 0) - 2)
|
||||||
|
+static void
|
||||||
|
+compute_level_geometry(
|
||||||
|
+ struct xfs_mount *mp,
|
||||||
|
+ struct bt_stat_level *lptr,
|
||||||
|
+ uint64_t nr_this_level,
|
||||||
|
+ int slack,
|
||||||
|
+ bool leaf)
|
||||||
|
+{
|
||||||
|
+ unsigned int maxrecs = mp->m_alloc_mxr[!leaf];
|
||||||
|
+ unsigned int desired_npb;
|
||||||
|
+
|
||||||
|
+ desired_npb = max(mp->m_alloc_mnr[!leaf], maxrecs - slack);
|
||||||
|
+ lptr->num_recs_tot = nr_this_level;
|
||||||
|
+ lptr->num_blocks = max(1ULL, nr_this_level / desired_npb);
|
||||||
|
+
|
||||||
|
+ lptr->num_recs_pb = nr_this_level / lptr->num_blocks;
|
||||||
|
+ lptr->modulo = nr_this_level % lptr->num_blocks;
|
||||||
|
+ if (lptr->num_recs_pb > maxrecs ||
|
||||||
|
+ (lptr->num_recs_pb == maxrecs && lptr->modulo)) {
|
||||||
|
+ lptr->num_blocks++;
|
||||||
|
+
|
||||||
|
+ lptr->num_recs_pb = nr_this_level / lptr->num_blocks;
|
||||||
|
+ lptr->modulo = nr_this_level % lptr->num_blocks;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this calculates a freespace cursor for an ag.
|
||||||
|
@@ -368,6 +389,7 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
int i;
|
||||||
|
int extents_used;
|
||||||
|
int extra_blocks;
|
||||||
|
+ uint64_t old_blocks;
|
||||||
|
bt_stat_level_t *lptr;
|
||||||
|
bt_stat_level_t *p_lptr;
|
||||||
|
extent_tree_node_t *ext_ptr;
|
||||||
|
@@ -386,10 +408,7 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
* of the tree and set up the cursor for the leaf level
|
||||||
|
* (note that the same code is duplicated further down)
|
||||||
|
*/
|
||||||
|
- lptr->num_blocks = howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0));
|
||||||
|
- lptr->num_recs_pb = num_extents / lptr->num_blocks;
|
||||||
|
- lptr->modulo = num_extents % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = num_extents;
|
||||||
|
+ compute_level_geometry(mp, lptr, num_extents, 2, true);
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
#ifdef XR_BLD_FREE_TRACE
|
||||||
|
@@ -403,30 +422,23 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
* if we need more levels, set them up. # of records
|
||||||
|
* per level is the # of blocks in the level below it
|
||||||
|
*/
|
||||||
|
- if (lptr->num_blocks > 1) {
|
||||||
|
- for (; btree_curs->level[level - 1].num_blocks > 1
|
||||||
|
- && level < XFS_BTREE_MAXLEVELS;
|
||||||
|
- level++) {
|
||||||
|
- lptr = &btree_curs->level[level];
|
||||||
|
- p_lptr = &btree_curs->level[level - 1];
|
||||||
|
- lptr->num_blocks = howmany(p_lptr->num_blocks,
|
||||||
|
- XR_ALLOC_BLOCK_MAXRECS(mp, level));
|
||||||
|
- lptr->modulo = p_lptr->num_blocks
|
||||||
|
- % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_pb = p_lptr->num_blocks
|
||||||
|
- / lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = p_lptr->num_blocks;
|
||||||
|
+ while (lptr->num_blocks > 1) {
|
||||||
|
+ p_lptr = lptr;
|
||||||
|
+ lptr = &btree_curs->level[level];
|
||||||
|
+
|
||||||
|
+ compute_level_geometry(mp, lptr,
|
||||||
|
+ p_lptr->num_blocks, 0, false);
|
||||||
|
#ifdef XR_BLD_FREE_TRACE
|
||||||
|
- fprintf(stderr, "%s %d %d %d %d %d\n", __func__,
|
||||||
|
- level,
|
||||||
|
- lptr->num_blocks,
|
||||||
|
- lptr->num_recs_pb,
|
||||||
|
- lptr->modulo,
|
||||||
|
- lptr->num_recs_tot);
|
||||||
|
+ fprintf(stderr, "%s %d %d %d %d %d\n", __func__,
|
||||||
|
+ level,
|
||||||
|
+ lptr->num_blocks,
|
||||||
|
+ lptr->num_recs_pb,
|
||||||
|
+ lptr->modulo,
|
||||||
|
+ lptr->num_recs_tot);
|
||||||
|
#endif
|
||||||
|
- }
|
||||||
|
+ level++;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
+ ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
ASSERT(lptr->num_blocks == 1);
|
||||||
|
btree_curs->num_levels = level;
|
||||||
|
|
||||||
|
@@ -494,8 +506,11 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
* see if the number of leaf blocks will change as a result
|
||||||
|
* of the number of extents changing
|
||||||
|
*/
|
||||||
|
- if (howmany(num_extents, XR_ALLOC_BLOCK_MAXRECS(mp, 0))
|
||||||
|
- != btree_curs->level[0].num_blocks) {
|
||||||
|
+ old_blocks = btree_curs->level[0].num_blocks;
|
||||||
|
+ compute_level_geometry(mp, &btree_curs->level[0], num_extents, 2, true);
|
||||||
|
+ extra_blocks = 0;
|
||||||
|
+
|
||||||
|
+ if (old_blocks != btree_curs->level[0].num_blocks) {
|
||||||
|
/*
|
||||||
|
* yes -- recalculate the cursor. If the number of
|
||||||
|
* excess (overallocated) blocks is < xfs_agfl_size/2, we're ok.
|
||||||
|
@@ -551,31 +566,19 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
}
|
||||||
|
|
||||||
|
lptr = &btree_curs->level[0];
|
||||||
|
- lptr->num_blocks = howmany(num_extents,
|
||||||
|
- XR_ALLOC_BLOCK_MAXRECS(mp, 0));
|
||||||
|
- lptr->num_recs_pb = num_extents / lptr->num_blocks;
|
||||||
|
- lptr->modulo = num_extents % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = num_extents;
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if we need more levels, set them up
|
||||||
|
*/
|
||||||
|
- if (lptr->num_blocks > 1) {
|
||||||
|
- for (level = 1; btree_curs->level[level-1].num_blocks
|
||||||
|
- > 1 && level < XFS_BTREE_MAXLEVELS;
|
||||||
|
- level++) {
|
||||||
|
- lptr = &btree_curs->level[level];
|
||||||
|
- p_lptr = &btree_curs->level[level-1];
|
||||||
|
- lptr->num_blocks = howmany(p_lptr->num_blocks,
|
||||||
|
- XR_ALLOC_BLOCK_MAXRECS(mp, level));
|
||||||
|
- lptr->modulo = p_lptr->num_blocks
|
||||||
|
- % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_pb = p_lptr->num_blocks
|
||||||
|
- / lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = p_lptr->num_blocks;
|
||||||
|
- }
|
||||||
|
+ while (lptr->num_blocks > 1) {
|
||||||
|
+ p_lptr = lptr;
|
||||||
|
+ lptr = &btree_curs->level[level++];
|
||||||
|
+
|
||||||
|
+ compute_level_geometry(mp, lptr,
|
||||||
|
+ p_lptr->num_blocks, 0, false);
|
||||||
|
}
|
||||||
|
+ ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
ASSERT(lptr->num_blocks == 1);
|
||||||
|
btree_curs->num_levels = level;
|
||||||
|
|
||||||
|
@@ -589,22 +592,6 @@ calculate_freespace_cursor(xfs_mount_t *
|
||||||
|
|
||||||
|
ASSERT(blocks_allocated_total >= blocks_needed);
|
||||||
|
extra_blocks = blocks_allocated_total - blocks_needed;
|
||||||
|
- } else {
|
||||||
|
- if (extents_used > 0) {
|
||||||
|
- /*
|
||||||
|
- * reset the leaf level geometry to account
|
||||||
|
- * for consumed extents. we can leave the
|
||||||
|
- * rest of the cursor alone since the number
|
||||||
|
- * of leaf blocks hasn't changed.
|
||||||
|
- */
|
||||||
|
- lptr = &btree_curs->level[0];
|
||||||
|
-
|
||||||
|
- lptr->num_recs_pb = num_extents / lptr->num_blocks;
|
||||||
|
- lptr->modulo = num_extents % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = num_extents;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- extra_blocks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
btree_curs->num_tot_blocks = blocks_allocated_pt;
|
||||||
|
@@ -1335,7 +1322,6 @@ init_rmapbt_cursor(
|
||||||
|
struct bt_stat_level *lptr;
|
||||||
|
struct bt_stat_level *p_lptr;
|
||||||
|
xfs_extlen_t blocks_allocated;
|
||||||
|
- int maxrecs;
|
||||||
|
|
||||||
|
if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) {
|
||||||
|
memset(btree_curs, 0, sizeof(struct bt_status));
|
||||||
|
@@ -1371,32 +1357,20 @@ init_rmapbt_cursor(
|
||||||
|
* Leave enough slack in the rmapbt that we can insert the
|
||||||
|
* metadata AG entries without too many splits.
|
||||||
|
*/
|
||||||
|
- maxrecs = mp->m_rmap_mxr[0];
|
||||||
|
- if (num_recs > maxrecs)
|
||||||
|
- maxrecs -= 10;
|
||||||
|
- blocks_allocated = lptr->num_blocks = howmany(num_recs, maxrecs);
|
||||||
|
-
|
||||||
|
- lptr->modulo = num_recs % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_pb = num_recs / lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = num_recs;
|
||||||
|
+ compute_level_geometry(mp, lptr, num_recs,
|
||||||
|
+ num_recs > mp->m_rmap_mxr[0] ? 10 : 0, true);
|
||||||
|
+ blocks_allocated = lptr->num_blocks;
|
||||||
|
level = 1;
|
||||||
|
|
||||||
|
- if (lptr->num_blocks > 1) {
|
||||||
|
- for (; btree_curs->level[level-1].num_blocks > 1
|
||||||
|
- && level < XFS_BTREE_MAXLEVELS;
|
||||||
|
- level++) {
|
||||||
|
- lptr = &btree_curs->level[level];
|
||||||
|
- p_lptr = &btree_curs->level[level - 1];
|
||||||
|
- lptr->num_blocks = howmany(p_lptr->num_blocks,
|
||||||
|
- mp->m_rmap_mxr[1]);
|
||||||
|
- lptr->modulo = p_lptr->num_blocks % lptr->num_blocks;
|
||||||
|
- lptr->num_recs_pb = p_lptr->num_blocks
|
||||||
|
- / lptr->num_blocks;
|
||||||
|
- lptr->num_recs_tot = p_lptr->num_blocks;
|
||||||
|
-
|
||||||
|
- blocks_allocated += lptr->num_blocks;
|
||||||
|
- }
|
||||||
|
+ while (lptr->num_blocks > 1) {
|
||||||
|
+ p_lptr = lptr;
|
||||||
|
+ lptr = &btree_curs->level[level++];
|
||||||
|
+
|
||||||
|
+ compute_level_geometry(mp, lptr,
|
||||||
|
+ p_lptr->num_blocks, 0, false);
|
||||||
|
+ blocks_allocated += lptr->num_blocks;
|
||||||
|
}
|
||||||
|
+ ASSERT(level < XFS_BTREE_MAXLEVELS);
|
||||||
|
ASSERT(lptr->num_blocks == 1);
|
||||||
|
btree_curs->num_levels = level;
|
||||||
|
|
@ -0,0 +1,88 @@
|
|||||||
|
From 08280b4b6efd317c673c6718a27d77e702d0480d Mon Sep 17 00:00:00 2001
|
||||||
|
From: "Darrick J. Wong" <darrick.wong@oracle.com>
|
||||||
|
Date: Fri, 10 Jul 2020 15:35:45 -0400
|
||||||
|
Subject: [PATCH] xfs_repair: tag inobt vs finobt errors properly
|
||||||
|
|
||||||
|
Amend the generic inode btree block scanner function to tag correctly
|
||||||
|
which tree it's complaining about. Previously, dubious finobt headers
|
||||||
|
would be attributed to the "inode btree", which is at best ambiguous
|
||||||
|
and misleading at worst.
|
||||||
|
|
||||||
|
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
repair/scan.c | 36 ++++++++++++++++++++++++++----------
|
||||||
|
1 file changed, 26 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/repair/scan.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/repair/scan.c
|
||||||
|
+++ xfsprogs-5.0.0/repair/scan.c
|
||||||
|
@@ -1934,6 +1934,7 @@ scan_inobt(
|
||||||
|
const struct xfs_buf_ops *ops)
|
||||||
|
{
|
||||||
|
struct aghdr_cnts *agcnts = priv;
|
||||||
|
+ char *name;
|
||||||
|
int i;
|
||||||
|
int numrecs;
|
||||||
|
int state;
|
||||||
|
@@ -1944,17 +1945,32 @@ scan_inobt(
|
||||||
|
|
||||||
|
hdr_errors = 0;
|
||||||
|
|
||||||
|
+ switch (magic) {
|
||||||
|
+ case XFS_FIBT_MAGIC:
|
||||||
|
+ case XFS_FIBT_CRC_MAGIC:
|
||||||
|
+ name = "fino";
|
||||||
|
+ break;
|
||||||
|
+ case XFS_IBT_MAGIC:
|
||||||
|
+ case XFS_IBT_CRC_MAGIC:
|
||||||
|
+ name = "ino";
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ name = "(unknown)";
|
||||||
|
+ assert(0);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (be32_to_cpu(block->bb_magic) != magic) {
|
||||||
|
- do_warn(_("bad magic # %#x in inobt block %d/%d\n"),
|
||||||
|
- be32_to_cpu(block->bb_magic), agno, bno);
|
||||||
|
+ do_warn(_("bad magic # %#x in %sbt block %d/%d\n"),
|
||||||
|
+ be32_to_cpu(block->bb_magic), name, agno, bno);
|
||||||
|
hdr_errors++;
|
||||||
|
bad_ino_btree = 1;
|
||||||
|
if (suspect)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (be16_to_cpu(block->bb_level) != level) {
|
||||||
|
- do_warn(_("expected level %d got %d in inobt block %d/%d\n"),
|
||||||
|
- level, be16_to_cpu(block->bb_level), agno, bno);
|
||||||
|
+ do_warn(_("expected level %d got %d in %sbt block %d/%d\n"),
|
||||||
|
+ level, be16_to_cpu(block->bb_level), name, agno, bno);
|
||||||
|
hdr_errors++;
|
||||||
|
bad_ino_btree = 1;
|
||||||
|
if (suspect)
|
||||||
|
@@ -1976,8 +1992,8 @@ scan_inobt(
|
||||||
|
default:
|
||||||
|
set_bmap(agno, bno, XR_E_MULT);
|
||||||
|
do_warn(
|
||||||
|
-_("inode btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
|
||||||
|
- state, agno, bno, suspect);
|
||||||
|
+_("%sbt btree block claimed (state %d), agno %d, bno %d, suspect %d\n"),
|
||||||
|
+ name, state, agno, bno, suspect);
|
||||||
|
}
|
||||||
|
|
||||||
|
numrecs = be16_to_cpu(block->bb_numrecs);
|
||||||
|
@@ -1999,8 +2015,8 @@ _("inode btree block claimed (state %d),
|
||||||
|
|
||||||
|
if (hdr_errors) {
|
||||||
|
bad_ino_btree = 1;
|
||||||
|
- do_warn(_("dubious inode btree block header %d/%d\n"),
|
||||||
|
- agno, bno);
|
||||||
|
+ do_warn(_("dubious %sbt btree block header %d/%d\n"),
|
||||||
|
+ name, agno, bno);
|
||||||
|
suspect++;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
|||||||
|
From 7b4a7b3f6bce91be45b54fc68e169cb756dc8c74 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Date: Mon, 24 Aug 2020 12:47:47 -0400
|
||||||
|
Subject: [PATCH] xfs_db: short circuit type_f if type is unchanged
|
||||||
|
|
||||||
|
There's no reason to go through the type change code if the
|
||||||
|
type has not been changed.
|
||||||
|
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
|
||||||
|
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
db/type.c | 2 ++
|
||||||
|
1 file changed, 2 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/db/type.c b/db/type.c
|
||||||
|
index 3cb1e868..572ac6d6 100644
|
||||||
|
--- a/db/type.c
|
||||||
|
+++ b/db/type.c
|
||||||
|
@@ -216,6 +216,8 @@ type_f(
|
||||||
|
tt = findtyp(argv[1]);
|
||||||
|
if (tt == NULL) {
|
||||||
|
dbprintf(_("no such type %s\n"), argv[1]);
|
||||||
|
+ } else if (iocur_top->typ == tt) {
|
||||||
|
+ return 0;
|
||||||
|
} else {
|
||||||
|
if (iocur_top->typ == NULL)
|
||||||
|
dbprintf(_("no current object\n"));
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
@ -0,0 +1,76 @@
|
|||||||
|
From 97a4059660b27a9b0e3d8cdde5dbef8712685865 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pavel Reichl <preichl@redhat.com>
|
||||||
|
Date: Mon, 28 Sep 2020 17:31:18 -0400
|
||||||
|
Subject: [PATCH] mkfs.xfs: fix ASSERT on too-small device with stripe geometry
|
||||||
|
|
||||||
|
When a too-small device is created with stripe geometry, we hit an
|
||||||
|
assert in align_ag_geometry():
|
||||||
|
|
||||||
|
mkfs.xfs: xfs_mkfs.c:2834: align_ag_geometry: Assertion `cfg->agcount != 0' failed.
|
||||||
|
|
||||||
|
This is because align_ag_geometry() finds that the size of the last
|
||||||
|
(only) AG is too small, and attempts to trim it off. Obviously 0
|
||||||
|
AGs is invalid, and we hit the ASSERT.
|
||||||
|
|
||||||
|
Reported-by: Zdenek Kabelac <zkabelac@redhat.com>
|
||||||
|
Suggested-by: Dave Chinner <dchinner@redhat.com>
|
||||||
|
Signed-off-by: Pavel Reichl <preichl@redhat.com>
|
||||||
|
Reviewed-by: Christoph Hellwig <hch@lst.de>
|
||||||
|
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
|
||||||
|
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
|
||||||
|
---
|
||||||
|
include/xfs_multidisk.h | 14 +++++++-------
|
||||||
|
mkfs/xfs_mkfs.c | 6 +++---
|
||||||
|
2 files changed, 10 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
Index: xfsprogs-5.0.0/include/xfs_multidisk.h
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/include/xfs_multidisk.h
|
||||||
|
+++ xfsprogs-5.0.0/include/xfs_multidisk.h
|
||||||
|
@@ -14,7 +14,6 @@
|
||||||
|
#define XFS_DFL_BLOCKSIZE_LOG 12 /* 4096 byte blocks */
|
||||||
|
#define XFS_DINODE_DFL_LOG 8 /* 256 byte inodes */
|
||||||
|
#define XFS_DINODE_DFL_CRC_LOG 9 /* 512 byte inodes for CRCs */
|
||||||
|
-#define XFS_MIN_DATA_BLOCKS 100
|
||||||
|
#define XFS_MIN_INODE_PERBLOCK 2 /* min inodes per block */
|
||||||
|
#define XFS_DFL_IMAXIMUM_PCT 25 /* max % of space for inodes */
|
||||||
|
#define XFS_MIN_REC_DIRSIZE 12 /* 4096 byte dirblocks (V2) */
|
||||||
|
@@ -25,13 +24,14 @@
|
||||||
|
* accept w/o warnings
|
||||||
|
*/
|
||||||
|
|
||||||
|
-#define XFS_AG_BYTES(bblog) ((long long)BBSIZE << (bblog))
|
||||||
|
-#define XFS_AG_MIN_BYTES ((XFS_AG_BYTES(15))) /* 16 MB */
|
||||||
|
-#define XFS_AG_MAX_BYTES ((XFS_AG_BYTES(31))) /* 1 TB */
|
||||||
|
-#define XFS_AG_MIN_BLOCKS(blog) (XFS_AG_MIN_BYTES >> (blog))
|
||||||
|
-#define XFS_AG_MAX_BLOCKS(blog) ((XFS_AG_MAX_BYTES - 1) >> (blog))
|
||||||
|
+#define XFS_AG_BYTES(bblog) ((long long)BBSIZE << (bblog))
|
||||||
|
+#define XFS_MIN_DATA_BLOCKS(cfg) (XFS_AG_MIN_BLOCKS((cfg)->blocklog))
|
||||||
|
+#define XFS_AG_MIN_BYTES ((XFS_AG_BYTES(15))) /* 16 MB */
|
||||||
|
+#define XFS_AG_MAX_BYTES ((XFS_AG_BYTES(31))) /* 1 TB */
|
||||||
|
+#define XFS_AG_MIN_BLOCKS(blog) (XFS_AG_MIN_BYTES >> (blog))
|
||||||
|
+#define XFS_AG_MAX_BLOCKS(blog) ((XFS_AG_MAX_BYTES - 1) >> (blog))
|
||||||
|
|
||||||
|
-#define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1))
|
||||||
|
+#define XFS_MAX_AGNUMBER ((xfs_agnumber_t)(NULLAGNUMBER - 1))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These values define what we consider a "multi-disk" filesystem. That is, a
|
||||||
|
Index: xfsprogs-5.0.0/mkfs/xfs_mkfs.c
|
||||||
|
===================================================================
|
||||||
|
--- xfsprogs-5.0.0.orig/mkfs/xfs_mkfs.c
|
||||||
|
+++ xfsprogs-5.0.0/mkfs/xfs_mkfs.c
|
||||||
|
@@ -2581,10 +2581,10 @@ _("size %s specified for data subvolume
|
||||||
|
cfg->dblocks = DTOBT(xi->dsize, cfg->blocklog);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (cfg->dblocks < XFS_MIN_DATA_BLOCKS) {
|
||||||
|
+ if (cfg->dblocks < XFS_MIN_DATA_BLOCKS(cfg)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
-_("size %lld of data subvolume is too small, minimum %d blocks\n"),
|
||||||
|
- (long long)cfg->dblocks, XFS_MIN_DATA_BLOCKS);
|
||||||
|
+_("size %lld of data subvolume is too small, minimum %lld blocks\n"),
|
||||||
|
+ (long long)cfg->dblocks, XFS_MIN_DATA_BLOCKS(cfg));
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
Summary: Utilities for managing the XFS filesystem
|
Summary: Utilities for managing the XFS filesystem
|
||||||
Name: xfsprogs
|
Name: xfsprogs
|
||||||
Version: 5.0.0
|
Version: 5.0.0
|
||||||
Release: 4%{?dist}
|
Release: 8%{?dist}
|
||||||
License: GPL+ and LGPLv2+
|
License: GPL+ and LGPLv2+
|
||||||
Group: System Environment/Base
|
Group: System Environment/Base
|
||||||
URL: https://xfs.wiki.kernel.org
|
URL: https://xfs.wiki.kernel.org
|
||||||
@ -25,6 +25,18 @@ Patch4: xfsprogs-5.3.0-xfs_growfs-allow-mounted-device-node-as-argument.patch
|
|||||||
Patch5: xfsprogs-5.5.0-libxfs-use-FALLOC_FL_ZERO_RANGE-in-libxfs_device_zer.patch
|
Patch5: xfsprogs-5.5.0-libxfs-use-FALLOC_FL_ZERO_RANGE-in-libxfs_device_zer.patch
|
||||||
Patch6: xfsprogs-5.4.0-mkfs-Break-block-discard-into-chunks-of-2-GB.patch
|
Patch6: xfsprogs-5.4.0-mkfs-Break-block-discard-into-chunks-of-2-GB.patch
|
||||||
Patch7: xfsprogs-5.4.0-mkfs-tidy-up-discard-notifications.patch
|
Patch7: xfsprogs-5.4.0-mkfs-tidy-up-discard-notifications.patch
|
||||||
|
Patch8: xfsprogs-5.7.0-xfs_quota-refactor-code-to-generate-id-from-name.patch
|
||||||
|
Patch9: xfsprogs-5.7.0-xfs_quota-allow-individual-timer-extension.patch
|
||||||
|
Patch10: xfsprogs-5.7.0-xfs_quota-fix-unsigned-int-id-comparisons.patch
|
||||||
|
Patch11: xfsprogs-5.7.0-xfs_repair-check-for-AG-btree-records-that-would-wra.patch
|
||||||
|
Patch12: xfsprogs-5.7.0-xfs_repair-tag-inobt-vs-finobt-errors-properly.patch
|
||||||
|
Patch13: xfsprogs-5.7.0-xfs_repair-complain-about-bad-interior-btree-pointer.patch
|
||||||
|
Patch14: xfsprogs-5.7.0-xfs_repair-convert-to-libxfs_verify_agbno.patch
|
||||||
|
Patch15: xfsprogs-5.9.0-mkfs.xfs-fix-ASSERT-on-too-small-device-with-stripe.patch
|
||||||
|
Patch16: xfsprogs-5.7.0-xfs_repair-fix-rebuilding-btree-block-less-than-minr.patch
|
||||||
|
Patch17: xfsprogs-5.10.0-xfs_quota-document-how-the-default-quota-is-stored.patch
|
||||||
|
Patch18: xfsprogs-5.8.0-xfs_db-short-circuit-type_f-if-type-is-unchanged.patch
|
||||||
|
Patch19: xfsprogs-5.10.0-xfs_repair-Use-proper-min-max-values-in-compute_level_geometry.patch
|
||||||
|
|
||||||
%description
|
%description
|
||||||
A set of commands to use the XFS filesystem, including mkfs.xfs.
|
A set of commands to use the XFS filesystem, including mkfs.xfs.
|
||||||
@ -63,6 +75,18 @@ also want to install xfsprogs.
|
|||||||
%patch5 -p1
|
%patch5 -p1
|
||||||
%patch6 -p1
|
%patch6 -p1
|
||||||
%patch7 -p1
|
%patch7 -p1
|
||||||
|
%patch8 -p1
|
||||||
|
%patch9 -p1
|
||||||
|
%patch10 -p1
|
||||||
|
%patch11 -p1
|
||||||
|
%patch12 -p1
|
||||||
|
%patch13 -p1
|
||||||
|
%patch14 -p1
|
||||||
|
%patch15 -p1
|
||||||
|
%patch16 -p1
|
||||||
|
%patch17 -p1
|
||||||
|
%patch18 -p1
|
||||||
|
%patch19 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
export tagname=CC
|
export tagname=CC
|
||||||
@ -122,6 +146,21 @@ rm -rf $RPM_BUILD_ROOT/%{_mandir}/man8/xfs_scrub*
|
|||||||
%{_libdir}/*.so
|
%{_libdir}/*.so
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Jan 07 2021 Bill O'Donnell <billodo@redhat.com> 5.0.0-8
|
||||||
|
- xfs_repair: Use proper min/max values in compute_level_geometry (#1910384)
|
||||||
|
|
||||||
|
* Mon Dec 14 2020 Bill O'Donnell <billodo@redhat.com> 5.0.0-7
|
||||||
|
- xfs_quota: document how the default quota is stored (#1850188)
|
||||||
|
- xfs_db: skip type change if type_f unchanged (#1867474)
|
||||||
|
|
||||||
|
* Wed Dec 09 2020 Bill O'Donnell <billodo@redhat.com> 5.0.0-6
|
||||||
|
- xfs_repair: improve AG btree ptr validation (libxfs_verify_agbno) (#1887288)
|
||||||
|
- mkfs.xfs: fix ASSERT on too-small device with stripe geometry (#1887401)
|
||||||
|
- xfs_repair: fix rebuilding btree block less than minrecs (#1759452)
|
||||||
|
|
||||||
|
* Wed Dec 02 2020 Bill O'Donnell <billodo@redhat.com> 5.0.0-5
|
||||||
|
- xfs_quota: allow individual timer extension (#1899204)
|
||||||
|
|
||||||
* Wed Jun 03 2020 Eric Sandeen <sandeen@redhat.com> 5.0.0-4
|
* Wed Jun 03 2020 Eric Sandeen <sandeen@redhat.com> 5.0.0-4
|
||||||
- mkfs.xfs: inform user about discard, and make interruptable (#1836414)
|
- mkfs.xfs: inform user about discard, and make interruptable (#1836414)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user