* Tue Feb 03 2026 Andrew Price <anprice@redhat.com> - 3.5.1-3
- gfs2_edit: Use 0x notation when printing hexadecimal values - libgfs2: Add a function to look up flags by symbol - gfs2_edit: Allow setting flags fields using symbols - gfs2_edit: Only call ioctl(BLKFLSBUF) on block devices - libgfs2: Fall back to printing a numerical value in lgfs2_field_str() - gfs2_edit: Set errno for invalid flag arguments in process_field() - libgfs2: Use '|' as the flag separator in lgfs2_field_str() - gfs2_edit: Print a better error message for missing path Resolves: RHEL-132202 - fsck.gfs2: Fix rebuilding bad 'system' inodes Resolves: RHEL-143418
This commit is contained in:
parent
1d17e1fc2a
commit
77ca5b65dc
@ -0,0 +1,45 @@
|
||||
commit 83ded388446e7422715196b2f470f1169d130311
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Mon Dec 1 14:39:30 2025 +0000
|
||||
|
||||
gfs2_edit: Use 0x notation when printing hexadecimal values
|
||||
|
||||
Changes the output of gfs2_edit -x for struct fields and log header
|
||||
flags.
|
||||
|
||||
Resolves: RHEL-132202
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c
|
||||
index 5d8811a6..82f5d3a8 100644
|
||||
--- a/gfs2/libgfs2/meta.c
|
||||
+++ b/gfs2/libgfs2/meta.c
|
||||
@@ -887,7 +887,7 @@ int lgfs2_field_str(char *str, const size_t size, const char *blk, const struct
|
||||
}
|
||||
|
||||
if (hex) {
|
||||
- snprintf(str, size, "%"PRIx64, value);
|
||||
+ snprintf(str, size, "0x%"PRIx64, value);
|
||||
goto out;
|
||||
}
|
||||
if (field->flags & LGFS2_MFF_MASK) {
|
||||
diff --git a/tests/mkfs.at b/tests/mkfs.at
|
||||
index 7064a9e2..9c93c80f 100644
|
||||
--- a/tests/mkfs.at
|
||||
+++ b/tests/mkfs.at
|
||||
@@ -206,11 +206,11 @@ AT_CHECK([$GFS_MKFS -p lock_nolock -o root_inherit_jdata= $GFS_TGT], 255, [ignor
|
||||
AT_CHECK([$GFS_MKFS -p lock_nolock -o root_inherit_jdata=42 $GFS_TGT], 255, [ignore], [ignore])
|
||||
AT_CHECK([$GFS_MKFS -p lock_nolock -o root_inherit_jdata=X $GFS_TGT], 255, [ignore], [ignore])
|
||||
AT_CHECK([$GFS_MKFS -p lock_nolock -o root_inherit_jdata $GFS_TGT], 0, [ignore], [ignore])
|
||||
-AT_CHECK([gfs2_edit -x -p root field di_flags $GFS_TGT | tr -d '\n'], 0, [80000001], [ignore])
|
||||
+AT_CHECK([gfs2_edit -x -p root field di_flags $GFS_TGT | tr -d '\n'], 0, [0x80000001], [ignore])
|
||||
AT_CHECK([$GFS_MKFS -p lock_nolock -o root_inherit_jdata=1 $GFS_TGT], 0, [ignore], [ignore])
|
||||
-AT_CHECK([gfs2_edit -x -p root field di_flags $GFS_TGT | tr -d '\n'], 0, [80000001], [ignore])
|
||||
+AT_CHECK([gfs2_edit -x -p root field di_flags $GFS_TGT | tr -d '\n'], 0, [0x80000001], [ignore])
|
||||
AT_CHECK([$GFS_MKFS -p lock_nolock -o root_inherit_jdata=0 $GFS_TGT], 0, [ignore], [ignore])
|
||||
-AT_CHECK([gfs2_edit -x -p root field di_flags $GFS_TGT | tr -d '\n'], 0, [1], [ignore])
|
||||
+AT_CHECK([gfs2_edit -x -p root field di_flags $GFS_TGT | tr -d '\n'], 0, [0x1], [ignore])
|
||||
AT_CHECK([$GFS_MKFS -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
|
||||
-AT_CHECK([gfs2_edit -x -p root field di_flags $GFS_TGT | tr -d '\n'], 0, [1], [ignore])
|
||||
+AT_CHECK([gfs2_edit -x -p root field di_flags $GFS_TGT | tr -d '\n'], 0, [0x1], [ignore])
|
||||
AT_CLEANUP
|
||||
@ -0,0 +1,98 @@
|
||||
commit 9179cb0f0bec09add0b64281bcd917e1869e3569
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Mon Dec 1 15:51:54 2025 +0000
|
||||
|
||||
libgfs2: Add a function to look up flags by symbol
|
||||
|
||||
Add lgfs2_flag_sym_value() to simplify parsing of flag values from
|
||||
strings.
|
||||
|
||||
Resolves: RHEL-132202
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/libgfs2/check_meta.c b/gfs2/libgfs2/check_meta.c
|
||||
index 340d3c8d..8e448203 100644
|
||||
--- a/gfs2/libgfs2/check_meta.c
|
||||
+++ b/gfs2/libgfs2/check_meta.c
|
||||
@@ -38,6 +38,30 @@ START_TEST(check_symtab)
|
||||
}
|
||||
END_TEST
|
||||
|
||||
+START_TEST(check_flag_sym_value)
|
||||
+{
|
||||
+ const struct lgfs2_metadata *di_meta = &lgfs2_metadata[LGFS2_MT_GFS2_DINODE];
|
||||
+ const struct lgfs2_metafield *flags_field = lgfs2_find_mfield_name("di_flags", di_meta);
|
||||
+
|
||||
+ ck_assert(lgfs2_flag_sym_value(NULL, flags_field) == 0);
|
||||
+ ck_assert(lgfs2_flag_sym_value("", flags_field) == 0);
|
||||
+ ck_assert(lgfs2_flag_sym_value("invalid_flag", flags_field) == 0);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_JDATA", flags_field) == GFS2_DIF_JDATA);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_EXHASH", flags_field) == GFS2_DIF_EXHASH);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_UNUSED", flags_field) == GFS2_DIF_UNUSED);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_EA_INDIRECT", flags_field) == GFS2_DIF_EA_INDIRECT);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_DIRECTIO", flags_field) == GFS2_DIF_DIRECTIO);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_IMMUTABLE", flags_field) == GFS2_DIF_IMMUTABLE);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_APPENDONLY", flags_field) == GFS2_DIF_APPENDONLY);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_NOATIME", flags_field) == GFS2_DIF_NOATIME);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_SYNC", flags_field) == GFS2_DIF_SYNC);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_SYSTEM", flags_field) == GFS2_DIF_SYSTEM);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_TRUNC_IN_PROG", flags_field) == GFS2_DIF_TRUNC_IN_PROG);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_INHERIT_DIRECTIO", flags_field) == GFS2_DIF_INHERIT_DIRECTIO);
|
||||
+ ck_assert(lgfs2_flag_sym_value("GFS2_DIF_INHERIT_JDATA", flags_field) == GFS2_DIF_INHERIT_JDATA);
|
||||
+}
|
||||
+END_TEST
|
||||
+
|
||||
START_TEST(check_ptrs)
|
||||
{
|
||||
int i, j;
|
||||
@@ -64,6 +88,7 @@ Suite *suite_meta(void)
|
||||
tcase_add_test(tc_meta, check_metadata_sizes);
|
||||
tcase_add_test(tc_meta, check_symtab);
|
||||
tcase_add_test(tc_meta, check_ptrs);
|
||||
+ tcase_add_test(tc_meta, check_flag_sym_value);
|
||||
suite_add_tcase(s, tc_meta);
|
||||
|
||||
return s;
|
||||
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
|
||||
index 7531a2d6..abe9944e 100644
|
||||
--- a/gfs2/libgfs2/libgfs2.h
|
||||
+++ b/gfs2/libgfs2/libgfs2.h
|
||||
@@ -452,6 +452,7 @@ extern const struct lgfs2_metadata *lgfs2_find_mtype(uint32_t mh_type, const uns
|
||||
extern const struct lgfs2_metadata *lgfs2_find_mtype_name(const char *name, const unsigned versions);
|
||||
extern const struct lgfs2_metafield *lgfs2_find_mfield_name(const char *name, const struct lgfs2_metadata *mtype);
|
||||
extern int lgfs2_field_str(char *str, const size_t size, const char *blk, const struct lgfs2_metafield *field, int hex);
|
||||
+extern uint32_t lgfs2_flag_sym_value(const char *sym, const struct lgfs2_metafield *field);
|
||||
extern int lgfs2_field_assign(char *blk, const struct lgfs2_metafield *field, const void *val);
|
||||
|
||||
/* buf.c */
|
||||
diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c
|
||||
index 82f5d3a8..3b313ad2 100644
|
||||
--- a/gfs2/libgfs2/meta.c
|
||||
+++ b/gfs2/libgfs2/meta.c
|
||||
@@ -922,6 +922,26 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * Look up a flag value from a symbolic name. Matching is case-sensitive.
|
||||
+ * Does not parse combined symbols like "X|Y".
|
||||
+ * sym: the symbolic name
|
||||
+ * field: the flags field the name relates to.
|
||||
+ * Returns the flag value or 0 if not found.
|
||||
+ */
|
||||
+uint32_t lgfs2_flag_sym_value(const char *sym, const struct lgfs2_metafield *field)
|
||||
+{
|
||||
+ if (sym == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ for (unsigned i = 0; i < field->nsyms; i++)
|
||||
+ {
|
||||
+ if (strcmp(sym, field->symtab[i].value) == 0)
|
||||
+ return field->symtab[i].key;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int lgfs2_field_assign(char *blk, const struct lgfs2_metafield *field, const void *val)
|
||||
{
|
||||
char *fieldp = blk + field->offset;
|
||||
@ -0,0 +1,95 @@
|
||||
commit 67b9d9a2f1380a8db1bcb963b18cdd00550c76b9
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Mon Dec 1 19:30:29 2025 +0000
|
||||
|
||||
gfs2_edit: Allow setting flags fields using symbols
|
||||
|
||||
Parse combinations of symbolic flags to set flags fields.
|
||||
|
||||
The separator is chosen to be '|' as it's consistent with C. It has the
|
||||
drawback of needing to be escaped in command lines but unfortunately the
|
||||
argument parsing code treats anything with '/' as a path so the
|
||||
separator used in output cannot be used. Adding a third separator would
|
||||
be even more confusing.
|
||||
|
||||
Resolves: RHEL-132202
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
|
||||
index ccce0fd0..821b9a02 100644
|
||||
--- a/gfs2/edit/hexedit.c
|
||||
+++ b/gfs2/edit/hexedit.c
|
||||
@@ -1689,6 +1689,38 @@ static void find_change_block_alloc(int *newval)
|
||||
exit(0);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * Parse a string like "GFS2_DIF_SYSTEM|GFS2_DIF_JDATA" into the corresponding
|
||||
+ * value for a bitmask field.
|
||||
+ * syms: The string.
|
||||
+ * field: The field type.
|
||||
+ * Returns the values for the specified flags ORed together or 0 on failure.
|
||||
+ */
|
||||
+static uint32_t flag_syms_value(const char *syms, const struct lgfs2_metafield *field)
|
||||
+{
|
||||
+ char *str, *iter, *tok;
|
||||
+ uint32_t val = 0;
|
||||
+
|
||||
+ if (syms == NULL || *syms == '\0')
|
||||
+ return 0;
|
||||
+
|
||||
+ str = iter = strdup(syms);
|
||||
+ if (str == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ while ((tok = strsep(&iter, "|"))) {
|
||||
+ uint32_t flag = lgfs2_flag_sym_value(tok, field);
|
||||
+
|
||||
+ if (flag == 0) {
|
||||
+ free(str);
|
||||
+ return 0;
|
||||
+ }
|
||||
+ val |= flag;
|
||||
+ }
|
||||
+ free(str);
|
||||
+ return val;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* process request to print a certain field from a previously pushed block
|
||||
*/
|
||||
@@ -1720,7 +1752,13 @@ static void process_field(const char *field, const char *nstr)
|
||||
err = lgfs2_field_assign(rbh->b_data, mfield, nstr);
|
||||
} else {
|
||||
uint64_t val = 0;
|
||||
- err = sscanf(nstr, "%"SCNi64, &val);
|
||||
+
|
||||
+ if (mfield->flags & LGFS2_MFF_MASK) {
|
||||
+ val = flag_syms_value(nstr, mfield);
|
||||
+ err = 1;
|
||||
+ }
|
||||
+ if (val == 0)
|
||||
+ err = sscanf(nstr, "%"SCNi64, &val);
|
||||
if (err == 1)
|
||||
/* coverity[overrun-buffer-val:SUPPRESS] False positive */
|
||||
err = lgfs2_field_assign(rbh->b_data, mfield, &val);
|
||||
diff --git a/tests/edit.at b/tests/edit.at
|
||||
index 29835df0..bc3dc28b 100644
|
||||
--- a/tests/edit.at
|
||||
+++ b/tests/edit.at
|
||||
@@ -71,3 +71,15 @@ AT_CHECK([truncate -s 10K test.file], 0, [ignore], [ignore])
|
||||
AT_CHECK([gfs2_edit restoremeta test.meta test.file], 0, [ignore], [ignore])
|
||||
AT_CHECK([fsck.gfs2 -n test.file], 0, [ignore], [ignore])
|
||||
AT_CLEANUP
|
||||
+
|
||||
+AT_SETUP([Set flags by symbol])
|
||||
+AT_KEYWORDS(gfs2_edit edit)
|
||||
+GFS_TGT_REGEN
|
||||
+AT_CHECK([$GFS_MKFS -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p journal0 field di_flags invalid_flag $GFS_TGT], 1, [ignore], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p journal0 field di_flags 'GFS2_DIF_SYSTEM' $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_SYSTEM], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p journal0 field di_flags 'GFS2_DIF_SYSTEM|GFS2_DIF_JDATA' $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_JDATA/GFS2_DIF_SYSTEM], [ignore])
|
||||
+AT_CHECK([gfs2_edit -x -p journal0 field di_flags 'GFS2_DIF_SYSTEM|GFS2_DIF_JDATA' $GFS_TGT | tr -d '\n'], 0, [0x201], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p journal0 field di_flags $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_JDATA/GFS2_DIF_SYSTEM], [ignore])
|
||||
+AT_CHECK([gfs2_edit -x -p journal0 field di_flags $GFS_TGT | tr -d '\n'], 0, [0x201], [ignore])
|
||||
+AT_CLEANUP
|
||||
@ -0,0 +1,65 @@
|
||||
commit 45628f23874fb8f596f5e8368f4247f08b30703b
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Tue Dec 2 14:25:03 2025 +0000
|
||||
|
||||
gfs2_edit: Only call ioctl(BLKFLSBUF) on block devices
|
||||
|
||||
Prevents failures of these calls causing confusing error messages.
|
||||
|
||||
Resolves: RHEL-132202
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
|
||||
index 821b9a02..7e3a8a24 100644
|
||||
--- a/gfs2/edit/hexedit.c
|
||||
+++ b/gfs2/edit/hexedit.c
|
||||
@@ -42,6 +42,7 @@ static struct lgfs2_inum gfs1_license_di;
|
||||
|
||||
int details = 0;
|
||||
char *device = NULL;
|
||||
+struct stat devstat;
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* erase - clear the screen */
|
||||
@@ -872,7 +873,8 @@ static void read_superblock(int fd)
|
||||
{
|
||||
struct gfs2_meta_header *mh;
|
||||
|
||||
- ioctl(fd, BLKFLSBUF, 0);
|
||||
+ if (S_ISBLK(devstat.st_mode))
|
||||
+ ioctl(fd, BLKFLSBUF, 0);
|
||||
memset(&sbd, 0, sizeof(struct lgfs2_sbd));
|
||||
sbd.sd_bsize = LGFS2_DEFAULT_BSIZE;
|
||||
sbd.device_fd = fd;
|
||||
@@ -950,7 +952,8 @@ static int read_rindex(void)
|
||||
|
||||
static int read_master_dir(void)
|
||||
{
|
||||
- ioctl(sbd.device_fd, BLKFLSBUF, 0);
|
||||
+ if (S_ISBLK(devstat.st_mode))
|
||||
+ ioctl(sbd.device_fd, BLKFLSBUF, 0);
|
||||
|
||||
bh = lgfs2_bread(&sbd, sbd.sd_meta_dir.in_addr);
|
||||
if (bh == NULL)
|
||||
@@ -986,7 +989,8 @@ int display(int identify_only, int trunc_zeros, uint64_t flagref,
|
||||
if (bh != NULL)
|
||||
lgfs2_brelse(bh);
|
||||
dev_offset = blk * sbd.sd_bsize;
|
||||
- ioctl(sbd.device_fd, BLKFLSBUF, 0);
|
||||
+ if (S_ISBLK(devstat.st_mode))
|
||||
+ ioctl(sbd.device_fd, BLKFLSBUF, 0);
|
||||
if (!(bh = lgfs2_bread(&sbd, blk))) {
|
||||
fprintf(stderr, "read error: %s from %s:%d: "
|
||||
"offset %"PRIu64" (0x%"PRIx64")\n",
|
||||
@@ -2575,6 +2579,11 @@ int main(int argc, char *argv[])
|
||||
fprintf(stderr, "Failed to open '%s': %s\n", device, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
+ if (fstat(fd, &devstat) != 0) {
|
||||
+ fprintf(stderr, "Failed to fstat '%s': %s\n", device, strerror(errno));
|
||||
+ close(fd);
|
||||
+ exit(1);
|
||||
+ }
|
||||
max_block = lseek(fd, 0, SEEK_END) / sbd.sd_bsize;
|
||||
|
||||
read_superblock(fd);
|
||||
@ -0,0 +1,60 @@
|
||||
commit 18fcae907955e5d24ddd63c9f98aa28c2e92ab5c
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Tue Dec 2 17:06:31 2025 +0000
|
||||
|
||||
libgfs2: Fall back to printing a numerical value in lgfs2_field_str()
|
||||
|
||||
If the bitmask value isn't a valid combination of flags then
|
||||
lgfs2_field_str() currently leaves the resulting string empty. Fall back
|
||||
to setting the string to the numerical value instead.
|
||||
|
||||
Resolves: RHEL-132202
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c
|
||||
index 3b313ad2..8b93c0a0 100644
|
||||
--- a/gfs2/libgfs2/meta.c
|
||||
+++ b/gfs2/libgfs2/meta.c
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <stdint.h>
|
||||
+#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <uuid.h>
|
||||
#include "libgfs2.h"
|
||||
@@ -892,6 +893,7 @@ int lgfs2_field_str(char *str, const size_t size, const char *blk, const struct
|
||||
}
|
||||
if (field->flags & LGFS2_MFF_MASK) {
|
||||
char *s = str, *end = str + size;
|
||||
+ bool found = false;
|
||||
unsigned n;
|
||||
|
||||
for (n = 0; n < field->nsyms; n++) {
|
||||
@@ -899,6 +901,7 @@ int lgfs2_field_str(char *str, const size_t size, const char *blk, const struct
|
||||
|
||||
if (!(value & sym->key))
|
||||
continue;
|
||||
+ found = true;
|
||||
if (s != str && s < end)
|
||||
*s++ = '/';
|
||||
if (s < end) {
|
||||
@@ -913,7 +916,8 @@ int lgfs2_field_str(char *str, const size_t size, const char *blk, const struct
|
||||
}
|
||||
if (s < end)
|
||||
*s = '\0';
|
||||
- goto out;
|
||||
+ if (found)
|
||||
+ goto out;
|
||||
}
|
||||
snprintf(str, size, "%"PRIu64, value);
|
||||
}
|
||||
diff --git a/tests/edit.at b/tests/edit.at
|
||||
index bc3dc28b..22a60f04 100644
|
||||
--- a/tests/edit.at
|
||||
+++ b/tests/edit.at
|
||||
@@ -82,4 +82,6 @@ AT_CHECK([gfs2_edit -p journal0 field di_flags 'GFS2_DIF_SYSTEM|GFS2_DIF_JDATA'
|
||||
AT_CHECK([gfs2_edit -x -p journal0 field di_flags 'GFS2_DIF_SYSTEM|GFS2_DIF_JDATA' $GFS_TGT | tr -d '\n'], 0, [0x201], [ignore])
|
||||
AT_CHECK([gfs2_edit -p journal0 field di_flags $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_JDATA/GFS2_DIF_SYSTEM], [ignore])
|
||||
AT_CHECK([gfs2_edit -x -p journal0 field di_flags $GFS_TGT | tr -d '\n'], 0, [0x201], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p journal0 field di_flags 0 $GFS_TGT | tr -d '\n'], 0, [0], [ignore])
|
||||
+AT_CHECK([gfs2_edit -x -p journal0 field di_flags 0 $GFS_TGT | tr -d '\n'], 0, [0x0], [ignore])
|
||||
AT_CLEANUP
|
||||
@ -0,0 +1,28 @@
|
||||
commit aa645d8035dcfbfb00d7ab5496019e8a04e56b61
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Tue Dec 2 17:52:46 2025 +0000
|
||||
|
||||
gfs2_edit: Set errno for invalid flag arguments in process_field()
|
||||
|
||||
sscanf() zeroes errno causing invalid flag arguments to be reported as
|
||||
|
||||
Could not set 'di_flags' to '': Success
|
||||
|
||||
Set errno to EINVAL to report validation failures in this section of
|
||||
process_field() sensibly.
|
||||
|
||||
Resolves: RHEL-132202
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
|
||||
index 7e3a8a24..2dc7d0a7 100644
|
||||
--- a/gfs2/edit/hexedit.c
|
||||
+++ b/gfs2/edit/hexedit.c
|
||||
@@ -1763,6 +1763,7 @@ static void process_field(const char *field, const char *nstr)
|
||||
}
|
||||
if (val == 0)
|
||||
err = sscanf(nstr, "%"SCNi64, &val);
|
||||
+ errno = EINVAL;
|
||||
if (err == 1)
|
||||
/* coverity[overrun-buffer-val:SUPPRESS] False positive */
|
||||
err = lgfs2_field_assign(rbh->b_data, mfield, &val);
|
||||
@ -0,0 +1,40 @@
|
||||
commit a83d4311da206711c3368c6be555c6ac16cb64e5
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Wed Dec 3 15:44:56 2025 +0000
|
||||
|
||||
libgfs2: Use '|' as the flag separator in lgfs2_field_str()
|
||||
|
||||
To make gfs2_edit's output consistent with its expected input.
|
||||
|
||||
Resolves: RHEL-132202
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/libgfs2/meta.c b/gfs2/libgfs2/meta.c
|
||||
index 8b93c0a0..9fb43e05 100644
|
||||
--- a/gfs2/libgfs2/meta.c
|
||||
+++ b/gfs2/libgfs2/meta.c
|
||||
@@ -903,7 +903,7 @@ int lgfs2_field_str(char *str, const size_t size, const char *blk, const struct
|
||||
continue;
|
||||
found = true;
|
||||
if (s != str && s < end)
|
||||
- *s++ = '/';
|
||||
+ *s++ = '|';
|
||||
if (s < end) {
|
||||
const char *v = sym->value + sym->prefix;
|
||||
size_t len = strlen(v);
|
||||
diff --git a/tests/edit.at b/tests/edit.at
|
||||
index 22a60f04..7aeaf70a 100644
|
||||
--- a/tests/edit.at
|
||||
+++ b/tests/edit.at
|
||||
@@ -78,9 +78,9 @@ GFS_TGT_REGEN
|
||||
AT_CHECK([$GFS_MKFS -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
|
||||
AT_CHECK([gfs2_edit -p journal0 field di_flags invalid_flag $GFS_TGT], 1, [ignore], [ignore])
|
||||
AT_CHECK([gfs2_edit -p journal0 field di_flags 'GFS2_DIF_SYSTEM' $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_SYSTEM], [ignore])
|
||||
-AT_CHECK([gfs2_edit -p journal0 field di_flags 'GFS2_DIF_SYSTEM|GFS2_DIF_JDATA' $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_JDATA/GFS2_DIF_SYSTEM], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p journal0 field di_flags 'GFS2_DIF_SYSTEM|GFS2_DIF_JDATA' $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_JDATA|GFS2_DIF_SYSTEM], [ignore])
|
||||
AT_CHECK([gfs2_edit -x -p journal0 field di_flags 'GFS2_DIF_SYSTEM|GFS2_DIF_JDATA' $GFS_TGT | tr -d '\n'], 0, [0x201], [ignore])
|
||||
-AT_CHECK([gfs2_edit -p journal0 field di_flags $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_JDATA/GFS2_DIF_SYSTEM], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p journal0 field di_flags $GFS_TGT | tr -d '\n'], 0, [GFS2_DIF_JDATA|GFS2_DIF_SYSTEM], [ignore])
|
||||
AT_CHECK([gfs2_edit -x -p journal0 field di_flags $GFS_TGT | tr -d '\n'], 0, [0x201], [ignore])
|
||||
AT_CHECK([gfs2_edit -p journal0 field di_flags 0 $GFS_TGT | tr -d '\n'], 0, [0], [ignore])
|
||||
AT_CHECK([gfs2_edit -x -p journal0 field di_flags 0 $GFS_TGT | tr -d '\n'], 0, [0x0], [ignore])
|
||||
@ -0,0 +1,28 @@
|
||||
commit 3defe7201255961dc82720069a2b901ba3c6498a
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Wed Dec 3 16:02:22 2025 +0000
|
||||
|
||||
gfs2_edit: Print a better error message for missing path
|
||||
|
||||
If gfs2_edit fails to parse the device path from argv it still passes
|
||||
the device variable to open(2) which results in a "Bad address" error
|
||||
message. Catch a NULL or empty path and report it as a missing path.
|
||||
|
||||
Resolves: RHEL-132202
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
|
||||
index 2dc7d0a7..19b58ff9 100644
|
||||
--- a/gfs2/edit/hexedit.c
|
||||
+++ b/gfs2/edit/hexedit.c
|
||||
@@ -2575,6 +2575,10 @@ int main(int argc, char *argv[])
|
||||
if (dmode == INIT_MODE)
|
||||
dmode = HEX_MODE;
|
||||
|
||||
+ if (device == NULL || *device == '\0') {
|
||||
+ fprintf(stderr, "No device path specified\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
fd = open(device, O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Failed to open '%s': %s\n", device, strerror(errno));
|
||||
137
RHEL-143418-fsck_gfs2_Fix_rebuilding_bad_system_inodes.patch
Normal file
137
RHEL-143418-fsck_gfs2_Fix_rebuilding_bad_system_inodes.patch
Normal file
@ -0,0 +1,137 @@
|
||||
commit d1392bb22bae2d82b589aefb267be93c22576bff
|
||||
Author: Andrew Price <anprice@redhat.com>
|
||||
Date: Thu Jan 15 17:30:12 2026 +0000
|
||||
|
||||
fsck.gfs2: Fix rebuilding bad 'system' inodes
|
||||
|
||||
When these inodes are scribbled over, the fsck.gfs2 builder functions
|
||||
called by check_system_inode() don't rebuild them properly. Firstly,
|
||||
they free the rebuilt inode causing a subsequent segfault; and secondly
|
||||
they don't remove the directory entry before rebuilding, causing the
|
||||
lgfs2_createi() call used by libgfs2 builder functions to just return
|
||||
the existing broken inode. Fix these two issues in each of the system
|
||||
inode builder functions.
|
||||
|
||||
Resolves: RHEL-143418
|
||||
Signed-off-by: Andrew Price <anprice@redhat.com>
|
||||
|
||||
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
|
||||
index 206929fc..49f51f53 100644
|
||||
--- a/gfs2/fsck/pass1.c
|
||||
+++ b/gfs2/fsck/pass1.c
|
||||
@@ -1465,6 +1465,8 @@ static int check_system_inode(struct fsck_cx *cx,
|
||||
if (query(cx, _("Create new %s system inode? (y/n) "), filename)) {
|
||||
log_err( _("Rebuilding system file \"%s\"\n"),
|
||||
filename);
|
||||
+ lgfs2_inode_free(sysinode);
|
||||
+ lgfs2_dirent_del(sysdir, filename, strlen(filename));
|
||||
error = builder(cx->sdp);
|
||||
if (error || *sysinode == NULL) {
|
||||
log_err( _("Error rebuilding system "
|
||||
@@ -1581,8 +1583,8 @@ static int build_inum(struct lgfs2_sbd *sdp)
|
||||
struct lgfs2_inode *ip = lgfs2_build_inum(sdp);
|
||||
if (ip == NULL)
|
||||
return -1;
|
||||
- lgfs2_inode_put(&ip);
|
||||
- return 0;
|
||||
+ sdp->md.inum = ip;
|
||||
+ return lgfs2_init_inum(sdp);
|
||||
}
|
||||
|
||||
static int build_statfs(struct lgfs2_sbd *sdp)
|
||||
@@ -1590,8 +1592,8 @@ static int build_statfs(struct lgfs2_sbd *sdp)
|
||||
struct lgfs2_inode *ip = lgfs2_build_statfs(sdp);
|
||||
if (ip == NULL)
|
||||
return -1;
|
||||
- lgfs2_inode_put(&ip);
|
||||
- return 0;
|
||||
+ sdp->md.statfs = ip;
|
||||
+ return lgfs2_init_statfs(sdp, NULL);
|
||||
}
|
||||
|
||||
static int build_rindex(struct lgfs2_sbd *sdp)
|
||||
@@ -1599,8 +1601,9 @@ static int build_rindex(struct lgfs2_sbd *sdp)
|
||||
struct lgfs2_inode *ip = lgfs2_build_rindex(sdp);
|
||||
if (ip == NULL)
|
||||
return -1;
|
||||
- lgfs2_inode_put(&ip);
|
||||
- return 0;
|
||||
+ sdp->md.riinode = ip;
|
||||
+ lgfs2_dinode_out(ip, ip->i_bh->b_data);
|
||||
+ return lgfs2_bwrite(ip->i_bh);
|
||||
}
|
||||
|
||||
static int build_quota(struct lgfs2_sbd *sdp)
|
||||
@@ -1608,8 +1611,9 @@ static int build_quota(struct lgfs2_sbd *sdp)
|
||||
struct lgfs2_inode *ip = lgfs2_build_quota(sdp);
|
||||
if (ip == NULL)
|
||||
return -1;
|
||||
- lgfs2_inode_put(&ip);
|
||||
- return 0;
|
||||
+ sdp->md.qinode = ip;
|
||||
+ lgfs2_dinode_out(ip, ip->i_bh->b_data);
|
||||
+ return lgfs2_bwrite(ip->i_bh);
|
||||
}
|
||||
|
||||
static int check_system_inodes(struct fsck_cx *cx)
|
||||
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
|
||||
index ba9434af..2f6b2828 100644
|
||||
--- a/gfs2/libgfs2/fs_ops.c
|
||||
+++ b/gfs2/libgfs2/fs_ops.c
|
||||
@@ -115,7 +115,8 @@ void lgfs2_inode_free(struct lgfs2_inode **ipp)
|
||||
{
|
||||
struct lgfs2_inode *ip = *ipp;
|
||||
|
||||
- free(ip->i_bh);
|
||||
+ if (ip)
|
||||
+ free(ip->i_bh);
|
||||
free(ip);
|
||||
*ipp = NULL;
|
||||
}
|
||||
diff --git a/tests/fsck.at b/tests/fsck.at
|
||||
index 538d41ad..c860d432 100644
|
||||
--- a/tests/fsck.at
|
||||
+++ b/tests/fsck.at
|
||||
@@ -75,6 +75,42 @@ AT_CHECK([fsck.gfs2 -y $GFS_TGT], 1, [ignore], [ignore])
|
||||
AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
|
||||
AT_CLEANUP
|
||||
|
||||
+AT_SETUP([Rebuild bad statfs])
|
||||
+AT_KEYWORDS(fsck.gfs2 fsck)
|
||||
+GFS_TGT_REGEN
|
||||
+AT_CHECK([mkfs.gfs2 -O -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p statfs field di_header.mh_magic 0 $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([fsck.gfs2 -y $GFS_TGT], 1, [ignore], [ignore])
|
||||
+AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
+AT_SETUP([Rebuild bad inum])
|
||||
+AT_KEYWORDS(fsck.gfs2 fsck)
|
||||
+GFS_TGT_REGEN
|
||||
+AT_CHECK([mkfs.gfs2 -O -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p inum field di_header.mh_magic 0 $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([fsck.gfs2 -y $GFS_TGT], 1, [ignore], [ignore])
|
||||
+AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
+AT_SETUP([Rebuild bad rindex])
|
||||
+AT_KEYWORDS(fsck.gfs2 fsck)
|
||||
+GFS_TGT_REGEN
|
||||
+AT_CHECK([mkfs.gfs2 -O -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p rindex field di_header.mh_magic 0 $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([fsck.gfs2 -y $GFS_TGT], 1, [ignore], [ignore])
|
||||
+AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
+AT_SETUP([Rebuild bad quota])
|
||||
+AT_KEYWORDS(fsck.gfs2 fsck)
|
||||
+GFS_TGT_REGEN
|
||||
+AT_CHECK([mkfs.gfs2 -O -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([gfs2_edit -p quota field di_header.mh_magic 0 $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CHECK([fsck.gfs2 -y $GFS_TGT], 1, [ignore], [ignore])
|
||||
+AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
AT_SETUP([gfs2 format versions])
|
||||
AT_KEYWORDS(fsck.gfs2 fsck)
|
||||
GFS_TGT_REGEN
|
||||
@ -1,6 +1,6 @@
|
||||
Name: gfs2-utils
|
||||
Version: 3.5.1
|
||||
Release: 2%{?dist}
|
||||
Release: 3%{?dist}
|
||||
License: GPLv2+ and LGPLv2+
|
||||
Summary: Utilities for managing the global file system (GFS2)
|
||||
%ifnarch %{arm}
|
||||
@ -22,6 +22,15 @@ BuildRequires: make
|
||||
Source: https://releases.pagure.org/gfs2-utils/gfs2-utils-%{version}.tar.gz
|
||||
URL: https://pagure.io/gfs2-utils
|
||||
Patch0: RHEL-26661-gfs2_edit_truncate_to_filesystem_size_at_end_of_restoremeta.patch
|
||||
Patch1: RHEL-132202-1-gfs2_edit_Use_0x_notation_when_printing_hexadecimal_values.patch
|
||||
Patch2: RHEL-132202-2-libgfs2_Add_a_function_to_look_up_flags_by_symbol.patch
|
||||
Patch3: RHEL-132202-3-gfs2_edit_Allow_setting_flags_fields_using_symbols.patch
|
||||
Patch4: RHEL-132202-4-gfs2_edit_Only_call_ioctl_BLKFLSBUF_on_block_devices.patch
|
||||
Patch5: RHEL-132202-5-libgfs2_Fall_back_to_printing_a_numerical_value_in_lgfs2_field_str.patch
|
||||
Patch6: RHEL-132202-6-gfs2_edit_Set_errno_for_invalid_flag_arguments_in_process_field.patch
|
||||
Patch7: RHEL-132202-7-libgfs2_Use_as_the_flag_separator_in_lgfs2_field_str.patch
|
||||
Patch8: RHEL-132202-8-gfs2_edit_Print_a_better_error_message_for_missing_path.patch
|
||||
Patch9: RHEL-143418-fsck_gfs2_Fix_rebuilding_bad_system_inodes.patch
|
||||
|
||||
%prep
|
||||
%autosetup -p1
|
||||
@ -64,6 +73,19 @@ modifying, and correcting inconsistencies in GFS2 file systems.
|
||||
%{_prefix}/lib/udev/rules.d/82-gfs2-withdraw.rules
|
||||
|
||||
%changelog
|
||||
* Tue Feb 03 2026 Andrew Price <anprice@redhat.com> - 3.5.1-3
|
||||
- gfs2_edit: Use 0x notation when printing hexadecimal values
|
||||
- libgfs2: Add a function to look up flags by symbol
|
||||
- gfs2_edit: Allow setting flags fields using symbols
|
||||
- gfs2_edit: Only call ioctl(BLKFLSBUF) on block devices
|
||||
- libgfs2: Fall back to printing a numerical value in lgfs2_field_str()
|
||||
- gfs2_edit: Set errno for invalid flag arguments in process_field()
|
||||
- libgfs2: Use '|' as the flag separator in lgfs2_field_str()
|
||||
- gfs2_edit: Print a better error message for missing path
|
||||
Resolves: RHEL-132202
|
||||
- fsck.gfs2: Fix rebuilding bad 'system' inodes
|
||||
Resolves: RHEL-143418
|
||||
|
||||
* Fri Jun 21 2024 Andrew Price <anprice@redhat.com> - 3.5.1-2
|
||||
- gfs2_edit: truncate to filesystem size at end of restoremeta()
|
||||
Resolves: RHEL-26661
|
||||
|
||||
Loading…
Reference in New Issue
Block a user