112 lines
4.0 KiB
Diff
112 lines
4.0 KiB
Diff
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
|