import xfsprogs-6.4.0-4.el9

i9c-beta changed/i9c-beta/xfsprogs-6.4.0-4.el9
MSVSphere Packaging Team 3 months ago
parent 41eb9d8962
commit a7d79da6c5
Signed by: sys_gitsync
GPG Key ID: B2B0B9F29E528FE8

2
.gitignore vendored

@ -1 +1 @@
SOURCES/xfsprogs-6.3.0.tar.xz
SOURCES/xfsprogs-6.4.0.tar.xz

@ -1 +1 @@
e976c2c41a957ee16094690596ee210dd45951fa SOURCES/xfsprogs-6.3.0.tar.xz
04935475fff6580d7e1919bf9a19331951edf529 SOURCES/xfsprogs-6.4.0.tar.xz

@ -1,7 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iIQEABYIAC0WIQT6QG4gav94c4l8aGS0VhjDaiT9IwUCZGs+kg8cY2VtQGtlcm5l
bC5vcmcACgkQtFYYw2ok/SO6wgEAgMdBBcJsx/oEPKLXGZr+ueGZ81K7hGq8ueFF
sXp69AEA+PiK4Bh/angpo2lhftgZhGaOHxmj8vIyH2jJSw53LgE=
=+kzW
-----END PGP SIGNATURE-----

@ -1,30 +0,0 @@
From 965f91091e4442ea74132aa0c3c6795d922bda8c Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Thu, 8 Jun 2023 11:13:20 +0200
Subject: [PATCH] mkfs: fix man's default value for sparse option
Fixes: 9cf846b51 ("mkfs: enable sparse inodes by default")
Suggested-by: Lukas Herbolt <lukas@herbolt.com>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
man/man8/mkfs.xfs.8.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/man/man8/mkfs.xfs.8.in b/man/man8/mkfs.xfs.8.in
index 01f9dc6e..ce6f1e2d 100644
--- a/man/man8/mkfs.xfs.8.in
+++ b/man/man8/mkfs.xfs.8.in
@@ -631,7 +631,7 @@ Enable sparse inode chunk allocation. The
.I value
is either 0 or 1, with 1 signifying that sparse allocation is enabled.
If the value is omitted, 1 is assumed. Sparse inode allocation is
-disabled by default. This feature is only available for filesystems
+enabled by default. This feature is only available for filesystems
formatted with
.B \-m crc=1.
.IP
--
2.41.0

@ -1,131 +0,0 @@
From 7901c8c1a501de87c42bb1ed83456f99462538c6 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Thu, 1 Jun 2023 11:41:10 +0200
Subject: [PATCH] xfs: set bnobt/cntbt numrecs correctly when formatting new
AGs
Source kernel commit: 8e698ee72c4ecbbf18264568eb310875839fd601
Through generic/300, I discovered that mkfs.xfs creates corrupt
filesystems when given these parameters:
# mkfs.xfs -d size=512M /dev/sda -f -d su=128k,sw=4 --unsupported
Filesystems formatted with --unsupported are not supported!!
meta-data=/dev/sda isize=512 agcount=8, agsize=16352 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=1, sparse=1, rmapbt=1
= reflink=1 bigtime=1 inobtcount=1 nrext64=1
data = bsize=4096 blocks=130816, imaxpct=25
= sunit=32 swidth=128 blks
naming =version 2 bsize=4096 ascii-ci=0, ftype=1
log =internal log bsize=4096 blocks=8192, version=2
= sectsz=512 sunit=32 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
= rgcount=0 rgsize=0 blks
Discarding blocks...Done.
# xfs_repair -n /dev/sda
Phase 1 - find and verify superblock...
- reporting progress in intervals of 15 minutes
Phase 2 - using internal log
- zero log...
- 16:30:50: zeroing log - 16320 of 16320 blocks done
- scan filesystem freespace and inode maps...
agf_freeblks 25, counted 0 in ag 4
sb_fdblocks 8823, counted 8798
The root cause of this problem is the numrecs handling in
xfs_freesp_init_recs, which is used to initialize a new AG. Prior to
calling the function, we set up the new bnobt block with numrecs == 1
and rely on _freesp_init_recs to format that new record. If the last
record created has a blockcount of zero, then it sets numrecs = 0.
That last bit isn't correct if the AG contains the log, the start of the
log is not immediately after the initial blocks due to stripe alignment,
and the end of the log is perfectly aligned with the end of the AG. For
this case, we actually formatted a single bnobt record to handle the
free space before the start of the (stripe aligned) log, and incremented
arec to try to format a second record. That second record turned out to
be unnecessary, so what we really want is to leave numrecs at 1.
The numrecs handling itself is overly complicated because a different
function sets numrecs == 1. Change the bnobt creation code to start
with numrecs set to zero and only increment it after successfully
formatting a free space extent into the btree block.
Fixes: f327a00745ff ("xfs: account for log space when formatting new AGs")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
libxfs/xfs_ag.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/libxfs/xfs_ag.c b/libxfs/xfs_ag.c
index e3465e06..5d269312 100644
--- a/libxfs/xfs_ag.c
+++ b/libxfs/xfs_ag.c
@@ -493,10 +493,12 @@ xfs_freesp_init_recs(
ASSERT(start >= mp->m_ag_prealloc_blocks);
if (start != mp->m_ag_prealloc_blocks) {
/*
- * Modify first record to pad stripe align of log
+ * Modify first record to pad stripe align of log and
+ * bump the record count.
*/
arec->ar_blockcount = cpu_to_be32(start -
mp->m_ag_prealloc_blocks);
+ be16_add_cpu(&block->bb_numrecs, 1);
nrec = arec + 1;
/*
@@ -507,7 +509,6 @@ xfs_freesp_init_recs(
be32_to_cpu(arec->ar_startblock) +
be32_to_cpu(arec->ar_blockcount));
arec = nrec;
- be16_add_cpu(&block->bb_numrecs, 1);
}
/*
* Change record start to after the internal log
@@ -516,15 +517,13 @@ xfs_freesp_init_recs(
}
/*
- * Calculate the record block count and check for the case where
- * the log might have consumed all available space in the AG. If
- * so, reset the record count to 0 to avoid exposure of an invalid
- * record start block.
+ * Calculate the block count of this record; if it is nonzero,
+ * increment the record count.
*/
arec->ar_blockcount = cpu_to_be32(id->agsize -
be32_to_cpu(arec->ar_startblock));
- if (!arec->ar_blockcount)
- block->bb_numrecs = 0;
+ if (arec->ar_blockcount)
+ be16_add_cpu(&block->bb_numrecs, 1);
}
/*
@@ -536,7 +535,7 @@ xfs_bnoroot_init(
struct xfs_buf *bp,
struct aghdr_init_data *id)
{
- xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 1, id->agno);
+ xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 0, id->agno);
xfs_freesp_init_recs(mp, bp, id);
}
@@ -546,7 +545,7 @@ xfs_cntroot_init(
struct xfs_buf *bp,
struct aghdr_init_data *id)
{
- xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 1, id->agno);
+ xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 0, id->agno);
xfs_freesp_init_recs(mp, bp, id);
}
--
2.41.0

@ -1,132 +0,0 @@
From bd970a7390d9af5ce859397a6c368d2465368d76 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Wed, 31 May 2023 11:13:21 +0200
Subject: [PATCH] xfs: stabilize the dirent name transformation function used
for ascii-ci dir hash computation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Source kernel commit: a9248538facc3d9e769489e50a544509c2f9cebe
Back in the old days, the "ascii-ci" feature was created to implement
case-insensitive directory entry lookups for latin1-encoded names and
remove the large overhead of Samba's case-insensitive lookup code. UTF8
names were not allowed, but nobody explicitly wrote in the documentation
that this was only expected to work if the system used latin1 names.
The kernel tolower function was selected to prepare names for hashed
lookups.
There's a major discrepancy in the function that computes directory entry
hashes for filesystems that have ASCII case-insensitive lookups enabled.
The root of this is that the kernel and glibc's tolower implementations
have differing behavior for extended ASCII accented characters. I wrote
a program to spit out characters for which the tolower() return value is
different from the input:
glibc tolower:
65:A 66:B 67:C 68:D 69:E 70:F 71:G 72:H 73:I 74:J 75:K 76:L 77:M 78:N
79:O 80:P 81:Q 82:R 83:S 84:T 85:U 86:V 87:W 88:X 89:Y 90:Z
kernel tolower:
65:A 66:B 67:C 68:D 69:E 70:F 71:G 72:H 73:I 74:J 75:K 76:L 77:M 78:N
79:O 80:P 81:Q 82:R 83:S 84:T 85:U 86:V 87:W 88:X 89:Y 90:Z 192:À 193:Á
194:Â 195:Ã 196:Ä 197:Å 198:Æ 199:Ç 200:È 201:É 202:Ê 203:Ë 204:Ì 205:Í
206:Î 207:Ï 208:Ð 209:Ñ 210:Ò 211:Ó 212:Ô 213:Õ 214:Ö 215:× 216:Ø 217:Ù
218:Ú 219:Û 220:Ü 221:Ý 222:Þ
Which means that the kernel and userspace do not agree on the hash value
for a directory filename that contains those higher values. The hash
values are written into the leaf index block of directories that are
larger than two blocks in size, which means that xfs_repair will flag
these directories as having corrupted hash indexes and rewrite the index
with hash values that the kernel now will not recognize.
Because the ascii-ci feature is not frequently enabled and the kernel
touches filesystems far more frequently than xfs_repair does, fix this
by encoding the kernel's toupper predicate and tolower functions into
libxfs. Give the new functions less provocative names to make it really
obvious that this is a pre-hash name preparation function, and nothing
else. This change makes userspace's behavior consistent with the
kernel.
Found by auditing obfuscate_name in xfs_metadump as part of working on
parent pointers, wondering how it could possibly work correctly with ci
filesystems, writing a test tool to create a directory with
hash-colliding names, and watching xfs_repair flag it.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
libxfs/xfs_dir2.c | 5 +++--
libxfs/xfs_dir2.h | 31 +++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c
index d6a19296..c19684b3 100644
--- a/libxfs/xfs_dir2.c
+++ b/libxfs/xfs_dir2.c
@@ -63,7 +63,7 @@ xfs_ascii_ci_hashname(
int i;
for (i = 0, hash = 0; i < name->len; i++)
- hash = tolower(name->name[i]) ^ rol32(hash, 7);
+ hash = xfs_ascii_ci_xfrm(name->name[i]) ^ rol32(hash, 7);
return hash;
}
@@ -84,7 +84,8 @@ xfs_ascii_ci_compname(
for (i = 0; i < len; i++) {
if (args->name[i] == name[i])
continue;
- if (tolower(args->name[i]) != tolower(name[i]))
+ if (xfs_ascii_ci_xfrm(args->name[i]) !=
+ xfs_ascii_ci_xfrm(name[i]))
return XFS_CMP_DIFFERENT;
result = XFS_CMP_CASE;
}
diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h
index dd39f17d..19af22a1 100644
--- a/libxfs/xfs_dir2.h
+++ b/libxfs/xfs_dir2.h
@@ -248,4 +248,35 @@ unsigned int xfs_dir3_data_end_offset(struct xfs_da_geometry *geo,
struct xfs_dir2_data_hdr *hdr);
bool xfs_dir2_namecheck(const void *name, size_t length);
+/*
+ * The "ascii-ci" feature was created to speed up case-insensitive lookups for
+ * a Samba product. Because of the inherent problems with CI and UTF-8
+ * encoding, etc, it was decided that Samba would be configured to export
+ * latin1/iso 8859-1 encodings as that covered >90% of the target markets for
+ * the product. Hence the "ascii-ci" casefolding code could be encoded into
+ * the XFS directory operations and remove all the overhead of casefolding from
+ * Samba.
+ *
+ * To provide consistent hashing behavior between the userspace and kernel,
+ * these functions prepare names for hashing by transforming specific bytes
+ * to other bytes. Robustness with other encodings is not guaranteed.
+ */
+static inline bool xfs_ascii_ci_need_xfrm(unsigned char c)
+{
+ if (c >= 0x41 && c <= 0x5a) /* A-Z */
+ return true;
+ if (c >= 0xc0 && c <= 0xd6) /* latin A-O with accents */
+ return true;
+ if (c >= 0xd8 && c <= 0xde) /* latin O-Y with accents */
+ return true;
+ return false;
+}
+
+static inline unsigned char xfs_ascii_ci_xfrm(unsigned char c)
+{
+ if (xfs_ascii_ci_need_xfrm(c))
+ c -= 'A' - 'a';
+ return c;
+}
+
#endif /* __XFS_DIR2_H__ */
--
2.41.0

@ -1,178 +0,0 @@
From 10a01bcdd748773c185255516a72e75a71295bd4 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Thu, 15 Jun 2023 09:11:04 -0700
Subject: [PATCH] xfs_db: fix metadump name obfuscation for ascii-ci
filesystems
Now that we've stabilized the dirent hash function for ascii-ci
filesystems, adapt the metadump name obfuscation code to detect when
it's obfuscating a directory entry name on an ascii-ci filesystem and
spit out names that actually have the same hash.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
db/metadump.c | 82 +++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 73 insertions(+), 9 deletions(-)
diff --git a/db/metadump.c b/db/metadump.c
index 317ff728..9ccee0b7 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -817,13 +817,17 @@ static void
obfuscate_name(
xfs_dahash_t hash,
size_t name_len,
- unsigned char *name)
+ unsigned char *name,
+ bool is_dirent)
{
- unsigned char *newp = name;
+ unsigned char *oldname = NULL;
+ unsigned char *newp;
int i;
- xfs_dahash_t new_hash = 0;
+ xfs_dahash_t new_hash;
unsigned char *first;
unsigned char high_bit;
+ int tries = 0;
+ bool is_ci_name = is_dirent && xfs_has_asciici(mp);
int shift;
/*
@@ -836,6 +840,26 @@ obfuscate_name(
if (name_len < 5)
return;
+ if (is_ci_name) {
+ oldname = malloc(name_len);
+ if (!oldname)
+ return;
+ memcpy(oldname, name, name_len);
+ }
+
+again:
+ newp = name;
+ new_hash = 0;
+
+ /*
+ * If we cannot generate a ci-compatible obfuscated name after 1000
+ * tries, don't bother obfuscating the name.
+ */
+ if (tries++ > 1000) {
+ memcpy(name, oldname, name_len);
+ goto out_free;
+ }
+
/*
* The beginning of the obfuscated name can be pretty much
* anything, so fill it in with random characters.
@@ -843,7 +867,11 @@ obfuscate_name(
*/
for (i = 0; i < name_len - 5; i++) {
*newp = random_filename_char();
- new_hash = *newp ^ rol32(new_hash, 7);
+ if (is_ci_name)
+ new_hash = xfs_ascii_ci_xfrm(*newp) ^
+ rol32(new_hash, 7);
+ else
+ new_hash = *newp ^ rol32(new_hash, 7);
newp++;
}
@@ -867,6 +895,17 @@ obfuscate_name(
high_bit = 0x80;
} else
high_bit = 0;
+
+ /*
+ * If ascii-ci is enabled, uppercase characters are converted
+ * to lowercase characters while computing the name hash. If
+ * any of the necessary correction bytes are uppercase, the
+ * hash of the new name will not match. Try again with a
+ * different prefix.
+ */
+ if (is_ci_name && xfs_ascii_ci_need_xfrm(*newp))
+ goto again;
+
ASSERT(!is_invalid_char(*newp));
newp++;
}
@@ -880,8 +919,15 @@ obfuscate_name(
*/
if (high_bit) {
*first ^= 0x10;
+
+ if (is_ci_name && xfs_ascii_ci_need_xfrm(*first))
+ goto again;
+
ASSERT(!is_invalid_char(*first));
}
+
+out_free:
+ free(oldname);
}
/*
@@ -1177,6 +1223,24 @@ handle_duplicate_name(xfs_dahash_t hash, size_t name_len, unsigned char *name)
return 1;
}
+static inline xfs_dahash_t
+dirattr_hashname(
+ bool is_dirent,
+ const uint8_t *name,
+ int namelen)
+{
+ if (is_dirent) {
+ struct xfs_name xname = {
+ .name = name,
+ .len = namelen,
+ };
+
+ return libxfs_dir2_hashname(mp, &xname);
+ }
+
+ return libxfs_da_hashname(name, namelen);
+}
+
static void
generate_obfuscated_name(
xfs_ino_t ino,
@@ -1205,9 +1269,9 @@ generate_obfuscated_name(
/* Obfuscate the name (if possible) */
- hash = libxfs_da_hashname(name, namelen);
- obfuscate_name(hash, namelen, name);
- ASSERT(hash == libxfs_da_hashname(name, namelen));
+ hash = dirattr_hashname(ino != 0, name, namelen);
+ obfuscate_name(hash, namelen, name, ino != 0);
+ ASSERT(hash == dirattr_hashname(ino != 0, name, namelen));
/*
* Make sure the name is not something already seen. If we
@@ -1320,7 +1384,7 @@ obfuscate_path_components(
/* last (or single) component */
namelen = strnlen((char *)comp, len);
hash = libxfs_da_hashname(comp, namelen);
- obfuscate_name(hash, namelen, comp);
+ obfuscate_name(hash, namelen, comp, false);
ASSERT(hash == libxfs_da_hashname(comp, namelen));
break;
}
@@ -1332,7 +1396,7 @@ obfuscate_path_components(
continue;
}
hash = libxfs_da_hashname(comp, namelen);
- obfuscate_name(hash, namelen, comp);
+ obfuscate_name(hash, namelen, comp, false);
ASSERT(hash == libxfs_da_hashname(comp, namelen));
comp += namelen + 1;
len -= namelen + 1;
--
2.41.0

@ -1,56 +0,0 @@
From cb8c70b017e30d4004373300bce488a9687166ac Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Mon, 5 Jun 2023 08:36:38 -0700
Subject: [PATCH] xfs_db: move obfuscate_name assertion to callers
Currently, obfuscate_name asserts that the hash of the new name is the
same as the old name. To enable bug fixes in the next patch, move this
assertion to the callers.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
db/metadump.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/db/metadump.c b/db/metadump.c
index 27d1df43..317ff728 100644
--- a/db/metadump.c
+++ b/db/metadump.c
@@ -882,7 +882,6 @@ obfuscate_name(
*first ^= 0x10;
ASSERT(!is_invalid_char(*first));
}
- ASSERT(libxfs_da_hashname(name, name_len) == hash);
}
/*
@@ -1208,6 +1207,7 @@ generate_obfuscated_name(
hash = libxfs_da_hashname(name, namelen);
obfuscate_name(hash, namelen, name);
+ ASSERT(hash == libxfs_da_hashname(name, namelen));
/*
* Make sure the name is not something already seen. If we
@@ -1321,6 +1321,7 @@ obfuscate_path_components(
namelen = strnlen((char *)comp, len);
hash = libxfs_da_hashname(comp, namelen);
obfuscate_name(hash, namelen, comp);
+ ASSERT(hash == libxfs_da_hashname(comp, namelen));
break;
}
namelen = slash - (char *)comp;
@@ -1332,6 +1333,7 @@ obfuscate_path_components(
}
hash = libxfs_da_hashname(comp, namelen);
obfuscate_name(hash, namelen, comp);
+ ASSERT(hash == libxfs_da_hashname(comp, namelen));
comp += namelen + 1;
len -= namelen + 1;
}
--
2.41.0

@ -1,41 +0,0 @@
From aca02624815ca47c6fd4cafdb0aeaad641ca1915 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Mon, 5 Jun 2023 08:37:24 -0700
Subject: [PATCH] xfs_repair: don't add junked entries to the rebuilt directory
If a directory contains multiple entries with the same name, we create
separate objects in the directory hashtab for each dirent. The first
one has p->junkit==0, but the subsequent ones have p->junkit==1.
Because these are duplicate names that are not garbage, the first
character of p->name.name is not set to a slash.
Don't add these subsequent hashtab entries to the rebuilt directory.
Found by running xfs/155 with the parent pointers patchset enabled.
Fixes: 33165ec3b4b ("Fix dirv2 rebuild in phase6 Merge of master-melb:xfs-cmds:26664a by kenmcd.")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Pavel Reichl <preichl@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
repair/phase6.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/repair/phase6.c b/repair/phase6.c
index 25bbcd10..3870c5c9 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -1316,7 +1316,8 @@ longform_dir2_rebuild(
/* go through the hash list and re-add the inodes */
for (p = hashtab->first; p; p = p->nextbyorder) {
-
+ if (p->junkit)
+ continue;
if (p->name.name[0] == '/' || (p->name.name[0] == '.' &&
(p->name.len == 1 || (p->name.len == 2 &&
p->name.name[1] == '.'))))
--
2.41.0

@ -1,57 +0,0 @@
From 67f541056f4dd3ba1ccc5d11464d67afdab0f2a3 Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Mon, 5 Jun 2023 08:37:39 -0700
Subject: [PATCH] xfs_repair: don't spray correcting imap all by itself
In xfs/155, I occasionally see this in the xfs_repair output:
correcting imap
correcting imap
correcting imap
...
This is completely useless, since we don't actually log which inode
prompted this message. This logic has been here for a really long time,
but ... I can't make heads nor tails of it. If we're running in verbose
or dry-run mode, then print the inode number, but not if we're running
in fixit mode?
A few lines later, if we're running in verbose dry-run mode, we print
"correcting imap" even though we're not going to write anything.
If we get here, the inode looks like it's in use, but the inode index
says it isn't. This is a corruption, so either we fix it or we say that
we would fix it.
Fixes: 6c39a3cbda3 ("Don't trash lost+found in phase 4 Merge of master-melb:xfs-cmds:29144a by kenmcd.")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
repair/dino_chunks.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c
index 0e09132b..0841e65b 100644
--- a/repair/dino_chunks.c
+++ b/repair/dino_chunks.c
@@ -871,13 +871,11 @@ next_readbuf:
*/
if (is_used) {
if (is_inode_free(ino_rec, irec_offset)) {
- if (verbose || no_modify) {
- do_warn(
+ do_warn(
_("imap claims in-use inode %" PRIu64 " is free, "),
ino);
- }
- if (verbose || !no_modify)
+ if (!no_modify)
do_warn(_("correcting imap\n"));
else
do_warn(_("would correct imap\n"));
--
2.41.0

@ -1,39 +0,0 @@
From 1e12a0751b99efd48cda501258e16f00bef9d13d Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Mon, 5 Jun 2023 08:38:01 -0700
Subject: [PATCH] xfs_repair: fix messaging when fixing imap due to sparse
cluster
This logic is wrong -- if we're in verbose dry-run mode, we do NOT want
to say that we're correcting the imap. Otherwise, we print things like:
imap claims inode XXX is present, but inode cluster is sparse,
But then we can erroneously tell the user that we would correct the
imap when in fact we /are/ correcting it.
Fixes: f4ff8086586 ("xfs_repair: don't crash on partially sparse inode clusters")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
repair/dino_chunks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c
index 0841e65b1844..64ce2a323c8d 100644
--- a/repair/dino_chunks.c
+++ b/repair/dino_chunks.c
@@ -834,7 +834,7 @@ next_readbuf:
do_warn(
_("imap claims inode %" PRIu64 " is present, but inode cluster is sparse, "),
ino);
- if (verbose || !no_modify)
+ if (!no_modify)
do_warn(_("correcting imap\n"));
else
do_warn(_("would correct imap\n"));
--
2.41.0

@ -1,96 +0,0 @@
From d159552bbb05de6998388b960f50e5e0012828ea Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Mon, 5 Jun 2023 08:37:50 -0700
Subject: [PATCH] xfs_repair: fix messaging when shortform_dir2_junk is called
This function is called when we've decide to junk a shortform directory
entry. This is obviously corruption of some kind, so we should always
say something, particularly if we're in !verbose repair mode.
Otherwise, if we're in non-verbose repair mode, we print things like:
entry "FOO" in shortform directory XXX references non-existent inode YYY
Without telling the sysadmin that we're removing the dirent.
Fixes: aaca101b1ae ("xfs_repair: add support for validating dirent ftype field")
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
repair/phase6.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/repair/phase6.c b/repair/phase6.c
index c6418534..be10d9b7 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -2440,10 +2440,7 @@ shortform_dir2_junk(
*/
(*index)--;
- if (verbose)
- do_warn(_("junking entry\n"));
- else
- do_warn("\n");
+ do_warn(_("junking entry\n"));
return sfep;
}
@@ -2592,7 +2589,7 @@ shortform_dir2_entry_check(
if (irec == NULL) {
do_warn(
- _("entry \"%s\" in shortform directory %" PRIu64 " references non-existent inode %" PRIu64 "\n"),
+ _("entry \"%s\" in shortform directory %" PRIu64 " references non-existent inode %" PRIu64 ", "),
fname, ino, lino);
next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
&max_size, &i, &bytes_deleted,
@@ -2609,7 +2606,7 @@ shortform_dir2_entry_check(
*/
if (is_inode_free(irec, ino_offset)) {
do_warn(
- _("entry \"%s\" in shortform directory inode %" PRIu64 " points to free inode %" PRIu64 "\n"),
+ _("entry \"%s\" in shortform directory inode %" PRIu64 " points to free inode %" PRIu64 ", "),
fname, ino, lino);
next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
&max_size, &i, &bytes_deleted,
@@ -2625,7 +2622,7 @@ shortform_dir2_entry_check(
*/
if (!inode_isadir(irec, ino_offset)) {
do_warn(
- _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory"),
+ _("%s (ino %" PRIu64 ") in root (%" PRIu64 ") is not a directory, "),
ORPHANAGE, lino, ino);
next_sfep = shortform_dir2_junk(mp, sfp, sfep,
lino, &max_size, &i,
@@ -2647,7 +2644,7 @@ shortform_dir2_entry_check(
lino, sfep->namelen, sfep->name,
libxfs_dir2_sf_get_ftype(mp, sfep))) {
do_warn(
-_("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
+_("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name, "),
fname, lino, ino);
next_sfep = shortform_dir2_junk(mp, sfp, sfep, lino,
&max_size, &i, &bytes_deleted,
@@ -2672,7 +2669,7 @@ _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
if (is_inode_reached(irec, ino_offset)) {
do_warn(
_("entry \"%s\" in directory inode %" PRIu64
- " references already connected inode %" PRIu64 ".\n"),
+ " references already connected inode %" PRIu64 ", "),
fname, ino, lino);
next_sfep = shortform_dir2_junk(mp, sfp, sfep,
lino, &max_size, &i,
@@ -2696,7 +2693,7 @@ _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"),
do_warn(
_("entry \"%s\" in directory inode %" PRIu64
" not consistent with .. value (%" PRIu64
- ") in inode %" PRIu64 ",\n"),
+ ") in inode %" PRIu64 ", "),
fname, ino, parent, lino);
next_sfep = shortform_dir2_junk(mp, sfp, sfep,
lino, &max_size, &i,
--
2.41.0

@ -0,0 +1,7 @@
-----BEGIN PGP SIGNATURE-----
iIUEABYIAC0WIQT6QG4gav94c4l8aGS0VhjDaiT9IwUCZLfVMw8cY2VtQGtlcm5l
bC5vcmcACgkQtFYYw2ok/SNKPwEA6fsxp1TRbPXQn6a605fU3cE6WjcqDLej3zYa
lx91BnABAKIWP14Rd7KPbCH4ezAPydFZxSn26trKqPxzAFOZ/skP
=mkU4
-----END PGP SIGNATURE-----

@ -0,0 +1,57 @@
From d096b26c33a858ad88db98306057da67e6d18611 Mon Sep 17 00:00:00 2001
From: Dave Chinner <dchinner@redhat.com>
Date: Wed, 6 Sep 2023 13:52:48 +0200
Subject: [PATCH] xfs: fix bounds check in xfs_defer_agfl_block()
Source kernel commit: 2bed0d82c2f78b91a0a9a5a73da57ee883a0c070
Need to happen before we allocate and then leak the xefi. Found by
coverity via an xfsprogs libxfs scan.
[djwong: This also fixes the type of the @agbno argument.]
Fixes: 7dfee17b13e5 ("xfs: validate block number being freed before adding to xefi")
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
---
libxfs/xfs_alloc.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
Index: xfsprogs-6.4.0/libxfs/xfs_alloc.c
===================================================================
--- xfsprogs-6.4.0.orig/libxfs/xfs_alloc.c
+++ xfsprogs-6.4.0/libxfs/xfs_alloc.c
@@ -2431,24 +2431,25 @@ static int
xfs_defer_agfl_block(
struct xfs_trans *tp,
xfs_agnumber_t agno,
- xfs_fsblock_t agbno,
+ xfs_agblock_t agbno,
struct xfs_owner_info *oinfo)
{
struct xfs_mount *mp = tp->t_mountp;
struct xfs_extent_free_item *xefi;
+ xfs_fsblock_t fsbno = XFS_AGB_TO_FSB(mp, agno, agbno);
ASSERT(xfs_extfree_item_cache != NULL);
ASSERT(oinfo != NULL);
+ if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbno(mp, fsbno)))
+ return -EFSCORRUPTED;
+
xefi = kmem_cache_zalloc(xfs_extfree_item_cache,
GFP_KERNEL | __GFP_NOFAIL);
- xefi->xefi_startblock = XFS_AGB_TO_FSB(mp, agno, agbno);
+ xefi->xefi_startblock = fsbno;
xefi->xefi_blockcount = 1;
xefi->xefi_owner = oinfo->oi_owner;
- if (XFS_IS_CORRUPT(mp, !xfs_verify_fsbno(mp, xefi->xefi_startblock)))
- return -EFSCORRUPTED;
-
trace_xfs_agfl_free_defer(mp, agno, 0, agbno, 1);
xfs_extent_free_get_group(mp, xefi);

@ -0,0 +1,102 @@
From a21daa3a739194b929de644779c359949390d467 Mon Sep 17 00:00:00 2001
From: Andrey Albershteyn <aalbersh@redhat.com>
Date: Wed, 17 Apr 2024 18:19:30 +0200
Subject: [PATCH] xfs_db: add helper for flist_find_type for clearer field
matching
Make flist_find_type() more readable by unloading field type
matching to the helper.
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
db/flist.c | 60 ++++++++++++++++++++++++++++++++++--------------------
1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/db/flist.c b/db/flist.c
index 0a6cc5fc..ab0a0f13 100644
--- a/db/flist.c
+++ b/db/flist.c
@@ -400,6 +400,40 @@ flist_split(
return v;
}
+static flist_t *
+flist_field_match(
+ const field_t *field,
+ fldt_t type,
+ void *obj,
+ int startoff)
+{
+ flist_t *fl;
+ int count;
+ const ftattr_t *fa;
+ flist_t *nfl;
+
+ fl = flist_make(field->name);
+ fl->fld = field;
+ if (field->ftyp == type)
+ return fl;
+ count = fcount(field, obj, startoff);
+ if (!count)
+ goto out;
+ fa = &ftattrtab[field->ftyp];
+ if (!fa->subfld)
+ goto out;
+
+ nfl = flist_find_ftyp(fa->subfld, type, obj, startoff);
+ if (nfl) {
+ fl->child = nfl;
+ return fl;
+ }
+
+out:
+ flist_free(fl);
+ return NULL;
+}
+
/*
* Given a set of fields, scan for a field of the given type.
* Return an flist leading to the first found field
@@ -413,33 +447,15 @@ flist_find_ftyp(
void *obj,
int startoff)
{
- flist_t *fl;
const field_t *f;
- int count;
- const ftattr_t *fa;
+ flist_t *fl;
for (f = fields; f->name; f++) {
- fl = flist_make(f->name);
- fl->fld = f;
- if (f->ftyp == type)
+ fl = flist_field_match(f, type, obj, startoff);
+ if (fl)
return fl;
- count = fcount(f, obj, startoff);
- if (!count) {
- flist_free(fl);
- continue;
- }
- fa = &ftattrtab[f->ftyp];
- if (fa->subfld) {
- flist_t *nfl;
-
- nfl = flist_find_ftyp(fa->subfld, type, obj, startoff);
- if (nfl) {
- fl->child = nfl;
- return fl;
- }
- }
- flist_free(fl);
}
+
return NULL;
}
--
2.45.2

@ -0,0 +1,35 @@
From 21dc682a3842eb7e4c79f7e511d840e708d7e757 Mon Sep 17 00:00:00 2001
From: Andrey Albershteyn <aalbersh@redhat.com>
Date: Tue, 23 Apr 2024 14:36:14 +0200
Subject: [PATCH] xfs_db: fix leak in flist_find_ftyp()
When count is zero fl reference is lost. Fix it by freeing the list.
Fixes: a0d79cb37a36 ("xfs_db: make flist_find_ftyp() to check for field existance on disk")
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Bill O'Donnell <bodonnel@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
---
db/flist.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/db/flist.c b/db/flist.c
index c81d229a..0a6cc5fc 100644
--- a/db/flist.c
+++ b/db/flist.c
@@ -424,8 +424,10 @@ flist_find_ftyp(
if (f->ftyp == type)
return fl;
count = fcount(f, obj, startoff);
- if (!count)
+ if (!count) {
+ flist_free(fl);
continue;
+ }
fa = &ftattrtab[f->ftyp];
if (fa->subfld) {
flist_t *nfl;
--
2.45.2

@ -0,0 +1,56 @@
From 9c6e9d8de2d236f630efdd6fddb6277e8664989b Mon Sep 17 00:00:00 2001
From: Andrey Albershteyn <aalbersh@redhat.com>
Date: Tue, 23 Apr 2024 14:36:17 +0200
Subject: [PATCH] xfs_fsr: convert fsrallfs to use time_t instead of int
Convert howlong argument to a time_t as it's truncated to int, but in
practice this is not an issue as duration will never be this big.
Add check for howlong to fit into int (printf can use int format
specifier). Even longer interval doesn't make much sense.
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
---
fsr/xfs_fsr.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index 3077d8f4..02d61ef9 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -72,7 +72,7 @@ static int packfile(char *fname, char *tname, int fd,
static void fsrdir(char *dirname);
static int fsrfs(char *mntdir, xfs_ino_t ino, int targetrange);
static void initallfs(char *mtab);
-static void fsrallfs(char *mtab, int howlong, char *leftofffile);
+static void fsrallfs(char *mtab, time_t howlong, char *leftofffile);
static void fsrall_cleanup(int timeout);
static int getnextents(int);
int xfsrtextsize(int fd);
@@ -165,6 +165,12 @@ main(int argc, char **argv)
break;
case 't':
howlong = atoi(optarg);
+ if (howlong > INT_MAX) {
+ fprintf(stderr,
+ _("%s: the maximum runtime is %d seconds.\n"),
+ optarg, INT_MAX);
+ exit(1);
+ }
break;
case 'f':
leftofffile = optarg;
@@ -387,7 +393,7 @@ initallfs(char *mtab)
}
static void
-fsrallfs(char *mtab, int howlong, char *leftofffile)
+fsrallfs(char *mtab, time_t howlong, char *leftofffile)
{
int fd;
int error;
--
2.45.2

@ -0,0 +1,64 @@
From 652f8066b7ca7dc1e08c2c40cdd9ba593a9de568 Mon Sep 17 00:00:00 2001
From: Andrey Albershteyn <aalbersh@redhat.com>
Date: Wed, 17 Apr 2024 18:19:29 +0200
Subject: [PATCH] xfs_fsr: replace atoi() with strtol()
Replace atoi() which silently fails with strtol() and report the
error.
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
fsr/xfs_fsr.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c
index 02d61ef9..fdd37756 100644
--- a/fsr/xfs_fsr.c
+++ b/fsr/xfs_fsr.c
@@ -164,7 +164,13 @@ main(int argc, char **argv)
usage(1);
break;
case 't':
- howlong = atoi(optarg);
+ errno = 0;
+ howlong = strtol(optarg, NULL, 10);
+ if (errno) {
+ fprintf(stderr, _("%s: invalid runtime: %s\n"),
+ optarg, strerror(errno));
+ exit(1);
+ }
if (howlong > INT_MAX) {
fprintf(stderr,
_("%s: the maximum runtime is %d seconds.\n"),
@@ -179,10 +185,24 @@ main(int argc, char **argv)
mtab = optarg;
break;
case 'b':
- argv_blksz_dio = atoi(optarg);
+ errno = 0;
+ argv_blksz_dio = strtol(optarg, NULL, 10);
+ if (errno) {
+ fprintf(stderr,
+ _("%s: invalid block size: %s\n"),
+ optarg, strerror(errno));
+ exit(1);
+ }
break;
case 'p':
- npasses = atoi(optarg);
+ errno = 0;
+ npasses = strtol(optarg, NULL, 10);
+ if (errno) {
+ fprintf(stderr,
+ _("%s: invalid number of passes: %s\n"),
+ optarg, strerror(errno));
+ exit(1);
+ }
break;
case 'C':
/* Testing opt: coerses frag count in result */
--
2.45.2

@ -0,0 +1,129 @@
From d03b73d240dc7f5b4c02700c79c2c4eeeb94b08b Mon Sep 17 00:00:00 2001
From: Andrey Albershteyn <aalbersh@redhat.com>
Date: Wed, 17 Apr 2024 18:19:31 +0200
Subject: [PATCH] xfs_repair: catch strtol() errors
strtol() sets errno if string parsing. Abort and tell user which
parameter is wrong.
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
repair/xfs_repair.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index 2ceea87d..2fc89dac 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -252,14 +252,22 @@ process_args(int argc, char **argv)
if (!val)
do_abort(
_("-o bhash requires a parameter\n"));
+ errno = 0;
libxfs_bhash_size = (int)strtol(val, NULL, 0);
+ if (errno)
+ do_abort(
+ _("-o bhash invalid parameter: %s\n"), strerror(errno));
bhash_option_used = 1;
break;
case AG_STRIDE:
if (!val)
do_abort(
_("-o ag_stride requires a parameter\n"));
+ errno = 0;
ag_stride = (int)strtol(val, NULL, 0);
+ if (errno)
+ do_abort(
+ _("-o ag_stride invalid parameter: %s\n"), strerror(errno));
break;
case FORCE_GEO:
if (val)
@@ -272,19 +280,31 @@ process_args(int argc, char **argv)
if (!val)
do_abort(
_("-o phase2_threads requires a parameter\n"));
+ errno = 0;
phase2_threads = (int)strtol(val, NULL, 0);
+ if (errno)
+ do_abort(
+ _("-o phase2_threads invalid parameter: %s\n"), strerror(errno));
break;
case BLOAD_LEAF_SLACK:
if (!val)
do_abort(
_("-o debug_bload_leaf_slack requires a parameter\n"));
+ errno = 0;
bload_leaf_slack = (int)strtol(val, NULL, 0);
+ if (errno)
+ do_abort(
+ _("-o debug_bload_leaf_slack invalid parameter: %s\n"), strerror(errno));
break;
case BLOAD_NODE_SLACK:
if (!val)
do_abort(
_("-o debug_bload_node_slack requires a parameter\n"));
+ errno = 0;
bload_node_slack = (int)strtol(val, NULL, 0);
+ if (errno)
+ do_abort(
+ _("-o debug_bload_node_slack invalid parameter: %s\n"), strerror(errno));
break;
case NOQUOTA:
quotacheck_skip();
@@ -305,7 +325,11 @@ process_args(int argc, char **argv)
if (!val)
do_abort(
_("-c lazycount requires a parameter\n"));
+ errno = 0;
lazy_count = (int)strtol(val, NULL, 0);
+ if (errno)
+ do_abort(
+ _("-o lazycount invalid parameter: %s\n"), strerror(errno));
convert_lazy_count = 1;
break;
case CONVERT_INOBTCOUNT:
@@ -356,7 +380,11 @@ process_args(int argc, char **argv)
if (bhash_option_used)
do_abort(_("-m option cannot be used with "
"-o bhash option\n"));
+ errno = 0;
max_mem_specified = strtol(optarg, NULL, 0);
+ if (errno)
+ do_abort(
+ _("%s: invalid memory amount: %s\n"), optarg, strerror(errno));
break;
case 'L':
zap_log = 1;
@@ -377,7 +405,11 @@ process_args(int argc, char **argv)
do_prefetch = 0;
break;
case 't':
+ errno = 0;
report_interval = strtol(optarg, NULL, 0);
+ if (errno)
+ do_abort(
+ _("%s: invalid interval: %s\n"), optarg, strerror(errno));
break;
case 'e':
report_corrected = true;
@@ -397,8 +429,14 @@ process_args(int argc, char **argv)
usage();
p = getenv("XFS_REPAIR_FAIL_AFTER_PHASE");
- if (p)
+ if (p) {
+ errno = 0;
fail_after_phase = (int)strtol(p, NULL, 0);
+ if (errno)
+ do_abort(
+ _("%s: invalid phase in XFS_REPAIR_FAIL_AFTER_PHASE: %s\n"),
+ p, strerror(errno));
+ }
}
void __attribute__((noreturn))
--
2.45.2

@ -0,0 +1,110 @@
From fcac184ccf342a345ea8fe4d842415841af89e64 Mon Sep 17 00:00:00 2001
From: Andrey Albershteyn <aalbersh@redhat.com>
Date: Tue, 23 Apr 2024 14:36:15 +0200
Subject: [PATCH] xfs_repair: make duration take time_t
In most of the uses of duration() takes time_t instead of int.
Convert the rest to use time_t and make duration() take time_t to
not truncate it to int.
While at it remove unnecessary parentheses around 'elapsed'.
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
---
repair/globals.c | 2 +-
repair/globals.h | 2 +-
repair/progress.c | 9 +++++----
repair/progress.h | 2 +-
repair/xfs_repair.c | 2 +-
5 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/repair/globals.c b/repair/globals.c
index a68929bd..24f720c4 100644
--- a/repair/globals.c
+++ b/repair/globals.c
@@ -116,7 +116,7 @@ uint32_t sb_width;
struct aglock *ag_locks;
struct aglock rt_lock;
-int report_interval;
+time_t report_interval;
uint64_t *prog_rpt_done;
int ag_stride;
diff --git a/repair/globals.h b/repair/globals.h
index a67e384a..b83a8ae6 100644
--- a/repair/globals.h
+++ b/repair/globals.h
@@ -160,7 +160,7 @@ struct aglock {
extern struct aglock *ag_locks;
extern struct aglock rt_lock;
-extern int report_interval;
+extern time_t report_interval;
extern uint64_t *prog_rpt_done;
extern int ag_stride;
diff --git a/repair/progress.c b/repair/progress.c
index f6c4d988..2ce36cef 100644
--- a/repair/progress.c
+++ b/repair/progress.c
@@ -265,15 +265,16 @@ progress_rpt_thread (void *p)
(current_phase == 7))) {
/* for inode phase report % complete */
do_log(
- _("\t- %02d:%02d:%02d: Phase %d: elapsed time %s - processed %d %s per minute\n"),
+ _("\t- %02d:%02d:%02d: Phase %d: elapsed time %s - processed %ld %s per minute\n"),
tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
current_phase, duration(elapsed, msgbuf),
- (int) (60*sum/(elapsed)), *msgp->format->type);
+ 60 * sum / elapsed, *msgp->format->type);
do_log(
_("\t- %02d:%02d:%02d: Phase %d: %" PRIu64 "%% done - estimated remaining time %s\n"),
tmp->tm_hour, tmp->tm_min, tmp->tm_sec,
current_phase, percent,
- duration((int) ((*msgp->total - sum) * (elapsed)/sum), msgbuf));
+ duration((*msgp->total - sum) * elapsed / sum,
+ msgbuf));
}
if (pthread_mutex_unlock(&msgp->mutex) != 0) {
@@ -420,7 +421,7 @@ timestamp(int end, int phase, char *buf)
}
char *
-duration(int length, char *buf)
+duration(time_t length, char *buf)
{
int sum;
int weeks;
diff --git a/repair/progress.h b/repair/progress.h
index 2c1690db..9575df16 100644
--- a/repair/progress.h
+++ b/repair/progress.h
@@ -38,7 +38,7 @@ extern void summary_report(void);
extern int set_progress_msg(int report, uint64_t total);
extern uint64_t print_final_rpt(void);
extern char *timestamp(int end, int phase, char *buf);
-extern char *duration(int val, char *buf);
+extern char *duration(time_t val, char *buf);
extern int do_parallel;
#define PROG_RPT_INC(a,b) if (ag_stride && prog_rpt_done) (a) += (b)
diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c
index ba9d2833..2ceea87d 100644
--- a/repair/xfs_repair.c
+++ b/repair/xfs_repair.c
@@ -377,7 +377,7 @@ process_args(int argc, char **argv)
do_prefetch = 0;
break;
case 't':
- report_interval = (int)strtol(optarg, NULL, 0);
+ report_interval = strtol(optarg, NULL, 0);
break;
case 'e':
report_corrected = true;
--
2.45.2

@ -0,0 +1,43 @@
From c4dd920b8a8900046e0785e55a43c7190b82c59a Mon Sep 17 00:00:00 2001
From: Andrey Albershteyn <aalbersh@redhat.com>
Date: Tue, 23 Apr 2024 14:36:16 +0200
Subject: [PATCH] xfs_scrub: don't call phase_end if phase_rusage was not
initialized
If unicrash_load() fails, all_pi can be used uninitialized in
phase_end(). Fix it by going to the unload: section if unicrash_load
fails and just go with unicrash_unload() (the is_service won't be
initialized here).
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Bill O'Donnell <bodonnel@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
---
scrub/xfs_scrub.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/scrub/xfs_scrub.c b/scrub/xfs_scrub.c
index 752180d6..50565857 100644
--- a/scrub/xfs_scrub.c
+++ b/scrub/xfs_scrub.c
@@ -631,7 +631,7 @@ main(
fprintf(stderr,
_("%s: couldn't initialize Unicode library.\n"),
progname);
- goto out;
+ goto out_unicrash;
}
pthread_mutex_init(&ctx.lock, NULL);
@@ -828,6 +828,7 @@ out:
phase_end(&all_pi, 0);
if (progress_fp)
fclose(progress_fp);
+out_unicrash:
unicrash_unload();
/*
--
2.45.2

@ -0,0 +1,80 @@
From 5a43a00432ebe9ab8b54155703a9eb9e1a1dd4ec Mon Sep 17 00:00:00 2001
From: "Darrick J. Wong" <djwong@kernel.org>
Date: Mon, 29 Jul 2024 16:23:31 -0700
Subject: [PATCH] xfs_repair: allow symlinks with short remote targets
Symbolic links can have extended attributes. If the attr fork consumes
enough space in the inode record, a shortform symlink can become a
remote symlink. However, if we delete those extended attributes, the
target is not moved back into the inode core.
IOWs, we can end up with a symlink inode that looks like this:
core.magic = 0x494e
core.mode = 0120777
core.version = 3
core.format = 2 (extents)
core.nlinkv2 = 1
core.nextents = 1
core.size = 297
core.nblocks = 1
core.naextents = 0
core.forkoff = 0
core.aformat = 2 (extents)
u3.bmx[0] = [startoff,startblock,blockcount,extentflag]
0:[0,12,1,0]
This is a symbolic link with a 297-byte target stored in a disk block,
which is to say this is a symlink with a remote target. The forkoff is
0, which is to say that there's 512 - 176 == 336 bytes in the inode core
to store the data fork.
Prior to kernel commit 1eb70f54c445f, the kernel was ok with this
arrangement, but the change to symlink validation in that patch now
produces corruption errors on filesystems written by older kernels that
are not otherwise inconsistent. Those changes were inspired by reports
of illegal memory accesses, which I think were a result of making data
fork access decisions based on symlink di_size and not on di_format.
Unfortunately, for a very long time xfs_repair has flagged these inodes
as being corrupt, even though the kernel has historically been willing
to read and write symlinks with these properties. Resolve the conflict
by adjusting the xfs_repair corruption tests to allow extents format.
This change matches the kernel patch "xfs: allow symlinks with short
remote targets".
While we're at it, fix a lurking bad symlink fork access.
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Pavel Reichl <preichl@redhat.com>
---
repair/dinode.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/repair/dinode.c b/repair/dinode.c
index 168cbf48..e36de9bf 100644
--- a/repair/dinode.c
+++ b/repair/dinode.c
@@ -1036,7 +1036,8 @@ process_symlink_extlist(
int max_blocks;
if (be64_to_cpu(dino->di_size) <= XFS_DFORK_DSIZE(dino, mp)) {
- if (dino->di_format == XFS_DINODE_FMT_LOCAL)
+ if (dino->di_format == XFS_DINODE_FMT_LOCAL ||
+ dino->di_format == XFS_DINODE_FMT_EXTENTS)
return 0;
do_warn(
_("mismatch between format (%d) and size (%" PRId64 ") in symlink ino %" PRIu64 "\n"),
@@ -1368,7 +1369,7 @@ process_symlink(
* get symlink contents into data area
*/
symlink = &data[0];
- if (be64_to_cpu(dino->di_size) <= XFS_DFORK_DSIZE(dino, mp)) {
+ if (dino->di_format == XFS_DINODE_FMT_LOCAL) {
/*
* local symlink, just copy the symlink out of the
* inode into the data area
--
2.46.0

@ -0,0 +1,25 @@
jdm_parentpaths() doesn't initialize count. If count happens to be
non-zero, following loop can result in access overflow.
Signed-off-by: Andrey Albershteyn <aalbersh@redhat.com>
---
io/parent.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/io/parent.c b/io/parent.c
index 8f63607ffec2..5750d98a3b75 100644
--- a/io/parent.c
+++ b/io/parent.c
@@ -112,7 +112,7 @@ check_parents(parent_t *parentbuf, size_t *parentbuf_size,
jdm_fshandle_t *fshandlep, struct xfs_bstat *statp)
{
int error, i;
- __u32 count;
+ __u32 count = 0;
parent_t *entryp;
do {
--
2.42.0

@ -1,7 +1,7 @@
Summary: Utilities for managing the XFS filesystem
Name: xfsprogs
Version: 6.3.0
Release: 1%{?dist}
Version: 6.4.0
Release: 4%{?dist}
License: GPL+ and LGPLv2+
URL: https://xfs.wiki.kernel.org
Source0: http://kernel.org/pub/linux/utils/fs/xfs/xfsprogs/%{name}-%{version}.tar.xz
@ -26,17 +26,19 @@ Suggests: xfsprogs-xfs_scrub
Patch0: xfsprogs-rhelonly-disable-old-kernel-bigtime-inobtcnt-on.patch
Patch1: xfsprogs-rhelonly-example-conf.patch
Patch2: xfsprogs-rhelonly-mkfs-tolerate-tiny-filesystems.patch
Patch3: xfsprogs-rhelonly-xfs_quota-fix-missing-mount-point-warning.patch
Patch4: xfsprogs-6.4.0-set-bnobt-cntbt-numrecs-correctly-when-formattin.patch
Patch5: xfsprogs-6.4.0-mkfs-fix-man-s-default-value-for-sparse-option.patch
Patch6: xfsprogs-6.4.0-xfs_repair-don-t-add-junked-entries-to-the-rebuilt-d.patch
Patch7: xfsprogs-6.4.0-xfs_repair-fix-messaging-when-fixing-imap-due-to-spa.patch
Patch8: xfsprogs-6.4.0-xfs_repair-don-t-spray-correcting-imap-all-by-itself.patch
Patch9: xfsprogs-6.4.0-xfs_repair-fix-messaging-when-shortform_dir2_junk-is.patch
Patch10: xfsprogs-6.4.0-xfs_db-move-obfuscate_name-assertion-to-callers.patch
Patch11: xfsprogs-6.4.0-xfs_db-fix-metadump-name-obfuscation-for-ascii-ci-fi.patch
Patch12: xfsprogs-6.5.0-mkfs.xfs.8-correction-on-mkfs.xfs-manpage-since-refl.patch
Patch13: xfsprogs-6.4.0-xfs-stabilize-the-dirent-name-transformation-functio.patch
Patch3: xfsprogs-rhelonly-upstream-v6.6.0-xfs_quota-fix-missing-mount-point-warning.patch
Patch4: xfsprogs-6.5.0-mkfs.xfs.8-correction-on-mkfs.xfs-manpage-since-refl.patch
Patch5: xfsprogs-6.5.0-xfs_db.xfs.8-xfs_db-fix-leak-in-flist_find_ftyp.patch
Patch6: xfsprogs-6.5.0-xfs_repair.xfs.8-xfs_repair-make-duration-take-time_t.patch
Patch7: xfsprogs-6.5.0-xfs_repair.xfs.8-xfs_scrub-don-t-call-phase_end-if-phase_rusage-was-n.patch
Patch8: xfsprogs-6.5.0-xfs_fsr.xfs.8-xfs_fsr-convert-fsrallfs-to-use-time_t-instead-of-in.patch
Patch9: xfsprogs-6.5.0-xfs_fsr.xfs.8-xfs_fsr-replace-atoi-with-strtol.patch
Patch10: xfsprogs-6.5.0-xfs_db.xfs.8-xfs_db-add-helper-for-flist_find_type-for-clearer-fi.patch
Patch11: xfsprogs-6.5.0-xfs_repair.xfs.8-xfs_repair-catch-strtol-errors.patch
Patch12: xfsprogs-rhelonly-xfs_db-fix-unitialized-variable-in-check_parents-function.patch
Patch13: xfsprogs-6.5.0-xfs.8-xfs-fix-bounds-check-in-xfs_defer_agfl_block.patch
# v6.9.0-270-g5a43a004: This patch is taken from the `for-next` branch.
Patch14: xfsprogs-for-next-xfs_repair-allow-symlinks-with-short-remote-targets.patch
%description
A set of commands to use the XFS filesystem, including mkfs.xfs.
@ -148,6 +150,47 @@ install -m 0644 %{SOURCE3} %{buildroot}%{mkfsdir}
%{_libdir}/*.so
%changelog
* Thu Aug 15 2024 Pavel Reichl <preichl@redhat.com> - 6.4.0-4
- xfs_repair: allow symlinks with short remote targets
- Related: RHEL-54306 and RHEL-53164
* Thu Jul 11 2024 Bill O'Donnell <bodonnel@redhat.com> - 6.4.0-3
- Fix coverity issue
- Related: RHEL-39449
- Following is the patch list:
- xfsprogs-6.5.0-xfs.8-xfs-fix-bounds-check-in-xfs_defer_agfl_block.patch
* Wed Jun 26 2024 Bill O'Donnell <bodonnel@redhat.com> - 6.4.0-2
- Fix various CVE issues.
- Related: RHEL-32996
- Following is the patch list:
- xfsprogs-6.5.0-xfs_db.xfs.8-xfs_db-fix-leak-in-flist_find_ftyp.patch
- xfsprogs-6.5.0-xfs_repair.xfs.8-xfs_repair-make-duration-take-time_t.patch
- xfsprogs-6.5.0-xfs_repair.xfs.8-xfs_scrub-don-t-call-phase_end-if-phase_rusage-was-n.patch
- xfsprogs-6.5.0-xfs_fsr.xfs.8-xfs_fsr-convert-fsrallfs-to-use-time_t-instead-of-in.patch
- xfsprogs-6.5.0-xfs_fsr.xfs.8-xfs_fsr-replace-atoi-with-strtol.patch
- xfsprogs-6.5.0-xfs_db.xfs.8-xfs_db-add-helper-for-flist_find_type-for-clearer-fi.patch
- xfsprogs-6.5.0-xfs_repair.xfs.8-xfs_repair-catch-strtol-errors.patch
- xfsprogs-rhelonly-xfs_db-fix-unitialized-variable-in-check_parents-function.patch
* Mon May 20 2024 Pavel Reichl <preichl@redhat.com> - 6.4.0-1
- Rebase to a more recent upstream release
- Related: RHEL-28339
- Following is a list of dropped backported patches which
- are contained in the current rebase:
- xfsprogs-6.4.0-set-bnobt-cntbt-numrecs-correctly-when-formattin.patch
- xfsprogs-6.4.0-mkfs-fix-man-s-default-value-for-sparse-option.patch
- xfsprogs-6.4.0-xfs_repair-don-t-add-junked-entries-to-the-rebuilt-d.patch
- xfsprogs-6.4.0-xfs_repair-fix-messaging-when-fixing-imap-due-to-spa.patch
- xfsprogs-6.4.0-xfs_repair-don-t-spray-correcting-imap-all-by-itself.patch
- xfsprogs-6.4.0-xfs_repair-fix-messaging-when-shortform_dir2_junk-is.patch
- xfsprogs-6.4.0-xfs_db-move-obfuscate_name-assertion-to-callers.patch
- xfsprogs-6.4.0-xfs_db-fix-metadump-name-obfuscation-for-ascii-ci-fi.patch
- xfsprogs-6.4.0-xfs-stabilize-the-dirent-name-transformation-functio.patch
-
- Rename xfs_quota-fix-missing-mount-point-warning.patch to reflect upstream
- version it was merged in.
* Mon Nov 13 2023 Pavel Reichl <preichl@redhat.com> - 6.3.0-1
- Rebase to upstream version 6.3.0
-

Loading…
Cancel
Save