]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: write scrub tag during validation
authorJohn Spray <john.spray@redhat.com>
Thu, 16 Jul 2015 12:45:45 +0000 (13:45 +0100)
committerYan, Zheng <zyan@redhat.com>
Wed, 4 Nov 2015 09:17:25 +0000 (17:17 +0800)
Signed-off-by: John Spray <john.spray@redhat.com>
src/mds/CInode.cc

index 4ba3ca4a9ccc2ad0aa0c590f828d49d6da0f9e71..6a0c1e1b3f0512c0b677e4731ab39e5adae13b19 100644 (file)
@@ -3685,6 +3685,40 @@ void CInode::validate_disk_state(CInode::validated_data *results,
       delete shadow_in;
     }
 
+    /**
+     * Fetch backtrace and set tag if tag is non-empty
+     */
+    void fetch_backtrace_and_tag(CInode *in, std::string tag,
+                                 Context *fin, int *bt_r, bufferlist *bt)
+    {
+      int64_t pool;
+      if (in->is_dir())
+        pool = in->mdcache->mds->mdsmap->get_metadata_pool();
+      else
+        pool = in->inode.layout.fl_pg_pool;
+
+      object_t oid = CInode::get_object_name(in->ino(), frag_t(), "");
+
+      ObjectOperation fetch;
+
+      fetch.getxattr("parent", bt, bt_r);
+      // We want to tag even if we get ENODATA fetching the backtrace
+      fetch.set_last_op_flags(CEPH_OSD_OP_FLAG_FAILOK);
+      if (!tag.empty()) {
+        bufferlist tag_bl;
+        ::encode(tag, tag_bl);
+        fetch.setxattr("scrub_tag", tag_bl);
+      }
+      if (tag.empty()) {
+        in->mdcache->mds->objecter->read(oid, object_locator_t(pool), fetch, CEPH_NOSNAP,
+            NULL, 0, fin);
+      } else {
+        SnapContext snapc;
+        in->mdcache->mds->objecter->mutate(oid, object_locator_t(pool), fetch, snapc,
+            ceph_clock_now(g_ceph_context), 0, NULL, fin);
+      }
+    }
+
     bool _start(int rval) {
       if (in->is_dirty()) {
         MDCache *mdcache = in->mdcache;
@@ -3703,7 +3737,12 @@ void CInode::validate_disk_state(CInode::validated_data *results,
       C_OnFinisher *conf = new C_OnFinisher(get_io_callback(BACKTRACE),
                                             in->mdcache->mds->finisher);
 
-      in->fetch_backtrace(conf, &bl);
+      // Rather than using the usual CInode::fetch_backtrace,
+      // use a special variant that optionally writes a tag in the same
+      // operation.
+      const std::string &tag = in->get_parent_dn()->scrub_info()->header->tag;
+      fetch_backtrace_and_tag(in, tag, conf,
+                              &results->backtrace.ondisk_read_retval, &bl);
       return false;
     }
 
@@ -3711,9 +3750,12 @@ void CInode::validate_disk_state(CInode::validated_data *results,
       // set up basic result reporting and make sure we got the data
       results->performed_validation = true; // at least, some of it!
       results->backtrace.checked = true;
-      results->backtrace.ondisk_read_retval = rval;
       results->backtrace.passed = false; // we'll set it true if we make it
-      if (rval != 0) {
+
+      // Ignore rval because it's the result of a FAILOK operation
+      // from fetch_backtrace_and_tag: the real result is in
+      // backtrace.ondisk_read_retval
+      if (results->backtrace.ondisk_read_retval != 0) {
         results->backtrace.error_str << "failed to read off disk; see retval";
         return true;
       }
@@ -3722,9 +3764,10 @@ void CInode::validate_disk_state(CInode::validated_data *results,
       try {
         bufferlist::iterator p = bl.begin();
         ::decode(results->backtrace.ondisk_value, p);
-      } catch (buffer::malformed_input&) {
+      } catch (buffer::error&) {
         results->backtrace.passed = false;
-        results->backtrace.error_str << "failed to decode on-disk backtrace!";
+        results->backtrace.error_str << "failed to decode on-disk backtrace ("
+                                     << bl.length() << " bytes)!";
         return true;
       }
       int64_t pool;