From: David Zafman Date: Thu, 8 Oct 2015 00:25:44 +0000 (-0700) Subject: ceph-objectstore-tool: Add undocumented clear-snapset command for testing X-Git-Tag: v0.94.7~28^2~1^2~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7b800b7c3efb5403d03fc0c4386821b433b85268;p=ceph.git ceph-objectstore-tool: Add undocumented clear-snapset command for testing Add test cases using new feature to corrupt SnapSet Signed-off-by: David Zafman (cherry picked from commit b6302acdd344997aabdb426104de9f24e9990437) No Sequencer in transactions in Hammer --- diff --git a/src/test/ceph_objectstore_tool.py b/src/test/ceph_objectstore_tool.py index 49f28ec883e6..e30f3bb1764c 100755 --- a/src/test/ceph_objectstore_tool.py +++ b/src/test/ceph_objectstore_tool.py @@ -862,6 +862,27 @@ def main(argv): cmd = (CFSD_PREFIX + "--pgid {pg} '' notacommand").format(osd=ONEOSD, pg=ONEPG) ERRORS += test_failure(cmd, "Unknown object command 'notacommand'") + cmd = (CFSD_PREFIX + "foo list-omap").format(osd=ONEOSD, pg=ONEPG) + ERRORS += test_failure(cmd, "No object id 'foo' found or invalid JSON specified") + + cmd = (CFSD_PREFIX + "'{{\"oid\":\"obj4\",\"key\":\"\",\"snapid\":-1,\"hash\":2826278768,\"max\":0,\"pool\":1,\"namespace\":\"\"}}' list-omap").format(osd=ONEOSD, pg=ONEPG) + ERRORS += test_failure(cmd, "Without --pgid the object '{\"oid\":\"obj4\",\"key\":\"\",\"snapid\":-1,\"hash\":2826278768,\"max\":0,\"pool\":1,\"namespace\":\"\"}' must be a JSON array") + + cmd = (CFSD_PREFIX + "'[]' list-omap").format(osd=ONEOSD, pg=ONEPG) + ERRORS += test_failure(cmd, "Object '[]' must be a JSON array with 2 elements") + + cmd = (CFSD_PREFIX + "'[\"1.0\"]' list-omap").format(osd=ONEOSD, pg=ONEPG) + ERRORS += test_failure(cmd, "Object '[\"1.0\"]' must be a JSON array with 2 elements") + + cmd = (CFSD_PREFIX + "'[\"1.0\", 5, 8, 9]' list-omap").format(osd=ONEOSD, pg=ONEPG) + ERRORS += test_failure(cmd, "Object '[\"1.0\", 5, 8, 9]' must be a JSON array with 2 elements") + + cmd = (CFSD_PREFIX + "'[1, 2]' list-omap").format(osd=ONEOSD, pg=ONEPG) + ERRORS += test_failure(cmd, "Object '[1, 2]' must be a JSON array with the first element a string") + + cmd = (CFSD_PREFIX + "'[\"1.3\",{{\"snapid\":\"not an int\"}}]' list-omap").format(osd=ONEOSD, pg=ONEPG) + ERRORS += test_failure(cmd, "Decode object JSON error: value type is 2 not 4") + TMPFILE = r"/tmp/tmp.{pid}".format(pid=pid) ALLPGS = OBJREPPGS + OBJECPGS OSDS = get_osds(ALLPGS[0], OSDDIR) diff --git a/src/test/osd/osd-scrub-snaps.sh b/src/test/osd/osd-scrub-snaps.sh index 51f08c8d7c6b..fbc93be8f446 100755 --- a/src/test/osd/osd-scrub-snaps.sh +++ b/src/test/osd/osd-scrub-snaps.sh @@ -27,7 +27,7 @@ wait_for_health ./ceph osd pool create test 1 1 dd if=/dev/urandom of=$TESTDATA bs=1032 count=1 -for i in `seq 1 5` +for i in `seq 1 14` do ./rados -p test put obj${i} $TESTDATA done @@ -38,6 +38,9 @@ dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP} ./rados -p test put obj1 $TESTDATA ./rados -p test put obj5 $TESTDATA ./rados -p test put obj3 $TESTDATA +for i in `seq 6 14` + do ./rados -p test put obj${i} $TESTDATA +done SNAP=2 ./rados -p test mksnap snap${SNAP} @@ -102,6 +105,25 @@ dd if=/dev/urandom of=$TESTDATA bs=256 count=7 rm -f $TESTDATA +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj6 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj7 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset corrupt +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj8 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset seq +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj9 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset clone_size +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj10 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset clone_overlap +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj11 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset clones +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj12 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset head +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj13 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset snaps +JSON="$(./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal --op list obj14 | grep \"snapid\":-2)" +./ceph-objectstore-tool --data-path dev/osd0 --journal-path dev/osd0.journal "$JSON" clear-snapset size + #MDS=0 MON=1 OSD=1 ./vstart.sh -l -d -o "osd_pool_default_size=1" ./ceph-osd -i 0 -c ceph.conf wait_for_health @@ -115,20 +137,30 @@ timeout 30 ./ceph -w ERRORS=0 declare -a err_strings -err_strings[0]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/6cf8deff/obj1/1 is an unexpected clone" +err_strings[0]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/2acecc8b/obj10/1 is missing in clone_overlap" err_strings[1]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/666934a3/obj5/7 no '_' attr" err_strings[2]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/666934a3/obj5/7 is an unexpected clone" -err_strings[3]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/666934a3/obj5/head expected clone 1/666934a3/obj5/2" -err_strings[4]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/666934a3/obj5/head expected clone 1/666934a3/obj5/1" -err_strings[5]="log_channel[(]cluster[)] log [[]INF[]] : scrub 1.0 1/666934a3/obj5/head missing clones" -err_strings[6]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/3f1ee208/obj2/snapdir no 'snapset' attr" -err_strings[7]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/3f1ee208/obj2/7 is an unexpected clone" -err_strings[8]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/3f1ee208/obj2/4 is an unexpected clone" -err_strings[9]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/a8759770/obj4/snapdir expected clone 1/a8759770/obj4/7" -err_strings[10]="log_channel[(]cluster[)] log [[]INF[]] : scrub 1.0 1/a8759770/obj4/snapdir missing clones" -err_strings[11]="log_channel[(]cluster[)] log [[]ERR[]] : 1.0 scrub 12 errors" -err_strings[12]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/666934a3/obj5/4 on disk size [(]4608[)] does not match object info size [(]512[)] adjusted for ondisk to [(]512[)]" -err_strings[13]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/61f68bb1/obj3/head on disk size [(]3840[)] does not match object info size [(]768[)] adjusted for ondisk to [(]768[)]" +err_strings[3]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/666934a3/obj5/4 on disk size [(]4608[)] does not match object info size [(]512[)] adjusted for ondisk to [(]512[)]" +err_strings[4]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/666934a3/obj5/head expected clone 1/666934a3/obj5/2" +err_strings[5]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/666934a3/obj5/head expected clone 1/666934a3/obj5/1" +err_strings[6]="log_channel[(]cluster[)] log [[]INF[]] : scrub 1.0 1/666934a3/obj5/head missing clones" +err_strings[7]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/d3a9faf5/obj12/head snapset.head_exists=false, but head exists" +err_strings[8]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/7c6b5865/obj13/head snaps empty" +err_strings[9]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/8df7eaa5/obj8/head snaps.seq not set" +err_strings[10]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/5c889059/obj7/head snapset.head_exists=false, but head exists" +err_strings[11]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/5c889059/obj7/1 is an unexpected clone" +err_strings[12]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/61f68bb1/obj3/head on disk size [(]3840[)] does not match object info size [(]768[)] adjusted for ondisk to [(]768[)]" +err_strings[13]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/83425cc4/obj6/1 is an unexpected clone" +err_strings[14]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/3f1ee208/obj2/snapdir no 'snapset' attr" +err_strings[15]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/3f1ee208/obj2/7 is an unexpected clone" +err_strings[16]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/3f1ee208/obj2/4 is an unexpected clone" +err_strings[17]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/a8759770/obj4/snapdir expected clone 1/a8759770/obj4/7" +err_strings[18]="log_channel[(]cluster[)] log [[]INF[]] : scrub 1.0 1/a8759770/obj4/snapdir missing clones" +err_strings[19]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/6cf8deff/obj1/1 is an unexpected clone" +err_strings[20]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/e478ac7f/obj9/1 is missing in clone_size" +err_strings[21]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/29547577/obj11/1 is an unexpected clone" +err_strings[22]="log_channel[(]cluster[)] log [[]ERR[]] : scrub 1.0 1/94122507/obj14/1 size 1032 != clone_size 1033" +err_strings[23]="log_channel[(]cluster[)] log [[]ERR[]] : 1.0 scrub 22 errors" for i in `seq 0 ${#err_strings[@]}` do diff --git a/src/tools/ceph_objectstore_tool.cc b/src/tools/ceph_objectstore_tool.cc index 448bc9ce91ca..8748c372c64c 100644 --- a/src/tools/ceph_objectstore_tool.cc +++ b/src/tools/ceph_objectstore_tool.cc @@ -2824,6 +2824,60 @@ int set_size(ObjectStore *store, coll_t coll, ghobject_t &ghobj, uint64_t setsiz return 0; } +int clear_snapset(ObjectStore *store, coll_t coll, ghobject_t &ghobj, + string arg) +{ + SnapSet ss; + int ret = get_snapset(store, coll, ghobj, ss); + if (ret < 0) + return ret; + + // Use "head" to set head_exists incorrectly + if (arg == "corrupt" || arg == "head") + ss.head_exists = !ghobj.hobj.is_head(); + else if (ss.head_exists != ghobj.hobj.is_head()) { + cerr << "Correcting head_exists, set to " + << (ghobj.hobj.is_head() ? "true" : "false") << std::endl; + ss.head_exists = ghobj.hobj.is_head(); + } + // Use "corrupt" to clear entire SnapSet + // Use "seq" to just corrupt SnapSet.seq + if (arg == "corrupt" || arg == "seq") + ss.seq = 0; + // Use "snaps" to just clear SnapSet.snaps + if (arg == "corrupt" || arg == "snaps") + ss.snaps.clear(); + // By default just clear clone, clone_overlap and clone_size + if (arg == "corrupt") + arg = ""; + if (arg == "" || arg == "clones") + ss.clones.clear(); + if (arg == "" || arg == "clone_overlap") + ss.clone_overlap.clear(); + if (arg == "" || arg == "clone_size") + ss.clone_size.clear(); + // Break all clone sizes by adding 1 + if (arg == "size") { + for (map::iterator i = ss.clone_size.begin(); + i != ss.clone_size.end(); ++i) + ++(i->second); + } + + if (!dry_run) { + bufferlist bl; + ::encode(ss, bl); + ObjectStore::Transaction t; + t.setattr(coll, ghobj, SS_ATTR, bl); + int r = store->apply_transaction(t); + if (r < 0) { + cerr << "Error setting snapset on : " << make_pair(coll, ghobj) << ", " + << cpp_strerror(r) << std::endl; + return r; + } + } + return 0; +} + void usage(po::options_description &desc) { cerr << std::endl; @@ -3793,6 +3847,16 @@ int main(int argc, char **argv) uint64_t size = atoll(arg1.c_str()); ret = set_size(fs, coll, ghobj, size, formatter); goto out; + } else if (objcmd == "clear-snapset") { + // UNDOCUMENTED: For testing zap SnapSet + // IGNORE extra args since not in usage anyway + if (!ghobj.hobj.has_snapset()) { + cerr << "'" << objcmd << "' requires a head or snapdir object" << std::endl; + ret = 1; + goto out; + } + ret = clear_snapset(fs, coll, ghobj, arg1); + goto out; } cerr << "Unknown object command '" << objcmd << "'" << std::endl; usage(desc);