diff --git a/SOURCES/dmpd-remove-pool-inactive-from-thin_trim-man-page.patch b/SOURCES/dmpd-remove-pool-inactive-from-thin_trim-man-page.patch new file mode 100644 index 0000000..cb32de9 --- /dev/null +++ b/SOURCES/dmpd-remove-pool-inactive-from-thin_trim-man-page.patch @@ -0,0 +1,17 @@ + man8/thin_trim.txt | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/man8/thin_trim.txt b/man8/thin_trim.txt +index 1d24a06..e19d8bd 100644 +--- a/man8/thin_trim.txt ++++ b/man8/thin_trim.txt +@@ -12,9 +12,6 @@ DESCRIPTION + OPTIONS + -h, --help Print help and exit. + -V, --version Print version information and exit. +- --pool-inactive Indicates you are aware the pool should be inactive. +- +- Suppresses a warning message and prompt. + + SEE ALSO + thin_dump(8), thin_repair(8), thin_restore(8), thin_rmap(8), thin_metadata_size(8) diff --git a/SOURCES/dmpd-tests-lib-bcache-rename-raise-raise_.patch b/SOURCES/dmpd-tests-lib-bcache-rename-raise-raise_.patch new file mode 100644 index 0000000..b3db209 --- /dev/null +++ b/SOURCES/dmpd-tests-lib-bcache-rename-raise-raise_.patch @@ -0,0 +1,77 @@ + ft-lib/bcache.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/ft-lib/bcache.c b/ft-lib/bcache.c +index 0dca503..ee5b6c5 100644 +--- a/ft-lib/bcache.c ++++ b/ft-lib/bcache.c +@@ -31,7 +31,7 @@ static void warn(const char *fmt, ...) + } + + // FIXME: raise a condition somehow? +-static void raise(const char *fmt, ...) ++static void raise_(const char *fmt, ...) + { + va_list ap; + +@@ -51,7 +51,7 @@ static inline struct list_head *list_pop(struct list_head *head) + struct list_head *l; + + if (head->next == head) +- raise("list is empty\n"); ++ raise_("list is empty\n"); + + l = head->next; + list_del(l); +@@ -98,7 +98,7 @@ static struct cb_set *cb_set_create(unsigned nr) + static void cb_set_destroy(struct cb_set *cbs) + { + if (!list_empty(&cbs->allocated)) +- raise("async io still in flight"); ++ raise_("async io still in flight"); + + free(cbs->vec); + free(cbs); +@@ -713,13 +713,13 @@ struct bcache *bcache_simple(const char *path, unsigned nr_cache_blocks) + uint64_t s; + + if (fd < 0) { +- raise("couldn't open cache file"); ++ raise_("couldn't open cache file"); + return NULL; + } + + r = fstat(fd, &info); + if (r < 0) { +- raise("couldn't stat cache file"); ++ raise_("couldn't stat cache file"); + return NULL; + } + +@@ -751,7 +751,7 @@ void bcache_destroy(struct bcache *cache) + static void check_index(struct bcache *cache, block_address index) + { + if (index >= cache->nr_data_blocks) +- raise("block out of bounds (%llu >= %llu)", ++ raise_("block out of bounds (%llu >= %llu)", + (unsigned long long) index, + (unsigned long long) cache->nr_data_blocks); + } +@@ -802,7 +802,7 @@ static struct block *lookup_or_read_block(struct bcache *cache, + // FIXME: this is insufficient. We need to also catch a read + // lock of a write locked block. Ref count needs to distinguish. + if (b->ref_count && (flags & (GF_DIRTY | GF_ZERO))) +- raise("concurrent write lock attempt"); ++ raise_("concurrent write lock attempt"); + + if (test_flags(b, BF_IO_PENDING)) { + miss(cache, flags); +@@ -858,7 +858,7 @@ struct block *get_block(struct bcache *cache, block_address index, unsigned flag + return b; + } + +- raise("couldn't get block"); ++ raise_("couldn't get block"); + return NULL; + } + diff --git a/SOURCES/dmpd-thin_repair-cache_repair-Check-input-file-exists-earlier.patch b/SOURCES/dmpd-thin_repair-cache_repair-Check-input-file-exists-earlier.patch new file mode 100644 index 0000000..9e66799 --- /dev/null +++ b/SOURCES/dmpd-thin_repair-cache_repair-Check-input-file-exists-earlier.patch @@ -0,0 +1,298 @@ + base/file_utils.cc | 4 ++-- + base/file_utils.h | 2 +- + caching/cache_repair.cc | 8 +++++++- + functional-tests/cache-functional-tests.scm | 32 ++++++++++++++++++++++++++--- + functional-tests/era-functional-tests.scm | 4 ++-- + functional-tests/functional-tests.scm | 4 ++-- + functional-tests/thin-functional-tests.scm | 27 ++++++++++++++++++++++-- + thin-provisioning/thin_repair.cc | 8 +++++++- + 8 files changed, 75 insertions(+), 14 deletions(-) + +diff --git a/base/file_utils.cc b/base/file_utils.cc +index ba8957c..7883cfe 100644 +--- a/base/file_utils.cc ++++ b/base/file_utils.cc +@@ -66,13 +66,13 @@ file_utils::file_exists(string const &path) { + } + + void +-file_utils::check_file_exists(string const &file) { ++file_utils::check_file_exists(string const &file, bool must_be_regular_file) { + struct stat info; + int r = ::stat(file.c_str(), &info); + if (r) + throw runtime_error("Couldn't stat file"); + +- if (!S_ISREG(info.st_mode)) ++ if (must_be_regular_file && !S_ISREG(info.st_mode)) + throw runtime_error("Not a regular file"); + } + +diff --git a/base/file_utils.h b/base/file_utils.h +index 2ee20ab..3edcc9e 100644 +--- a/base/file_utils.h ++++ b/base/file_utils.h +@@ -10,7 +10,7 @@ + namespace file_utils { + int open_file(std::string const &path, int flags); + bool file_exists(std::string const &path); +- void check_file_exists(std::string const &file); ++ void check_file_exists(std::string const &file, bool must_be_regular_file = true); + int create_block_file(std::string const &path, off_t file_size); + int open_block_file(std::string const &path, off_t min_size, bool writeable, bool excl = true); + uint64_t get_file_length(std::string const &file); +diff --git a/caching/cache_repair.cc b/caching/cache_repair.cc +index 9587d5f..8a837a8 100644 +--- a/caching/cache_repair.cc ++++ b/caching/cache_repair.cc +@@ -2,6 +2,7 @@ + #include + #include + ++#include "base/file_utils.h" + #include "base/output_file_requirements.h" + #include "caching/commands.h" + #include "caching/metadata.h" +@@ -29,12 +30,17 @@ namespace { + } + + int repair(string const &old_path, string const &new_path) { ++ bool metadata_touched = false; + try { ++ file_utils::check_file_exists(new_path, false); ++ metadata_touched = true; + metadata_dump(open_metadata_for_read(old_path), + output_emitter(new_path), + true); + + } catch (std::exception &e) { ++ if (metadata_touched) ++ file_utils::zero_superblock(new_path); + cerr << e.what() << endl; + return 1; + } +@@ -110,7 +116,7 @@ cache_repair_cmd::run(int argc, char **argv) + check_output_file_requirements(*output_path); + + else { +- cerr << "no output file provided" << endl; ++ cerr << "No output file provided." << endl; + usage(cerr); + return 1; + } +diff --git a/functional-tests/cache-functional-tests.scm b/functional-tests/cache-functional-tests.scm +index 0e70b94..9b3a203 100644 +--- a/functional-tests/cache-functional-tests.scm ++++ b/functional-tests/cache-functional-tests.scm +@@ -15,6 +15,7 @@ + (define-tool cache-dump) + (define-tool cache-restore) + (define-tool cache-metadata-size) ++ (define-tool cache-repair) + + (define-syntax with-cache-xml + (syntax-rules () +@@ -35,7 +36,8 @@ + (syntax-rules () + ((_ (md) b1 b2 ...) + (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 + (syntax-rules () +@@ -180,7 +182,7 @@ + "the input file can't be found" + (with-empty-metadata (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)))) + + (define-scenario (cache-restore garbage-input-file) +@@ -188,7 +190,7 @@ + (with-empty-metadata (md) + (with-temp-file-sized ((xml "cache.xml" 4096)) + (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) + "the output file can't be found" +@@ -354,4 +356,28 @@ + (run-ok-rcv (stdout stderr) (cache-metadata-size "--nr-blocks 67108864") + (assert-equal "3678208 sectors" stdout) + (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)))) ++ + ) +diff --git a/functional-tests/era-functional-tests.scm b/functional-tests/era-functional-tests.scm +index 373fe34..890f0ff 100644 +--- a/functional-tests/era-functional-tests.scm ++++ b/functional-tests/era-functional-tests.scm +@@ -153,7 +153,7 @@ + "the input file can't be found" + (with-empty-metadata (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)))) + + (define-scenario (era-restore garbage-input-file) +@@ -161,7 +161,7 @@ + (with-empty-metadata (md) + (with-temp-file-sized ((xml "era.xml" 4096)) + (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) + "Fails if no metadata dev specified" +diff --git a/functional-tests/functional-tests.scm b/functional-tests/functional-tests.scm +index aa5b95c..758498e 100644 +--- a/functional-tests/functional-tests.scm ++++ b/functional-tests/functional-tests.scm +@@ -21,7 +21,7 @@ + assert-eof + assert-starts-with + assert-matches +- assert-superblock-untouched ++ assert-superblock-all-zeroes + assert-member? + assert-raises-thunk + assert-raises +@@ -259,7 +259,7 @@ + (loop (+ i 1)) + #f))))) + +- (define (assert-superblock-untouched md) ++ (define (assert-superblock-all-zeroes md) + (with-bcache (cache md 1) + (with-block (b cache 0 (get-flags)) + (unless (all-zeroes? (block-data b) 4096) +diff --git a/functional-tests/thin-functional-tests.scm b/functional-tests/thin-functional-tests.scm +index d096b78..6bb7d24 100644 +--- a/functional-tests/thin-functional-tests.scm ++++ b/functional-tests/thin-functional-tests.scm +@@ -37,10 +37,12 @@ + b1 b2 ...))))) + + ;;; 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 + (syntax-rules () + ((_ (md) b1 b2 ...) + (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 ...)))) + + (define-syntax with-empty-metadata +@@ -167,7 +169,7 @@ + "the input file can't be found" + (with-empty-metadata (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)))) + + (define-scenario (thin-restore garbage-input-file) +@@ -175,7 +177,7 @@ + (with-empty-metadata (md) + (with-temp-file-sized ((xml "thin.xml" 4096)) + (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) + "the output file can't be found" +@@ -333,4 +335,25 @@ + (with-empty-metadata (md) + (run-fail-rcv (_ stderr) (thin-repair "-i" xml "-o" md) + #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)))) ++ + ) +diff --git a/thin-provisioning/thin_repair.cc b/thin-provisioning/thin_repair.cc +index e22b193..0673753 100644 +--- a/thin-provisioning/thin_repair.cc ++++ b/thin-provisioning/thin_repair.cc +@@ -2,6 +2,7 @@ + #include + #include + ++#include "base/file_utils.h" + #include "base/output_file_requirements.h" + #include "persistent-data/file_utils.h" + #include "thin-provisioning/commands.h" +@@ -17,15 +18,20 @@ using namespace thin_provisioning; + + namespace { + int repair(string const &old_path, string const &new_path) { ++ bool metadata_touched = false; + try { + // block size gets updated by the restorer + block_manager<>::ptr new_bm = open_bm(new_path, block_manager<>::READ_WRITE); ++ file_utils::check_file_exists(old_path, false); ++ metadata_touched = true; + metadata::ptr new_md(new metadata(new_bm, metadata::CREATE, 128, 0)); + emitter::ptr e = create_restore_emitter(new_md); + block_manager<>::ptr old_bm = open_bm(old_path, block_manager<>::READ_ONLY); + metadata_repair(old_bm, e); + + } catch (std::exception &e) { ++ if (metadata_touched) ++ file_utils::zero_superblock(new_path); + cerr << e.what() << endl; + return 1; + } +@@ -101,7 +107,7 @@ thin_repair_cmd::run(int argc, char **argv) + check_output_file_requirements(*output_path); + + else { +- cerr << "no output file provided" << endl; ++ cerr << "No output file provided." << endl; + usage(cerr); + return 1; + } diff --git a/SPECS/device-mapper-persistent-data.spec b/SPECS/device-mapper-persistent-data.spec index acdfb28..92a8f01 100644 --- a/SPECS/device-mapper-persistent-data.spec +++ b/SPECS/device-mapper-persistent-data.spec @@ -5,13 +5,16 @@ Summary: Device-mapper Persistent Data Tools Name: device-mapper-persistent-data Version: 0.8.5 -Release: 2%{?dist} +Release: 3%{?dist} License: GPLv3+ Group: System Environment/Base URL: https://github.com/jthornber/thin-provisioning-tools #Source0: https://github.com/jthornber/thin-provisioning-tools/archive/thin-provisioning-tools-% {version}.tar.gz Source0: https://github.com/jthornber/thin-provisioning-tools/archive/v%{version}.tar.gz Patch0: device-mapper-persistent-data-avoid-strip.patch +Patch1: dmpd-remove-pool-inactive-from-thin_trim-man-page.patch +Patch2: dmpd-thin_repair-cache_repair-Check-input-file-exists-earlier.patch +Patch3: dmpd-tests-lib-bcache-rename-raise-raise_.patch BuildRequires: autoconf, expat-devel, libaio-devel, libstdc++-devel, boost-devel, gcc-c++ Requires: expat @@ -27,6 +30,9 @@ snapshot eras %prep %setup -q -n thin-provisioning-tools-%{version} %patch0 -p1 -b .avoid_strip +%patch1 -p1 -b .remove_pool_inactive_option +%patch2 -p1 -b .check_input_file_erlier +%patch3 -p1 -b .backup3 echo %{version}-%{release} > VERSION %build @@ -83,6 +89,10 @@ make DESTDIR=%{buildroot} MANDIR=%{_mandir} install #% {_sbindir}/thin_show_duplicates %changelog +* Wed Nov 27 2019 Marian Csontos - 0.8.5-3 +- Remove obsolete pool-inactive option from thin_trim man page. +- Check input file exists eralier, and prevent writing incorrect metadata. + * Tue Jun 04 2019 Marian Csontos - 0.8.5-2 - Bump release