]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: debug support for omap deep-scrub
authorDavid Zafman <david.zafman@inktank.com>
Tue, 15 Jan 2013 00:37:09 +0000 (16:37 -0800)
committerDavid Zafman <david.zafman@inktank.com>
Tue, 22 Jan 2013 23:57:01 +0000 (15:57 -0800)
Deep-scrub test support through admin socket

Signed-off-by: David Zafman <david.zafman@inktank.com>
Reviewed-by: Samuel Just <sam.just@inktank.com>
src/common/ceph_argparse.cc
src/common/ceph_argparse.h
src/osd/OSD.cc
src/osd/OSD.h
src/osd/OSDMap.h

index 646931acdc9ee54d4e8a48d2b48b37456328ee92..f26fe93b656d2c3d3aeb30ad375d73145a0ddac2 100644 (file)
 #undef generic_dout
 #undef dendl
 
+void string_to_vec(std::vector<std::string>& args, std::string argstr)
+{
+  istringstream iss(argstr);
+  while(iss) {
+    string sub;
+    iss >> sub;
+    if (sub == "") break;
+    args.push_back(sub);
+  }
+}
+
 void env_to_vec(std::vector<const char*>& args, const char *name)
 {
   if (!name)
index fd9439c5627186579130c6a07d9191a408ed88a3..3ef0251abeb8762bf378c7e0599745384d180e71 100644 (file)
@@ -43,6 +43,7 @@ public:
 };
 
 /////////////////////// Functions ///////////////////////
+extern void string_to_vec(std::vector<std::string>& args, std::string argstr);
 extern void env_to_vec(std::vector<const char*>& args, const char *name=NULL);
 extern void argv_to_vec(int argc, const char **argv,
                  std::vector<const char*>& args);
index 0d289f6c8751cdab866a88cd9fa5d8fa73e09799..34ec3678f08911c017aa9f3b7c980bebbdbd043f 100644 (file)
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <signal.h>
+#include <ctype.h>
 #include <boost/scoped_ptr.hpp>
 
 #if defined(DARWIN) || defined(__FreeBSD__)
@@ -869,6 +870,22 @@ public:
   }
 };
 
+class TestOpsSocketHook : public AdminSocketHook {
+  OSDService *service;
+  ObjectStore *store;
+public:
+  TestOpsSocketHook(OSDService *s, ObjectStore *st) : service(s), store(st) {}
+  bool call(std::string command, std::string args, bufferlist& out) {
+    stringstream ss;
+    test_ops(service, store, command, args, ss);
+    out.append(ss);
+    return true;
+  }
+  void test_ops(OSDService *service, ObjectStore *store, std::string command,
+     std::string args, ostream &ss);
+
+};
+
 int OSD::init()
 {
   Mutex::Locker lock(osd_lock);
@@ -966,10 +983,24 @@ int OSD::init()
   AdminSocket *admin_socket = cct->get_admin_socket();
   r = admin_socket->register_command("dump_ops_in_flight", admin_ops_hook,
                                          "show the ops currently in flight");
+  assert(r == 0);
   historic_ops_hook = new HistoricOpsSocketHook(this);
   r = admin_socket->register_command("dump_historic_ops", historic_ops_hook,
                                          "show slowest recent ops");
   assert(r == 0);
+  test_ops_hook = new TestOpsSocketHook(&(this->service), this->store);
+  r = admin_socket->register_command("setomapval", test_ops_hook,
+                              "setomap <pool-id> <obj-name> <key> <val>");
+  assert(r == 0);
+  r = admin_socket->register_command("rmomapkey", test_ops_hook,
+                               "rmomapkey <pool-id> <obj-name> <key>");
+  assert(r == 0);
+  r = admin_socket->register_command("setomapheader", test_ops_hook,
+                               "setomapheader <pool-id> <obj-name> <header>");
+  assert(r == 0);
+  r = admin_socket->register_command("getomap", test_ops_hook,
+                               "getomap <pool-id> <obj-name>");
+  assert(r == 0);
 
   service.init();
   service.publish_map(osdmap);
@@ -1125,6 +1156,12 @@ int OSD::shutdown()
   delete historic_ops_hook;
   admin_ops_hook = NULL;
   historic_ops_hook = NULL;
+  cct->get_admin_socket()->unregister_command("setomapval");
+  cct->get_admin_socket()->unregister_command("rmomapkey");
+  cct->get_admin_socket()->unregister_command("setomapheader");
+  cct->get_admin_socket()->unregister_command("getomap");
+  delete test_ops_hook;
+  test_ops_hook = NULL;
 
   recovery_tp.stop();
   dout(10) << "recovery tp stopped" << dendl;
@@ -2292,6 +2329,120 @@ void OSD::dump_ops_in_flight(ostream& ss)
   op_tracker.dump_ops_in_flight(ss);
 }
 
+// Usage:
+//   setomapval <pool-id> <obj-name> <key> <val>
+//   rmomapkey <pool-id> <obj-name> <key>
+//   setomapheader <pool-id> <obj-name> <header>
+void TestOpsSocketHook::test_ops(OSDService *service, ObjectStore *store,
+     std::string command, std::string args, ostream &ss)
+{
+  //Test support
+  //Support changing the omap on a single osd by using the Admin Socket to
+  //directly request the osd make a change.
+  if (command == "setomapval" || command == "rmomapkey" ||
+        command == "setomapheader" || command == "getomap") {
+    std::vector<std::string> argv;
+    pg_t rawpg, pgid;
+    int64_t pool;
+    OSDMapRef curmap = service->get_osdmap();
+    int r;
+
+    argv.push_back(command);
+    string_to_vec(argv, args);
+    int argc = argv.size();
+
+    if (argc < 3) {
+      ss << "Illegal request";
+      return;
+    }
+    pool = curmap->const_lookup_pg_pool_name(argv[1].c_str());
+    //If we can't find it my name then maybe id specified
+    if (pool < 0 && isdigit(argv[1].c_str()[0]))
+      pool = atoll(argv[1].c_str());
+    r = -1;
+    if (pool >= 0)
+        r = curmap->object_locator_to_pg(object_t(argv[2]),
+          object_locator_t(pool), rawpg);
+    if (r < 0) {
+        ss << "Invalid pool " << argv[1];
+        return;
+    }
+    pgid = curmap->raw_pg_to_pg(rawpg);
+
+    hobject_t obj(object_t(argv[2]), string(""), CEPH_NOSNAP, rawpg.ps(), pool);
+    ObjectStore::Transaction t;
+
+    if (command == "setomapval") {
+      if (argc != 5) {
+        ss << "usage: setomapval <pool> <obj-name> <key> <val>";
+        return;
+      }
+      map<string, bufferlist> newattrs;
+      bufferlist val;
+      string key(argv[3]);
+      val.append(argv[4]);
+      newattrs[key] = val;
+      t.omap_setkeys(coll_t(pgid), obj, newattrs);
+      r = store->apply_transaction(t);
+      if (r < 0)
+        ss << "error=" << r;
+      else
+        ss << "ok";
+    } else if (command == "rmomapkey") {
+      if (argc != 4) {
+        ss << "usage: rmomapkey <pool> <obj-name> <key>";
+        return;
+      }
+      set<string> keys;
+
+      keys.insert(string(argv[3]));
+      t.omap_rmkeys(coll_t(pgid), obj, keys);
+      r = store->apply_transaction(t);
+      if (r < 0)
+        ss << "error=" << r;
+      else
+        ss << "ok";
+    } else if (command == "setomapheader") {
+      if (argc != 4) {
+        ss << "usage: setomapheader <pool> <obj-name> <header>";
+        return;
+      }
+      bufferlist newheader;
+
+      newheader.append(argv[3]);
+      t.omap_setheader(coll_t(pgid), obj, newheader);
+      r = store->apply_transaction(t);
+      if (r < 0)
+        ss << "error=" << r;
+      else
+        ss << "ok";
+    } else if (command == "getomap") {
+      if (argc != 3) {
+        ss << "usage: getomap <pool> <obj-name>";
+        return;
+      }
+      //Debug: Output entire omap
+      bufferlist hdrbl;
+      map<string, bufferlist> keyvals;
+      r = store->omap_get(coll_t(pgid), obj, &hdrbl, &keyvals);
+      if (r >= 0) {
+          ss << "header=" << string(hdrbl.c_str(), hdrbl.length());
+          for (map<string, bufferlist>::iterator it = keyvals.begin();
+              it != keyvals.end(); it++)
+            ss << " key=" << (*it).first << " val="
+               << string((*it).second.c_str(), (*it).second.length());
+      } else {
+          ss << "error=" << r;
+      }
+    }
+    return;
+  }
+  ss << "Internal error - command=" << command;
+  return;
+}
+
 // =========================================
 void OSD::RemoveWQ::_process(boost::tuple<coll_t, SequencerRef, DeletingStateRef> *item)
 {
index 83308486f0f2487cb1929ed997abf859d598affd..be4ed11791e4fd6ec371e852c9674ebf0232512e 100644 (file)
@@ -133,6 +133,7 @@ class AuthAuthorizeHandlerRegistry;
 
 class OpsFlightSocketHook;
 class HistoricOpsSocketHook;
+class TestOpsSocketHook;
 struct C_CompleteSplits;
 
 extern const coll_t meta_coll;
@@ -617,11 +618,14 @@ private:
   void dump_historic_ops(ostream& ss) {
     return op_tracker.dump_historic_ops(ss);
   }
+  void test_ops(std::string command, std::string args, ostream& ss);
   friend class OpsFlightSocketHook;
   friend class HistoricOpsSocketHook;
+  friend class TestOpsSocketHook;
   friend class C_CompleteSplits;
   OpsFlightSocketHook *admin_ops_hook;
   HistoricOpsSocketHook *historic_ops_hook;
+  TestOpsSocketHook *test_ops_hook;
 
   // -- op queue --
 
index 4d4bbd0b03176c231b5a69b0e1abf6e7f300d4a6..5105fc7ab0e4c18e6cb7a69d0b8b154acff74642 100644 (file)
@@ -450,6 +450,10 @@ public:
     return -ENOENT;
   }
 
+  int64_t const_lookup_pg_pool_name(const char *name) const {
+    return const_cast<OSDMap *>(this)->lookup_pg_pool_name(name);
+  }
+
   int64_t get_pool_max() const {
     return pool_max;
   }