]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
MDCache: add a scrub_dentry() function, and wire it up to the admin socket
authorGreg Farnum <greg@inktank.com>
Fri, 11 Jul 2014 22:20:32 +0000 (15:20 -0700)
committerGreg Farnum <gfarnum@redhat.com>
Fri, 7 Nov 2014 20:42:14 +0000 (12:42 -0800)
scrub_dentry() is passed a string path, and it validates it before replying. We
hook up an admin socket command "scrub_path" to call it and dump the output.

Signed-off-by: Greg Farnum <greg@inktank.com>
src/include/ceph_fs.h
src/mds/MDCache.cc
src/mds/MDCache.h
src/mds/MDS.cc
src/mds/MDS.h

index 10b52a5033abe1792e069e1e03331e74e162ede8..cf6148eee9497dc778341345db2aee5858669625 100644 (file)
@@ -340,6 +340,7 @@ enum {
        // internal op
        CEPH_MDS_OP_FRAGMENTDIR= 0x01500,
        CEPH_MDS_OP_EXPORTDIR  = 0x01501,
+       CEPH_MDS_OP_VALIDATE   = 0x01502
 };
 
 extern const char *ceph_mds_op_name(int op);
index 20318cc36332b17c80da5a24fd0e80898f7b44b4..c52a90b8b3a483c5ea6714a3ba16b74eb237d1bb 100644 (file)
@@ -11493,3 +11493,43 @@ void C_MDS_RetryRequest::finish(int r)
   mdr->retry++;
   cache->dispatch_request(mdr);
 }
+
+class C_scrub_dentry_finish : public Context {
+public:
+  CInode::validated_data results;
+  MDCache *mdcache;
+  MDRequestRef mdr;
+  Context *on_finish;
+  Formatter *formatter;
+  C_scrub_dentry_finish(MDCache *mdc, MDRequestRef& mdr,
+                        Context *fin, Formatter *f) :
+    mdcache(mdc), mdr(mdr), on_finish(fin), formatter(f) {}
+
+  void finish(int r) {
+    CInode::dump_validation_results(results, formatter);
+    mdcache->request_finish(mdr);
+    on_finish->complete(r);
+  }
+};
+
+void MDCache::scrub_dentry(const string& path, Formatter *f, Context *fin)
+{
+  dout(10) << "scrub_dentry " << path << dendl;
+  MDRequestRef mdr = request_start_internal(CEPH_MDS_OP_VALIDATE);
+  set<SimpleLock*> rdlocks, wrlocks, xlocks;
+  filepath fp(path.c_str());
+  mdr->set_filepath(fp);
+
+  // TODO: this is not actually safe with multiple MDSes!
+  CInode *in = mds->server->rdlock_path_pin_ref(mdr, 0, rdlocks, true);
+  assert(in != NULL); // TODO: obviously can't keep this, but it helps ensure authness
+  assert(in->is_auth());
+
+  bool locked = mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks);
+  if (!locked)
+    return;
+  C_scrub_dentry_finish *finisher = new C_scrub_dentry_finish(this, mdr,
+                                                              fin, f);
+  in->validate_disk_state(&finisher->results, finisher);
+  return;
+}
index 812b4ec2402c143b4393d22ef8e5a6e2a55c47ed..bd991f618a8ab8aff9e426f38430b535ddc9f3a0 100644 (file)
@@ -1032,7 +1032,7 @@ public:
     while (n--) ++p;
     return p->second;
   }
-
+  void scrub_dentry(const string& path, Formatter *f, Context *fin);
 };
 
 class C_MDS_RetryRequest : public MDSInternalContext {
index 5661fb51dc043deb407f190cd0b1d5f301292b56..74d81f1df44d37f998608ab099b5252e6d941049 100644 (file)
@@ -286,12 +286,27 @@ bool MDS::asok_command(string command, cmdmap_t& cmdmap, string format,
       dout(15) << "session " << session << " not in sessionmap!" << dendl;
       mds_lock.Unlock();
     }
+  } else if (command == "scrub_path") {
+    string path;
+    cmd_getval(g_ceph_context, cmdmap, "path", path);
+    command_scrub_path(f, path);
   }
   f->flush(ss);
   delete f;
   return true;
 }
 
+void MDS::command_scrub_path(Formatter *f, const string& path)
+{
+  C_SaferCond scond;
+  {
+    Mutex::Locker l(mds_lock);
+    mdcache->scrub_dentry(path, f, &scond);
+  }
+  scond.wait();
+  // scrub_dentry() finishers will dump the data for us; we're done!
+}
+
 void MDS::set_up_admin_socket()
 {
   int r;
@@ -307,6 +322,10 @@ void MDS::set_up_admin_socket()
   r = admin_socket->register_command("dump_historic_ops", "dump_historic_ops",
                                     asok_hook,
                                     "show slowest recent ops");
+  r = admin_socket->register_command("scrub_path",
+                                     "scrub_path name=path,type=CephString",
+                                     asok_hook,
+                                     "scrub an inode and output results");
   assert(0 == r);
   r = admin_socket->register_command("session evict",
                                     "session evict name=client_id,type=CephString",
@@ -326,6 +345,7 @@ void MDS::clean_up_admin_socket()
   admin_socket->unregister_command("status");
   admin_socket->unregister_command("dump_ops_in_flight");
   admin_socket->unregister_command("dump_historic_ops");
+  admin_socket->unregister_command("scrub_path");
   delete asok_hook;
   asok_hook = NULL;
 }
index a51a5f9b032dc6121ab72c55f43f70e4eea2a385..aac6e6760a947e774289db866e50e70b701b2c11 100644 (file)
@@ -375,6 +375,7 @@ private:
   void set_up_admin_socket();
   void clean_up_admin_socket();
   void check_ops_in_flight(); // send off any slow ops to monitor
+  void command_scrub_path(Formatter *f, const string& path);
     // config observer bits
   virtual const char** get_tracked_conf_keys() const;
   virtual void handle_conf_change(const struct md_config_t *conf,