[thin_repair, cache_repair] Check input file exists earlier
and zero superblock if we fail part way through a repair. bz1499781
This commit is contained in:
parent
a3b8e9db78
commit
1dd7b454bb
@ -2,6 +2,7 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
||||||
|
#include "base/file_utils.h"
|
||||||
#include "base/output_file_requirements.h"
|
#include "base/output_file_requirements.h"
|
||||||
#include "caching/commands.h"
|
#include "caching/commands.h"
|
||||||
#include "caching/metadata.h"
|
#include "caching/metadata.h"
|
||||||
@ -29,12 +30,17 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int repair(string const &old_path, string const &new_path) {
|
int repair(string const &old_path, string const &new_path) {
|
||||||
|
bool metadata_touched = false;
|
||||||
try {
|
try {
|
||||||
|
file_utils::check_file_exists(new_path);
|
||||||
|
metadata_touched = true;
|
||||||
metadata_dump(open_metadata_for_read(old_path),
|
metadata_dump(open_metadata_for_read(old_path),
|
||||||
output_emitter(new_path),
|
output_emitter(new_path),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
|
if (metadata_touched)
|
||||||
|
file_utils::zero_superblock(new_path);
|
||||||
cerr << e.what() << endl;
|
cerr << e.what() << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -110,7 +116,7 @@ cache_repair_cmd::run(int argc, char **argv)
|
|||||||
check_output_file_requirements(*output_path);
|
check_output_file_requirements(*output_path);
|
||||||
|
|
||||||
else {
|
else {
|
||||||
cerr << "no output file provided" << endl;
|
cerr << "No output file provided." << endl;
|
||||||
usage(cerr);
|
usage(cerr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
(define-tool cache-dump)
|
(define-tool cache-dump)
|
||||||
(define-tool cache-restore)
|
(define-tool cache-restore)
|
||||||
(define-tool cache-metadata-size)
|
(define-tool cache-metadata-size)
|
||||||
|
(define-tool cache-repair)
|
||||||
|
|
||||||
(define-syntax with-cache-xml
|
(define-syntax with-cache-xml
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
@ -35,7 +36,8 @@
|
|||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((_ (md) b1 b2 ...)
|
((_ (md) b1 b2 ...)
|
||||||
(with-temp-file-sized ((md "cache.bin" (to-bytes (meg 4))))
|
(with-temp-file-sized ((md "cache.bin" (to-bytes (meg 4))))
|
||||||
b1 b2 ...))))
|
(system (fmt #f "dd if=/usr/bin/ls of=" md " bs=4096 > /dev/null 2>&1"))
|
||||||
|
b1 b2 ...))))
|
||||||
|
|
||||||
(define-syntax with-empty-metadata
|
(define-syntax with-empty-metadata
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
@ -180,7 +182,7 @@
|
|||||||
"the input file can't be found"
|
"the input file can't be found"
|
||||||
(with-empty-metadata (md)
|
(with-empty-metadata (md)
|
||||||
(run-fail-rcv (_ stderr) (cache-restore "-i no-such-file -o" md)
|
(run-fail-rcv (_ stderr) (cache-restore "-i no-such-file -o" md)
|
||||||
(assert-superblock-untouched md)
|
(assert-superblock-all-zeroes md)
|
||||||
(assert-starts-with "Couldn't stat file" stderr))))
|
(assert-starts-with "Couldn't stat file" stderr))))
|
||||||
|
|
||||||
(define-scenario (cache-restore garbage-input-file)
|
(define-scenario (cache-restore garbage-input-file)
|
||||||
@ -188,7 +190,7 @@
|
|||||||
(with-empty-metadata (md)
|
(with-empty-metadata (md)
|
||||||
(with-temp-file-sized ((xml "cache.xml" 4096))
|
(with-temp-file-sized ((xml "cache.xml" 4096))
|
||||||
(run-fail-rcv (_ stderr) (cache-restore "-i" xml "-o" md)
|
(run-fail-rcv (_ stderr) (cache-restore "-i" xml "-o" md)
|
||||||
(assert-superblock-untouched md)))))
|
(assert-superblock-all-zeroes md)))))
|
||||||
|
|
||||||
(define-scenario (cache-restore missing-output-file)
|
(define-scenario (cache-restore missing-output-file)
|
||||||
"the output file can't be found"
|
"the output file can't be found"
|
||||||
@ -354,4 +356,28 @@
|
|||||||
(run-ok-rcv (stdout stderr) (cache-metadata-size "--nr-blocks 67108864")
|
(run-ok-rcv (stdout stderr) (cache-metadata-size "--nr-blocks 67108864")
|
||||||
(assert-equal "3678208 sectors" stdout)
|
(assert-equal "3678208 sectors" stdout)
|
||||||
(assert-eof stderr)))
|
(assert-eof stderr)))
|
||||||
|
|
||||||
|
;;;-----------------------------------------------------------
|
||||||
|
;;; cache_repair scenarios
|
||||||
|
;;;-----------------------------------------------------------
|
||||||
|
(define-scenario (cache-repair missing-input-file)
|
||||||
|
"the input file can't be found"
|
||||||
|
(with-empty-metadata (md)
|
||||||
|
(run-fail-rcv (_ stderr) (cache-repair "-i no-such-file -o" md)
|
||||||
|
(assert-superblock-all-zeroes md)
|
||||||
|
(assert-starts-with "Couldn't stat path" stderr))))
|
||||||
|
|
||||||
|
(define-scenario (cache-repair garbage-input-file)
|
||||||
|
"the input file is just zeroes"
|
||||||
|
(with-empty-metadata (md1)
|
||||||
|
(with-corrupt-metadata (md2)
|
||||||
|
(run-fail-rcv (_ stderr) (cache-repair "-i" md1 "-o" md2)
|
||||||
|
(assert-superblock-all-zeroes md2)))))
|
||||||
|
|
||||||
|
(define-scenario (cache-repair missing-output-file)
|
||||||
|
"the output file can't be found"
|
||||||
|
(with-cache-xml (xml)
|
||||||
|
(run-fail-rcv (_ stderr) (cache-repair "-i" xml)
|
||||||
|
(assert-starts-with "No output file provided." stderr))))
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@ -153,7 +153,7 @@
|
|||||||
"the input file can't be found"
|
"the input file can't be found"
|
||||||
(with-empty-metadata (md)
|
(with-empty-metadata (md)
|
||||||
(run-fail-rcv (_ stderr) (era-restore "-i no-such-file -o" md)
|
(run-fail-rcv (_ stderr) (era-restore "-i no-such-file -o" md)
|
||||||
(assert-superblock-untouched md)
|
(assert-superblock-all-zeroes md)
|
||||||
(assert-starts-with "Couldn't stat file" stderr))))
|
(assert-starts-with "Couldn't stat file" stderr))))
|
||||||
|
|
||||||
(define-scenario (era-restore garbage-input-file)
|
(define-scenario (era-restore garbage-input-file)
|
||||||
@ -161,7 +161,7 @@
|
|||||||
(with-empty-metadata (md)
|
(with-empty-metadata (md)
|
||||||
(with-temp-file-sized ((xml "era.xml" 4096))
|
(with-temp-file-sized ((xml "era.xml" 4096))
|
||||||
(run-fail-rcv (_ stderr) (era-restore "-i " xml "-o" md)
|
(run-fail-rcv (_ stderr) (era-restore "-i " xml "-o" md)
|
||||||
(assert-superblock-untouched md)))))
|
(assert-superblock-all-zeroes md)))))
|
||||||
|
|
||||||
(define-scenario (era-restore output-unspecified)
|
(define-scenario (era-restore output-unspecified)
|
||||||
"Fails if no metadata dev specified"
|
"Fails if no metadata dev specified"
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
assert-eof
|
assert-eof
|
||||||
assert-starts-with
|
assert-starts-with
|
||||||
assert-matches
|
assert-matches
|
||||||
assert-superblock-untouched
|
assert-superblock-all-zeroes
|
||||||
assert-member?
|
assert-member?
|
||||||
assert-raises-thunk
|
assert-raises-thunk
|
||||||
assert-raises
|
assert-raises
|
||||||
@ -259,7 +259,7 @@
|
|||||||
(loop (+ i 1))
|
(loop (+ i 1))
|
||||||
#f)))))
|
#f)))))
|
||||||
|
|
||||||
(define (assert-superblock-untouched md)
|
(define (assert-superblock-all-zeroes md)
|
||||||
(with-bcache (cache md 1)
|
(with-bcache (cache md 1)
|
||||||
(with-block (b cache 0 (get-flags))
|
(with-block (b cache 0 (get-flags))
|
||||||
(unless (all-zeroes? (block-data b) 4096)
|
(unless (all-zeroes? (block-data b) 4096)
|
||||||
|
@ -37,10 +37,12 @@
|
|||||||
b1 b2 ...)))))
|
b1 b2 ...)))))
|
||||||
|
|
||||||
;;; It would be nice if the metadata was at least similar to valid data.
|
;;; It would be nice if the metadata was at least similar to valid data.
|
||||||
|
;;; Here I'm just using the start of the ls binary as 'random' data.
|
||||||
(define-syntax with-corrupt-metadata
|
(define-syntax with-corrupt-metadata
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((_ (md) b1 b2 ...)
|
((_ (md) b1 b2 ...)
|
||||||
(with-temp-file-sized ((md "thin.bin" (meg 4)))
|
(with-temp-file-sized ((md "thin.bin" (meg 4)))
|
||||||
|
(system (fmt #f "dd if=/usr/bin/ls of=" md " bs=4096 > /dev/null 2>&1"))
|
||||||
b1 b2 ...))))
|
b1 b2 ...))))
|
||||||
|
|
||||||
(define-syntax with-empty-metadata
|
(define-syntax with-empty-metadata
|
||||||
@ -167,7 +169,7 @@
|
|||||||
"the input file can't be found"
|
"the input file can't be found"
|
||||||
(with-empty-metadata (md)
|
(with-empty-metadata (md)
|
||||||
(run-fail-rcv (_ stderr) (thin-restore "-i no-such-file -o" md)
|
(run-fail-rcv (_ stderr) (thin-restore "-i no-such-file -o" md)
|
||||||
(assert-superblock-untouched md)
|
(assert-superblock-all-zeroes md)
|
||||||
(assert-starts-with "Couldn't stat file" stderr))))
|
(assert-starts-with "Couldn't stat file" stderr))))
|
||||||
|
|
||||||
(define-scenario (thin-restore garbage-input-file)
|
(define-scenario (thin-restore garbage-input-file)
|
||||||
@ -175,7 +177,7 @@
|
|||||||
(with-empty-metadata (md)
|
(with-empty-metadata (md)
|
||||||
(with-temp-file-sized ((xml "thin.xml" 4096))
|
(with-temp-file-sized ((xml "thin.xml" 4096))
|
||||||
(run-fail-rcv (_ stderr) (thin-restore "-i " xml "-o" md)
|
(run-fail-rcv (_ stderr) (thin-restore "-i " xml "-o" md)
|
||||||
(assert-superblock-untouched md)))))
|
(assert-superblock-all-zeroes md)))))
|
||||||
|
|
||||||
(define-scenario (thin-restore missing-output-file)
|
(define-scenario (thin-restore missing-output-file)
|
||||||
"the output file can't be found"
|
"the output file can't be found"
|
||||||
@ -333,4 +335,25 @@
|
|||||||
(with-empty-metadata (md)
|
(with-empty-metadata (md)
|
||||||
(run-fail-rcv (_ stderr) (thin-repair "-i" xml "-o" md)
|
(run-fail-rcv (_ stderr) (thin-repair "-i" xml "-o" md)
|
||||||
#t))))
|
#t))))
|
||||||
|
|
||||||
|
(define-scenario (thin-repair missing-input-file)
|
||||||
|
"the input file can't be found"
|
||||||
|
(with-empty-metadata (md)
|
||||||
|
(run-fail-rcv (_ stderr) (thin-repair "-i no-such-file -o" md)
|
||||||
|
(assert-superblock-all-zeroes md)
|
||||||
|
(assert-starts-with "Couldn't stat file" stderr))))
|
||||||
|
|
||||||
|
(define-scenario (thin-repair garbage-input-file)
|
||||||
|
"the input file is just zeroes"
|
||||||
|
(with-empty-metadata (md1)
|
||||||
|
(with-corrupt-metadata (md2)
|
||||||
|
(run-fail-rcv (_ stderr) (thin-repair "-i " md1 "-o" md2)
|
||||||
|
(assert-superblock-all-zeroes md2)))))
|
||||||
|
|
||||||
|
(define-scenario (thin-repair missing-output-file)
|
||||||
|
"the output file can't be found"
|
||||||
|
(with-thin-xml (xml)
|
||||||
|
(run-fail-rcv (_ stderr) (thin-repair "-i " xml)
|
||||||
|
(assert-starts-with "No output file provided." stderr))))
|
||||||
|
|
||||||
)
|
)
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
||||||
|
#include "base/file_utils.h"
|
||||||
#include "base/output_file_requirements.h"
|
#include "base/output_file_requirements.h"
|
||||||
#include "persistent-data/file_utils.h"
|
#include "persistent-data/file_utils.h"
|
||||||
#include "thin-provisioning/commands.h"
|
#include "thin-provisioning/commands.h"
|
||||||
@ -17,15 +18,20 @@ using namespace thin_provisioning;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int repair(string const &old_path, string const &new_path) {
|
int repair(string const &old_path, string const &new_path) {
|
||||||
|
bool metadata_touched = false;
|
||||||
try {
|
try {
|
||||||
// block size gets updated by the restorer
|
// block size gets updated by the restorer
|
||||||
block_manager<>::ptr new_bm = open_bm(new_path, block_manager<>::READ_WRITE);
|
block_manager<>::ptr new_bm = open_bm(new_path, block_manager<>::READ_WRITE);
|
||||||
|
file_utils::check_file_exists(old_path);
|
||||||
|
metadata_touched = true;
|
||||||
metadata::ptr new_md(new metadata(new_bm, metadata::CREATE, 128, 0));
|
metadata::ptr new_md(new metadata(new_bm, metadata::CREATE, 128, 0));
|
||||||
emitter::ptr e = create_restore_emitter(new_md);
|
emitter::ptr e = create_restore_emitter(new_md);
|
||||||
block_manager<>::ptr old_bm = open_bm(old_path, block_manager<>::READ_ONLY);
|
block_manager<>::ptr old_bm = open_bm(old_path, block_manager<>::READ_ONLY);
|
||||||
metadata_repair(old_bm, e);
|
metadata_repair(old_bm, e);
|
||||||
|
|
||||||
} catch (std::exception &e) {
|
} catch (std::exception &e) {
|
||||||
|
if (metadata_touched)
|
||||||
|
file_utils::zero_superblock(new_path);
|
||||||
cerr << e.what() << endl;
|
cerr << e.what() << endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -101,7 +107,7 @@ thin_repair_cmd::run(int argc, char **argv)
|
|||||||
check_output_file_requirements(*output_path);
|
check_output_file_requirements(*output_path);
|
||||||
|
|
||||||
else {
|
else {
|
||||||
cerr << "no output file provided" << endl;
|
cerr << "No output file provided." << endl;
|
||||||
usage(cerr);
|
usage(cerr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user