summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-07-26 13:58:46 -0700
committerSage Weil <sage@inktank.com>2013-07-26 13:59:45 -0700
commitc24e652d8c5e693498814ebe38c6adbec079ea36 (patch)
tree16192246b5fb66b8c86d131a2350d03c841f36fd
parentc562b72e703f671127d0ea2173f6a6907c825cd1 (diff)
downloadceph-c24e652d8c5e693498814ebe38c6adbec079ea36.tar.gz
osd: load all classes on startup
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>
-rw-r--r--src/osd/ClassHandler.cc39
-rw-r--r--src/osd/ClassHandler.h2
-rw-r--r--src/osd/OSD.cc1
3 files changed, 41 insertions, 1 deletions
diff --git a/src/osd/ClassHandler.cc b/src/osd/ClassHandler.cc
index 5af2ac01a0f..3cc319efabe 100644
--- a/src/osd/ClassHandler.cc
+++ b/src/osd/ClassHandler.cc
@@ -18,6 +18,11 @@
#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;
diff --git a/src/osd/ClassHandler.h b/src/osd/ClassHandler.h
index 733ed01a35d..f7c80f9454b 100644
--- a/src/osd/ClassHandler.h
+++ b/src/osd/ClassHandler.h
@@ -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);
diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc
index bc3aa604fec..c642a068e1c 100644
--- a/src/osd/OSD.cc
+++ b/src/osd/OSD.cc
@@ -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);