]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/cephfs: make 'cephfs-data-scan scan_links' fix dentry's first 31680/head
authorYan, Zheng <zyan@redhat.com>
Fri, 15 Nov 2019 15:59:44 +0000 (23:59 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 15 Nov 2019 17:11:05 +0000 (01:11 +0800)
Dentries injected by 'cephfs-data-scan foo' have 'first == CEPH_NOSNAP'.
This confuses mimic and later version MDS, and can cause them to crash.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
Fixes: https://tracker.ceph.com/issues/42829
src/tools/cephfs/DataScan.cc
src/tools/cephfs/DataScan.h

index 4dfbe48ccd9ffb55a59af099b628082a38ec69f0..8fb670ad08e62a59186ac40a552a4933020c72ff 100644 (file)
@@ -931,6 +931,7 @@ int DataScan::scan_links()
   };
   map<inodeno_t, list<link_info_t> > dup_primaries;
   map<inodeno_t, link_info_t> bad_nlink_inos;
+  map<inodeno_t, link_info_t> injected_inos;
 
   map<dirfrag_t, set<string> > to_remove;
 
@@ -973,8 +974,11 @@ int DataScan::scan_links()
        snapid_t last;
        dentry_key_t::decode_helper(p.first, dname, last);
 
-       if (last != CEPH_NOSNAP)
+       if (last != CEPH_NOSNAP) {
+         if (last > last_snap)
+           last_snap = last;
          continue;
+       }
 
        try {
          snapid_t dnfirst;
@@ -1040,6 +1044,8 @@ int DataScan::scan_links()
                snaps.insert(make_move_iterator(begin(srnode.snaps)),
                             make_move_iterator(end(srnode.snaps)));
              }
+             if (dnfirst == CEPH_NOSNAP)
+               injected_inos[ino] = link_info_t(dir_ino, frag_id, dname, inode.inode);
            }
          } else if (dentry_type == 'L') {
            inodeno_t ino;
@@ -1142,6 +1148,23 @@ int DataScan::scan_links()
   dup_primaries.clear();
   remote_links.clear();
 
+  {
+    objecter->with_osdmap([&](const OSDMap& o) {
+      for (auto p : data_pools) {
+       const pg_pool_t *pi = o.get_pg_pool(p);
+       if (!pi)
+         continue;
+       if (pi->snap_seq > last_snap)
+         last_snap = pi->snap_seq;
+      }
+    });
+
+    if (!snaps.empty()) {
+      if (snaps.rbegin()->first > last_snap)
+       last_snap = snaps.rbegin()->first;
+    }
+  }
+
   for (auto& p : to_remove) {
     object_t frag_oid = InodeStore::get_object_name(p.first.ino, p.first.frag, "");
 
@@ -1155,7 +1178,8 @@ int DataScan::scan_links()
 
   for (auto &p : bad_nlink_inos) {
     InodeStore inode;
-    int r = read_dentry(p.second.dirino, p.second.frag, p.second.name, &inode);
+    snapid_t first;
+    int r = read_dentry(p.second.dirino, p.second.frag, p.second.name, &inode, &first);
     if (r < 0) {
       derr << "Unexpected error reading dentry "
           << p.second.dirfrag() << "/" << p.second.name
@@ -1167,7 +1191,27 @@ int DataScan::scan_links()
       continue;
 
     inode.inode.nlink = p.second.nlink;
-    r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode);
+    r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode, first);
+    if (r < 0)
+      return r;
+  }
+
+  for (auto &p : injected_inos) {
+    InodeStore inode;
+    snapid_t first;
+    int r = read_dentry(p.second.dirino, p.second.frag, p.second.name, &inode, &first);
+    if (r < 0) {
+      derr << "Unexpected error reading dentry "
+       << p.second.dirfrag() << "/" << p.second.name
+       << ": " << cpp_strerror(r) << dendl;
+      return r;
+    }
+
+    if (first != CEPH_NOSNAP)
+      continue;
+
+    first = last_snap + 1;
+    r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode, first);
     if (r < 0)
       return r;
   }
@@ -1191,21 +1235,6 @@ int DataScan::scan_links()
   }
 
   {
-    objecter->with_osdmap([&](const OSDMap& o) {
-      for (auto p : data_pools) {
-       const pg_pool_t *pi = o.get_pg_pool(p);
-       if (!pi)
-         continue;
-       if (pi->snap_seq > last_snap)
-         last_snap = pi->snap_seq;
-      }
-    });
-
-    if (!snaps.empty()) {
-      if (snaps.rbegin()->first > last_snap)
-       last_snap = snaps.rbegin()->first;
-    }
-
     SnapServer snaptable;
     snaptable.set_rank(0);
     bool dirty = false;
@@ -1410,11 +1439,10 @@ int MetadataTool::read_fnode(
 }
 
 int MetadataTool::read_dentry(inodeno_t parent_ino, frag_t frag,
-                const std::string &dname, InodeStore *inode)
+                const std::string &dname, InodeStore *inode, snapid_t *dnfirst)
 {
   ceph_assert(inode != NULL);
 
-
   std::string key;
   dentry_key_t dn_key(CEPH_NOSNAP, dname.c_str());
   dn_key.encode(key);
@@ -1439,18 +1467,19 @@ int MetadataTool::read_dentry(inodeno_t parent_ino, frag_t frag,
 
   try {
     auto q = vals[key].cbegin();
-    snapid_t dnfirst;
-    decode(dnfirst, q);
+    snapid_t first;
+    decode(first, q);
     char dentry_type;
     decode(dentry_type, q);
     if (dentry_type == 'I') {
       inode->decode_bare(q);
-      return 0;
     } else {
       dout(20) << "dentry type '" << dentry_type << "': cannot"
                   "read an inode out of that" << dendl;
       return -EINVAL;
     }
+    if (dnfirst)
+      *dnfirst = first;
   } catch (const buffer::error &err) {
     dout(20) << "encoding error in dentry 0x" << std::hex << parent_ino
              << std::dec << "/" << dname << dendl;
@@ -1913,20 +1942,16 @@ int MetadataDriver::find_or_create_dirfrag(
 
 int MetadataDriver::inject_linkage(
     inodeno_t dir_ino, const std::string &dname,
-    const frag_t fragment, const InodeStore &inode)
+    const frag_t fragment, const InodeStore &inode, const snapid_t dnfirst)
 {
-  // We have no information about snapshots, so everything goes
-  // in as CEPH_NOSNAP
-  snapid_t snap = CEPH_NOSNAP;
-
   object_t frag_oid = InodeStore::get_object_name(dir_ino, fragment, "");
 
   std::string key;
-  dentry_key_t dn_key(snap, dname.c_str());
+  dentry_key_t dn_key(CEPH_NOSNAP, dname.c_str());
   dn_key.encode(key);
 
   bufferlist dentry_bl;
-  encode(snap, dentry_bl);
+  encode(dnfirst, dentry_bl);
   encode('I', dentry_bl);
   inode.encode_bare(dentry_bl, CEPH_FEATURES_SUPPORTED_DEFAULT);
 
index dd064492d01e7eb627c0eecfe8af76e1ddb2fdee..5c87fe2bdec4a89a169209ba49445f8e3964d5be 100644 (file)
@@ -174,7 +174,7 @@ class MetadataTool
    * Try and read a dentry from a dirfrag
    */
   int read_dentry(inodeno_t parent_ino, frag_t frag,
-                  const std::string &dname, InodeStore *inode);
+                 const std::string &dname, InodeStore *inode, snapid_t *dnfirst=nullptr);
 };
 
 /**
@@ -220,7 +220,7 @@ class MetadataDriver : public RecoveryDriver, public MetadataTool
 
     int inject_linkage(
         inodeno_t dir_ino, const std::string &dname,
-        const frag_t fragment, const InodeStore &inode);
+        const frag_t fragment, const InodeStore &inode, snapid_t dnfirst=CEPH_NOSNAP);
 
     int inject_with_backtrace(
         const inode_backtrace_t &bt,