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
|
||||
Name: xfsprogs
|
||||
Version: 5.0.0
|
||||
Release: 4%{?dist}
|
||||
Release: 8%{?dist}
|
||||
License: GPL+ and LGPLv2+
|
||||
Group: System Environment/Base
|
||||
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
|
||||
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
|
||||
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
|
||||
A set of commands to use the XFS filesystem, including mkfs.xfs.
|
||||
@ -63,6 +75,18 @@ also want to install xfsprogs.
|
||||
%patch5 -p1
|
||||
%patch6 -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
|
||||
export tagname=CC
|
||||
@ -122,6 +146,21 @@ rm -rf $RPM_BUILD_ROOT/%{_mandir}/man8/xfs_scrub*
|
||||
%{_libdir}/*.so
|
||||
|
||||
%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
|
||||
- mkfs.xfs: inform user about discard, and make interruptable (#1836414)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user