* 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
- Update tests/testsuite
This commit is contained in:
Andrew Price 2024-06-21 16:46:11 +01:00
parent 6e67c1e1df
commit 1d17e1fc2a
3 changed files with 235 additions and 22 deletions

View File

@ -0,0 +1,111 @@
commit f837169ab53dc915e10bdb480eaeb5bbb52c0c09
Author: Paul Evans <pevans@redhat.com>
Date: Wed Mar 6 12:28:16 2024 +0000
gfs2_edit: truncate to filesystem size at end of restoremeta()
Truncate to metadata header's filesystem size at the end of restore if
a header is present.
Resolves: RHEL-26661
Signed-off-by: Paul Evans <pevans@redhat.com>
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index 4ee76be0..f5448974 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -1327,9 +1327,8 @@ static void restoremeta_usage(void)
fprintf(stderr, "gfs2_edit restoremeta <metadata_file> <block_device>\n");
}
-static int restore_init(const char *path, struct metafd *mfd, int printonly)
+static int restore_init(const char *path, struct metafd *mfd, struct savemeta *sm, int printonly)
{
- struct savemeta sm = {0};
struct gfs2_sb rsb;
uint16_t sb_siglen;
char *end;
@@ -1357,7 +1356,7 @@ static int restore_init(const char *path, struct metafd *mfd, int printonly)
return -1;
}
bp = restore_buf;
- ret = parse_header(bp, &sm);
+ ret = parse_header(bp, sm);
if (ret == 0) {
bp = restore_buf + sizeof(struct savemeta_header);
restore_off = sizeof(struct savemeta_header);
@@ -1383,10 +1382,10 @@ static int restore_init(const char *path, struct metafd *mfd, int printonly)
if (ret != 0)
return ret;
- if (sm.sm_fs_bytes > 0) {
- sbd.fssize = sm.sm_fs_bytes / sbd.sd_bsize;
+ if (sm->sm_fs_bytes > 0) {
+ sbd.fssize = sm->sm_fs_bytes / sbd.sd_bsize;
printf("Saved file system size is %"PRIu64" blocks, %.2fGB\n",
- sbd.fssize, sm.sm_fs_bytes / ((float)(1 << 30)));
+ sbd.fssize, sm->sm_fs_bytes / ((float)(1 << 30)));
}
printf("Block size is %uB\n", sbd.sd_bsize);
printf("This is gfs%c metadata.\n", sbd.gfs1 ? '1': '2');
@@ -1406,6 +1405,8 @@ static int restore_init(const char *path, struct metafd *mfd, int printonly)
void restoremeta(const char *in_fn, const char *out_device, uint64_t printonly)
{
struct metafd mfd = {0};
+ struct savemeta sm = {0};
+ struct stat st;
int error;
termlines = 0;
@@ -1430,7 +1431,7 @@ void restoremeta(const char *in_fn, const char *out_device, uint64_t printonly)
optional block no */
printonly = check_keywords(out_device);
- error = restore_init(in_fn, &mfd, printonly);
+ error = restore_init(in_fn, &mfd, &sm, printonly);
if (error != 0)
exit(error);
@@ -1440,6 +1441,23 @@ void restoremeta(const char *in_fn, const char *out_device, uint64_t printonly)
}
error = restore_data(sbd.device_fd, &mfd, printonly);
+
+ /* When there is a metadata header available, truncate to filesystem
+ size if our device_fd is a regular file */
+ if (!printonly) {
+ if (fstat(sbd.device_fd, &st) == -1) {
+ fprintf(stderr, "Failed to stat %s: %s\n", out_device, strerror(errno));
+ error = errno;
+ }
+
+ if (sm.sm_fs_bytes > 0 && S_ISREG(st.st_mode)) {
+ if (ftruncate(sbd.device_fd, sm.sm_fs_bytes) != 0) {
+ fprintf(stderr, "Failed to truncate: %s, %s\n", out_device, strerror(errno));
+ error = errno;
+ }
+ }
+ }
+
printf("File %s %s %s.\n", in_fn,
(printonly ? "print" : "restore"),
(error ? "error" : "successful"));
diff --git a/tests/edit.at b/tests/edit.at
index d6795218..29835df0 100644
--- a/tests/edit.at
+++ b/tests/edit.at
@@ -61,3 +61,13 @@ AT_CHECK([$GFS_MKFS -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
AT_CHECK([gfs2_edit savemeta -z0 $GFS_TGT /dev/null], 0, [ignore], [ignore])
AT_CHECK([gfs2_edit savemeta $GFS_TGT /dev/null], 0, [ignore], [ignore])
AT_CLEANUP
+
+AT_SETUP([Truncate on restoremeta])
+AT_KEYWORDS(gfs2_edit edit)
+GFS_TGT_REGEN
+AT_CHECK([$GFS_MKFS -p lock_nolock $GFS_TGT], 0, [ignore], [ignore])
+AT_CHECK([gfs2_edit savemeta $GFS_TGT test.meta], 0, [ignore], [ignore])
+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

View File

@ -1,6 +1,6 @@
Name: gfs2-utils Name: gfs2-utils
Version: 3.5.1 Version: 3.5.1
Release: 1%{?dist} Release: 2%{?dist}
License: GPLv2+ and LGPLv2+ License: GPLv2+ and LGPLv2+
Summary: Utilities for managing the global file system (GFS2) Summary: Utilities for managing the global file system (GFS2)
%ifnarch %{arm} %ifnarch %{arm}
@ -21,6 +21,7 @@ BuildRequires: bzip2-devel
BuildRequires: make BuildRequires: make
Source: https://releases.pagure.org/gfs2-utils/gfs2-utils-%{version}.tar.gz Source: https://releases.pagure.org/gfs2-utils/gfs2-utils-%{version}.tar.gz
URL: https://pagure.io/gfs2-utils URL: https://pagure.io/gfs2-utils
Patch0: RHEL-26661-gfs2_edit_truncate_to_filesystem_size_at_end_of_restoremeta.patch
%prep %prep
%autosetup -p1 %autosetup -p1
@ -63,6 +64,11 @@ modifying, and correcting inconsistencies in GFS2 file systems.
%{_prefix}/lib/udev/rules.d/82-gfs2-withdraw.rules %{_prefix}/lib/udev/rules.d/82-gfs2-withdraw.rules
%changelog %changelog
* 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
- Update tests/testsuite
* Tue Apr 11 2023 Andrew Price <anprice@redhat.com> - 3.5.1-1 * Tue Apr 11 2023 Andrew Price <anprice@redhat.com> - 3.5.1-1
- New upstream release - New upstream release
- Drop patches - Drop patches

View File

@ -652,9 +652,10 @@ at_help_all="1;mkfs.at:4;Locking protocol validation;mkfs.gfs2 mkfs;
40;edit.at:37;Save/restoremeta, 4 journals;gfs2_edit edit; 40;edit.at:37;Save/restoremeta, 4 journals;gfs2_edit edit;
41;edit.at:47;Save/restoremeta, min. block size, 4 journals;gfs2_edit edit; 41;edit.at:47;Save/restoremeta, min. block size, 4 journals;gfs2_edit edit;
42;edit.at:57;Save metadata to /dev/null;gfs2_edit edit; 42;edit.at:57;Save metadata to /dev/null;gfs2_edit edit;
43;tune.at:4;Format version;tunegfs2 tune; 43;edit.at:65;Truncate on restoremeta;gfs2_edit edit;
44;tune.at:20;Handle bad fs;tunegfs2 tune; 44;tune.at:4;Format version;tunegfs2 tune;
45;tune.at:28;Expected output;tunegfs2 tune; 45;tune.at:20;Handle bad fs;tunegfs2 tune;
46;tune.at:28;Expected output;tunegfs2 tune;
" "
# List of the all the test groups. # List of the all the test groups.
at_groups_all=`printf "%s\n" "$at_help_all" | sed 's/;.*//'` at_groups_all=`printf "%s\n" "$at_help_all" | sed 's/;.*//'`
@ -668,7 +669,7 @@ at_fn_validate_ranges ()
for at_grp for at_grp
do do
eval at_value=\$$at_grp eval at_value=\$$at_grp
if test $at_value -lt 1 || test $at_value -gt 45; then if test $at_value -lt 1 || test $at_value -gt 46; then
printf "%s\n" "invalid test group: $at_value" >&2 printf "%s\n" "invalid test group: $at_value" >&2
exit 1 exit 1
fi fi
@ -998,7 +999,7 @@ fi
# List of tests. # List of tests.
if $at_list_p; then if $at_list_p; then
cat <<_ATEOF || at_write_fail=1 cat <<_ATEOF || at_write_fail=1
gfs2-utils 3.5.0 test suite test groups: gfs2-utils 3.5.1 test suite test groups:
NUM: FILE-NAME:LINE TEST-GROUP-NAME NUM: FILE-NAME:LINE TEST-GROUP-NAME
KEYWORDS KEYWORDS
@ -1039,7 +1040,7 @@ _ATEOF
exit $at_write_fail exit $at_write_fail
fi fi
if $at_version_p; then if $at_version_p; then
printf "%s\n" "$as_me (gfs2-utils 3.5.0)" && printf "%s\n" "$as_me (gfs2-utils 3.5.1)" &&
cat <<\_ATEOF || at_write_fail=1 cat <<\_ATEOF || at_write_fail=1
Copyright (C) 2021 Free Software Foundation, Inc. Copyright (C) 2021 Free Software Foundation, Inc.
@ -1066,7 +1067,7 @@ at_banner_text_2="fsck.gfs2 tests"
# Category starts at test group 37. # Category starts at test group 37.
at_banner_text_3="gfs2_edit tests" at_banner_text_3="gfs2_edit tests"
# Banner 4. tune.at:2 # Banner 4. tune.at:2
# Category starts at test group 43. # Category starts at test group 44.
at_banner_text_4="tunegfs2 tests" at_banner_text_4="tunegfs2 tests"
# Take any -C into account. # Take any -C into account.
@ -1236,11 +1237,11 @@ exec 5>>"$at_suite_log"
# Banners and logs. # Banners and logs.
printf "%s\n" "## ---------------------------- ## printf "%s\n" "## ---------------------------- ##
## gfs2-utils 3.5.0 test suite. ## ## gfs2-utils 3.5.1 test suite. ##
## ---------------------------- ##" ## ---------------------------- ##"
{ {
printf "%s\n" "## ---------------------------- ## printf "%s\n" "## ---------------------------- ##
## gfs2-utils 3.5.0 test suite. ## ## gfs2-utils 3.5.1 test suite. ##
## ---------------------------- ##" ## ---------------------------- ##"
echo echo
@ -2100,7 +2101,7 @@ _ASBOX
printf "%s\n" "Please send $at_msg and all information you think might help: printf "%s\n" "Please send $at_msg and all information you think might help:
To: <cluster-devel@redhat.com> To: <cluster-devel@redhat.com>
Subject: [gfs2-utils 3.5.0] $as_me: $at_msg1$at_msg2 Subject: [gfs2-utils 3.5.1] $as_me: $at_msg1$at_msg2
You may investigate any problem if you feel able to do so, in which You may investigate any problem if you feel able to do so, in which
case the test suite provides a good starting point. Its output may case the test suite provides a good starting point. Its output may
@ -6225,14 +6226,109 @@ $at_traceon; }
read at_status <"$at_status_file" read at_status <"$at_status_file"
#AT_STOP_42 #AT_STOP_42
#AT_START_43 #AT_START_43
at_fn_group_banner 43 'tune.at:4' \ at_fn_group_banner 43 'edit.at:65' \
"Format version" " " 4 "Truncate on restoremeta" " " 3
at_xfail=no at_xfail=no
( (
printf "%s\n" "43. $at_setup_line: testing $at_desc ..." printf "%s\n" "43. $at_setup_line: testing $at_desc ..."
$at_traceon $at_traceon
{ set +x
printf "%s\n" "$at_srcdir/edit.at:67: rm -f \$GFS_TGT && truncate -s \${GFS_TGT_SZ}G \${GFS_TGT}"
at_fn_check_prepare_notrace 'a ${...} parameter expansion' "edit.at:67"
( $at_check_trace; rm -f $GFS_TGT && truncate -s ${GFS_TGT_SZ}G ${GFS_TGT}
) >>"$at_stdout" 2>>"$at_stderr" 5>&-
at_status=$? at_failed=false
$at_check_filter
echo stderr:; cat "$at_stderr"
echo stdout:; cat "$at_stdout"
at_fn_check_skip $at_status "$at_srcdir/edit.at:67"
$at_failed && at_fn_log_failure
$at_traceon; }
printf "%s\n" "edit.at:67" >"$at_check_line_file"
(test ! -f ${GFS_TGT}) \
&& at_fn_check_skip 77 "$at_srcdir/edit.at:67"
{ set +x
printf "%s\n" "$at_srcdir/edit.at:68: \$GFS_MKFS -p lock_nolock \$GFS_TGT"
at_fn_check_prepare_dynamic "$GFS_MKFS -p lock_nolock $GFS_TGT" "edit.at:68"
( $at_check_trace; $GFS_MKFS -p lock_nolock $GFS_TGT
) >>"$at_stdout" 2>>"$at_stderr" 5>&-
at_status=$? at_failed=false
$at_check_filter
echo stderr:; cat "$at_stderr"
echo stdout:; cat "$at_stdout"
at_fn_check_status 0 $at_status "$at_srcdir/edit.at:68"
$at_failed && at_fn_log_failure
$at_traceon; }
{ set +x
printf "%s\n" "$at_srcdir/edit.at:69: gfs2_edit savemeta \$GFS_TGT test.meta"
at_fn_check_prepare_dynamic "gfs2_edit savemeta $GFS_TGT test.meta" "edit.at:69"
( $at_check_trace; gfs2_edit savemeta $GFS_TGT test.meta
) >>"$at_stdout" 2>>"$at_stderr" 5>&-
at_status=$? at_failed=false
$at_check_filter
echo stderr:; cat "$at_stderr"
echo stdout:; cat "$at_stdout"
at_fn_check_status 0 $at_status "$at_srcdir/edit.at:69"
$at_failed && at_fn_log_failure
$at_traceon; }
{ set +x
printf "%s\n" "$at_srcdir/edit.at:70: truncate -s 10K test.file"
at_fn_check_prepare_trace "edit.at:70"
( $at_check_trace; truncate -s 10K test.file
) >>"$at_stdout" 2>>"$at_stderr" 5>&-
at_status=$? at_failed=false
$at_check_filter
echo stderr:; cat "$at_stderr"
echo stdout:; cat "$at_stdout"
at_fn_check_status 0 $at_status "$at_srcdir/edit.at:70"
$at_failed && at_fn_log_failure
$at_traceon; }
{ set +x
printf "%s\n" "$at_srcdir/edit.at:71: gfs2_edit restoremeta test.meta test.file"
at_fn_check_prepare_trace "edit.at:71"
( $at_check_trace; gfs2_edit restoremeta test.meta test.file
) >>"$at_stdout" 2>>"$at_stderr" 5>&-
at_status=$? at_failed=false
$at_check_filter
echo stderr:; cat "$at_stderr"
echo stdout:; cat "$at_stdout"
at_fn_check_status 0 $at_status "$at_srcdir/edit.at:71"
$at_failed && at_fn_log_failure
$at_traceon; }
{ set +x
printf "%s\n" "$at_srcdir/edit.at:72: fsck.gfs2 -n test.file"
at_fn_check_prepare_trace "edit.at:72"
( $at_check_trace; fsck.gfs2 -n test.file
) >>"$at_stdout" 2>>"$at_stderr" 5>&-
at_status=$? at_failed=false
$at_check_filter
echo stderr:; cat "$at_stderr"
echo stdout:; cat "$at_stdout"
at_fn_check_status 0 $at_status "$at_srcdir/edit.at:72"
$at_failed && at_fn_log_failure
$at_traceon; }
set +x
$at_times_p && times >"$at_times_file"
) 5>&1 2>&1 7>&- | eval $at_tee_pipe
read at_status <"$at_status_file"
#AT_STOP_43
#AT_START_44
at_fn_group_banner 44 'tune.at:4' \
"Format version" " " 4
at_xfail=no
(
printf "%s\n" "44. $at_setup_line: testing $at_desc ..."
$at_traceon
{ set +x { set +x
printf "%s\n" "$at_srcdir/tune.at:6: rm -f \$GFS_TGT && truncate -s \${GFS_TGT_SZ}G \${GFS_TGT}" printf "%s\n" "$at_srcdir/tune.at:6: rm -f \$GFS_TGT && truncate -s \${GFS_TGT_SZ}G \${GFS_TGT}"
at_fn_check_prepare_notrace 'a ${...} parameter expansion' "tune.at:6" at_fn_check_prepare_notrace 'a ${...} parameter expansion' "tune.at:6"
@ -6348,13 +6444,13 @@ $at_traceon; }
$at_times_p && times >"$at_times_file" $at_times_p && times >"$at_times_file"
) 5>&1 2>&1 7>&- | eval $at_tee_pipe ) 5>&1 2>&1 7>&- | eval $at_tee_pipe
read at_status <"$at_status_file" read at_status <"$at_status_file"
#AT_STOP_43 #AT_STOP_44
#AT_START_44 #AT_START_45
at_fn_group_banner 44 'tune.at:20' \ at_fn_group_banner 45 'tune.at:20' \
"Handle bad fs" " " 4 "Handle bad fs" " " 4
at_xfail=no at_xfail=no
( (
printf "%s\n" "44. $at_setup_line: testing $at_desc ..." printf "%s\n" "45. $at_setup_line: testing $at_desc ..."
$at_traceon $at_traceon
@ -6392,13 +6488,13 @@ $at_traceon; }
$at_times_p && times >"$at_times_file" $at_times_p && times >"$at_times_file"
) 5>&1 2>&1 7>&- | eval $at_tee_pipe ) 5>&1 2>&1 7>&- | eval $at_tee_pipe
read at_status <"$at_status_file" read at_status <"$at_status_file"
#AT_STOP_44 #AT_STOP_45
#AT_START_45 #AT_START_46
at_fn_group_banner 45 'tune.at:28' \ at_fn_group_banner 46 'tune.at:28' \
"Expected output" " " 4 "Expected output" " " 4
at_xfail=no at_xfail=no
( (
printf "%s\n" "45. $at_setup_line: testing $at_desc ..." printf "%s\n" "46. $at_setup_line: testing $at_desc ..."
$at_traceon $at_traceon
@ -6511,4 +6607,4 @@ $at_traceon; }
$at_times_p && times >"$at_times_file" $at_times_p && times >"$at_times_file"
) 5>&1 2>&1 7>&- | eval $at_tee_pipe ) 5>&1 2>&1 7>&- | eval $at_tee_pipe
read at_status <"$at_status_file" read at_status <"$at_status_file"
#AT_STOP_45 #AT_STOP_46