From 0d910eb7ab51c7ebd436c2194aceedc0a3595125 Mon Sep 17 00:00:00 2001 From: Hunter Shaffer Date: Wed, 14 Aug 2024 16:47:59 -0400 Subject: [PATCH] Check if source device has been mounted The filesystem we are restoring into needs to be empty and never mounted. Here we check the all of the quorum blocks timestamps to see whether the device we are restoring into has been mounted before. Adds a test in the test script that attempts to restore a previously mounted device. Signed-off-by: Hunter Shaffer Signed-off-by: Auke Kok --- tests/src/parallel_restore.c | 2 +- tests/src/restore_copy.c | 2 +- utils/src/parallel_restore.c | 47 +++++++++++++++++++++++++++++++++++- utils/src/parallel_restore.h | 2 +- 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/tests/src/parallel_restore.c b/tests/src/parallel_restore.c index e45f7121..b6c82657 100644 --- a/tests/src/parallel_restore.c +++ b/tests/src/parallel_restore.c @@ -601,7 +601,7 @@ static int do_restore(struct opts *opts) ret = scoutfs_parallel_restore_create_writer(&wri); error_exit(ret, "create writer %d", ret); - ret = scoutfs_parallel_restore_import_super(wri, super); + ret = scoutfs_parallel_restore_import_super(wri, super, dev_fd); error_exit(ret, "import super %d", ret); slices = calloc(1 + opts->nr_writers, sizeof(struct scoutfs_parallel_restore_slice)); diff --git a/tests/src/restore_copy.c b/tests/src/restore_copy.c index 47f28796..7979443f 100644 --- a/tests/src/restore_copy.c +++ b/tests/src/restore_copy.c @@ -672,7 +672,7 @@ static int do_restore(struct opts *opts) ret = scoutfs_parallel_restore_create_writer(&wri); error_exit(ret, "create writer %d", ret); - ret = scoutfs_parallel_restore_import_super(wri, super); + ret = scoutfs_parallel_restore_import_super(wri, super, dev_fd); error_exit(ret, "import super %d", ret); slices = calloc(2, sizeof(struct scoutfs_parallel_restore_slice)); diff --git a/utils/src/parallel_restore.c b/utils/src/parallel_restore.c index 18e9797b..2c18dc9a 100644 --- a/utils/src/parallel_restore.c +++ b/utils/src/parallel_restore.c @@ -1816,13 +1816,58 @@ out: return count > 0 ? 0 : err; } +/* + * Here we take in a dev's fd an read its quorum blocks to see if the dev has + * been mounted before + */ +static spr_err_t scoutfs_check_if_previous_mount(int fd) +{ + struct scoutfs_quorum_block *blk = NULL; + struct scoutfs_quorum_block_event *ev; + u64 blkno; + int i, j; + spr_err_t err; + + for (i = 0; i < SCOUTFS_QUORUM_MAX_SLOTS; i++) { + blkno = SCOUTFS_QUORUM_BLKNO + i; + err = read_block(fd, blkno, SCOUTFS_BLOCK_SM_SHIFT, (void **)&blk); + if (!blk) + return EINVAL; + + dprintf("quorum block read; quorum bklno: %llu, err_val: %d\n", blkno, err); + if (err) { + free(blk); + return err; + } + + for (j = 0; j < SCOUTFS_QUORUM_EVENT_NR; j++) { + ev = &blk->events[j]; + if (ev->ts.sec || ev->ts.nsec) { + free(blk); + return EINVAL; + } + } + + free(blk); + } + + return err; +} + spr_err_t scoutfs_parallel_restore_import_super(struct scoutfs_parallel_restore_writer *wri, - struct scoutfs_super_block *super) + struct scoutfs_super_block *super, int fd) { spr_err_t err; u64 start; u64 len; + /* + * check the device we are restoring into to make sure + * that it has has never been mounted + */ + if (scoutfs_check_if_previous_mount(fd)) + return EINVAL; + if (le64_to_cpu(super->fmt_vers) < 2) return EINVAL; diff --git a/utils/src/parallel_restore.h b/utils/src/parallel_restore.h index 075c71ae..4f4c3558 100644 --- a/utils/src/parallel_restore.h +++ b/utils/src/parallel_restore.h @@ -97,7 +97,7 @@ spr_err_t scoutfs_parallel_restore_write_buf(struct scoutfs_parallel_restore_wri size_t *count_ret); spr_err_t scoutfs_parallel_restore_import_super(struct scoutfs_parallel_restore_writer *wri, - struct scoutfs_super_block *super); + struct scoutfs_super_block *super, int fd); spr_err_t scoutfs_parallel_restore_export_super(struct scoutfs_parallel_restore_writer *wri, struct scoutfs_super_block *super);