]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: load all classes on startup
authorSage Weil <sage@inktank.com>
Fri, 26 Jul 2013 20:58:46 +0000 (13:58 -0700)
committerSage Weil <sage@inktank.com>
Fri, 26 Jul 2013 20:59:45 +0000 (13:59 -0700)
This avoid creating a wide window between when ceph-osd is started and
when a request arrives needing a class and it is loaded.  In particular,
upgrading the packages in that window may cause linkage errors (if the
class API has changed, for example).

Fixes: #5752
Signed-off-by: Sage Weil <sage@inktank.com>
Reviewed-by: Yehuda Sadeh <yehuda@inktank.com>
src/osd/ClassHandler.cc
src/osd/ClassHandler.h
src/osd/OSD.cc

index 5af2ac01a0fbde8d9d9f39c0a5e768a421026c23..3cc319efabeef622afb2b898e30e50d468eae31b 100644 (file)
 #undef dout_prefix
 #define dout_prefix *_dout
 
+
+#define CLS_PREFIX "libcls_"
+#define CLS_SUFFIX ".so"
+
+
 int ClassHandler::open_class(const string& cname, ClassData **pcls)
 {
   Mutex::Locker lock(mutex);
@@ -31,11 +36,43 @@ int ClassHandler::open_class(const string& cname, ClassData **pcls)
   return 0;
 }
 
+int ClassHandler::open_all_classes()
+{
+  dout(10) << __func__ << dendl;
+  DIR *dir = ::opendir(g_conf->osd_class_dir.c_str());
+  if (!dir)
+    return -errno;
+
+  char buf[offsetof(struct dirent, d_name) + PATH_MAX + 1];
+  struct dirent *pde;
+  int r = 0;
+  while ((r = ::readdir_r(dir, (dirent *)&buf, &pde)) == 0 && pde) {
+    if (pde->d_name[0] == '.')
+      continue;
+    if (strlen(pde->d_name) > sizeof(CLS_PREFIX) - 1 + sizeof(CLS_SUFFIX) - 1 &&
+       strncmp(pde->d_name, CLS_PREFIX, sizeof(CLS_PREFIX) - 1) == 0 &&
+       strcmp(pde->d_name + strlen(pde->d_name) - (sizeof(CLS_SUFFIX) - 1), CLS_SUFFIX) == 0) {
+      char cname[strlen(pde->d_name)];
+      strcpy(cname, pde->d_name + sizeof(CLS_PREFIX) - 1);
+      cname[strlen(cname) - (sizeof(CLS_SUFFIX) - 1)] = '\0';
+      dout(10) << __func__ << " found " << cname << dendl;
+      ClassData *cls;
+      r = open_class(cname, &cls);
+      if (r < 0)
+       goto out;
+    }
+  }
+ out:
+  closedir(dir);
+  return r;
+}
+
 void ClassHandler::shutdown()
 {
   for (map<string, ClassData>::iterator p = classes.begin(); p != classes.end(); ++p) {
     dlclose(p->second.handle);
   }
+  classes.clear();
 }
 
 ClassHandler::ClassData *ClassHandler::_get_class(const string& cname)
@@ -63,7 +100,7 @@ int ClassHandler::_load_class(ClassData *cls)
   if (cls->status == ClassData::CLASS_UNKNOWN ||
       cls->status == ClassData::CLASS_MISSING) {
     char fname[PATH_MAX];
-    snprintf(fname, sizeof(fname), "%s/libcls_%s.so",
+    snprintf(fname, sizeof(fname), "%s/" CLS_PREFIX "%s" CLS_SUFFIX,
             g_conf->osd_class_dir.c_str(),
             cls->name.c_str());
     dout(10) << "_load_class " << cls->name << " from " << fname << dendl;
index 733ed01a35d3ebe53a18c6bad17c5815a00e6b40..f7c80f9454b0cc95846dfd9a6d86416aa4950eaa 100644 (file)
@@ -78,6 +78,8 @@ private:
 public:
   ClassHandler() : mutex("ClassHandler") {}
   
+  int open_all_classes();
+
   int open_class(const string& cname, ClassData **pcls);
   
   ClassData *register_class(const char *cname);
index bc3aa604fecf6085b04ae05469b22735f5498b10..c642a068e1c7a3f34f83cc17e8fabc7f6aa5c31c 100644 (file)
@@ -1165,6 +1165,7 @@ int OSD::init()
 
   class_handler = new ClassHandler();
   cls_initialize(class_handler);
+  class_handler->open_all_classes();
 
   // load up "current" osdmap
   assert_warn(!osdmap);