]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/cephfs: use xattr layout if present+valid
authorJohn Spray <john.spray@redhat.com>
Mon, 3 Aug 2015 13:54:37 +0000 (14:54 +0100)
committerJohn Spray <john.spray@redhat.com>
Thu, 13 Aug 2015 13:28:53 +0000 (14:28 +0100)
So that in cases where files had an unguessable (e.g.
striped) layout, but they were lucky enough to
have the layout stashed in their xattr, we can
provide the correct layout on recovery.

Signed-off-by: John Spray <john.spray@redhat.com>
src/tools/cephfs/DataScan.cc

index 8269c0880036a7a77a666c6ccd7cb4da7804a3f3..4fc563c9fcfd787e80cd0d7afea0cac5ee54a945 100644 (file)
@@ -491,12 +491,17 @@ int DataScan::scan_inodes()
 
     AccumulateResult accum_res;
     inode_backtrace_t backtrace;
+    ceph_file_layout loaded_layout = g_default_file_layout;
     int r = ClsCephFSClient::fetch_inode_accumulate_result(
-        data_io, oid, &backtrace, &accum_res);
+        data_io, oid, &backtrace, &loaded_layout, &accum_res);
     
     if (r < 0) {
       dout(4) << "Unexpected error loading accumulated metadata from '"
               << oid << "': " << cpp_strerror(r) << dendl;
+      // FIXME: this creates situation where if a client has a corrupt
+      // backtrace/layout, we will fail to inject it.  We should (optionally)
+      // proceed if the backtrace/layout is corrupt but we have valid
+      // accumulated metadata.
       continue;
     }
 
@@ -505,6 +510,11 @@ int DataScan::scan_inodes()
     uint32_t chunk_size = g_default_file_layout.fl_object_size;
     bool have_backtrace = !(backtrace.ancestors.empty());
 
+    // This is the layout we will use for injection, populated either
+    // from loaded_layout or from best guesses
+    ceph_file_layout guessed_layout;
+    guessed_layout.fl_pg_pool = data_pool_id;
+
     // Calculate file_size, guess chunk_size
     if (accum_res.ceiling_obj_index > 0) {
       // When there are multiple objects, the largest object probably
@@ -515,7 +525,27 @@ int DataScan::scan_inodes()
         chunk_size = accum_res.max_obj_size;
       }
 
-      file_size = chunk_size * accum_res.ceiling_obj_index
+      if (loaded_layout.fl_pg_pool == uint32_t(-1)) {
+        // If no stashed layout was found, guess it
+        guessed_layout.fl_object_size = chunk_size;
+        guessed_layout.fl_stripe_unit = chunk_size;
+      } else if (loaded_layout.fl_object_size < accum_res.max_obj_size) {
+        // If the max size seen exceeds what the stashed layout claims, then
+        // disbelieve it.  Guess instead.
+        dout(4) << "bogus xattr layout on 0x" << std::hex << obj_name_ino
+                << std::dec << ", ignoring in favour of best guess" << dendl;
+        guessed_layout.fl_object_size = chunk_size;
+        guessed_layout.fl_stripe_unit = chunk_size;
+      } else {
+        // We have a stashed layout that we can't disprove, so apply it
+        guessed_layout = loaded_layout;
+        // User might have transplanted files from a pool with a different
+        // ID, so whatever the loaded_layout says, we'll force the injected
+        // layout to point to the pool we really read from
+        guessed_layout.fl_pg_pool = data_pool_id;
+      }
+
+      file_size = guessed_layout.fl_object_size * accum_res.ceiling_obj_index
                   + accum_res.ceiling_obj_size;
     } else {
       file_size = accum_res.ceiling_obj_size;