]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: metadata retrieval added to open image state machine 9190/head
authorJason Dillaman <dillaman@redhat.com>
Wed, 18 May 2016 23:19:24 +0000 (19:19 -0400)
committerJason Dillaman <dillaman@redhat.com>
Thu, 19 May 2016 00:38:13 +0000 (20:38 -0400)
Fixes: http://tracker.ceph.com/issues/15928
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/ImageCtx.cc
src/librbd/ImageCtx.h
src/librbd/image/OpenRequest.cc
src/librbd/image/OpenRequest.h

index fa05103168664a67b0e5d6162b05aadc268e6115..564996985f9c63a10dc7edac464939d9befc63fd 100644 (file)
@@ -234,10 +234,6 @@ struct C_InvalidateCache : public Context {
   void ImageCtx::init() {
     assert(!header_oid.empty());
     assert(old_format || !id.empty());
-    if (!old_format) {
-      init_layout();
-    }
-    apply_metadata_confs();
 
     asok_hook = new LibrbdAdminSocketHook(this);
 
@@ -888,31 +884,32 @@ struct C_InvalidateCache : public Context {
     completed_reqs.clear();
   }
 
-  bool ImageCtx::_filter_metadata_confs(const string &prefix, map<string, bool> &configs,
-                                        map<string, bufferlist> &pairs, map<string, bufferlist> *res) {
+  bool ImageCtx::_filter_metadata_confs(const string &prefix,
+                                        map<string, bool> &configs,
+                                        const map<string, bufferlist> &pairs,
+                                        map<string, bufferlist> *res) {
     size_t conf_prefix_len = prefix.size();
 
     string start = prefix;
-    for (map<string, bufferlist>::iterator it = pairs.begin(); it != pairs.end(); ++it) {
-      if (it->first.compare(0, MIN(conf_prefix_len, it->first.size()), prefix) > 0)
+    for (auto it : pairs) {
+      if (it.first.compare(0, MIN(conf_prefix_len, it.first.size()), prefix) > 0)
         return false;
 
-      if (it->first.size() <= conf_prefix_len)
+      if (it.first.size() <= conf_prefix_len)
         continue;
 
-      string key = it->first.substr(conf_prefix_len, it->first.size() - conf_prefix_len);
-      map<string, bool>::iterator cit = configs.find(key);
-      if ( cit != configs.end()) {
+      string key = it.first.substr(conf_prefix_len, it.first.size() - conf_prefix_len);
+      auto cit = configs.find(key);
+      if (cit != configs.end()) {
         cit->second = true;
-        res->insert(make_pair(key, it->second));
+        res->insert(make_pair(key, it.second));
       }
     }
     return true;
   }
 
-  void ImageCtx::apply_metadata_confs() {
+  void ImageCtx::apply_metadata(const std::map<std::string, bufferlist> &meta) {
     ldout(cct, 20) << __func__ << dendl;
-    static uint64_t max_conf_items = 128;
     std::map<string, bool> configs = boost::assign::map_list_of(
         "rbd_non_blocking_aio", false)(
         "rbd_cache", false)(
@@ -943,39 +940,18 @@ struct C_InvalidateCache : public Context {
         "rbd_journal_object_flush_age", false)(
         "rbd_journal_pool", false);
 
-    string start = METADATA_CONF_PREFIX;
     md_config_t local_config_t;
-
-    bool retrieve_metadata = !old_format;
-    while (retrieve_metadata) {
-      map<string, bufferlist> pairs, res;
-      int r = cls_client::metadata_list(&md_ctx, header_oid, start, max_conf_items,
-                                    &pairs);
-      if (r == -EOPNOTSUPP || r == -EIO) {
-        ldout(cct, 10) << "config metadata not supported by OSD" << dendl;
-        break;
-      } else if (r < 0) {
-        lderr(cct) << __func__ << " couldn't list config metadata: " << r
+    std::map<std::string, bufferlist> res;
+
+    _filter_metadata_confs(METADATA_CONF_PREFIX, configs, meta, &res);
+    for (auto it : res) {
+      std::string val(it.second.c_str(), it.second.length());
+      int j = local_config_t.set_val(it.first.c_str(), val);
+      if (j < 0) {
+        lderr(cct) << __func__ << " failed to set config " << it.first
+                   << " with value " << it.second.c_str() << ": " << j
                    << dendl;
-        break;
-      }
-      if (pairs.empty()) {
-        break;
-      }
-
-      retrieve_metadata = _filter_metadata_confs(METADATA_CONF_PREFIX, configs,
-                                                 pairs, &res);
-      for (map<string, bufferlist>::iterator it = res.begin();
-           it != res.end(); ++it) {
-        string val(it->second.c_str(), it->second.length());
-        int j = local_config_t.set_val(it->first.c_str(), val);
-        if (j < 0) {
-          lderr(cct) << __func__ << " failed to set config " << it->first
-                     << " with value " << it->second.c_str() << ": " << j
-                     << dendl;
-        }
       }
-      start = pairs.rbegin()->first;
     }
 
 #define ASSIGN_OPTION(config)                                                  \
index 3b58c6699ff765d8d4967c866593def2eb3cb934..076072c7a01879e3861194c9fe0ff056425f4dbb 100644 (file)
@@ -192,7 +192,7 @@ namespace librbd {
     journal::Policy *journal_policy = nullptr;
 
     static bool _filter_metadata_confs(const string &prefix, std::map<string, bool> &configs,
-                                       map<string, bufferlist> &pairs, map<string, bufferlist> *res);
+                                       const map<string, bufferlist> &pairs, map<string, bufferlist> *res);
 
     // unit test mock helpers
     static ImageCtx* create(const std::string &image_name,
@@ -285,7 +285,7 @@ namespace librbd {
     void cancel_async_requests();
     void cancel_async_requests(Context *on_finish);
 
-    void apply_metadata_confs();
+    void apply_metadata(const std::map<std::string, bufferlist> &meta);
 
     ExclusiveLock<ImageCtx> *create_exclusive_lock();
     ObjectMap *create_object_map(uint64_t snap_id);
index 3027ecadab5f98e6df5909d63531c03d1844d83c..41f753e1c378b781137bdf662e6041861e501fde 100644 (file)
@@ -11,6 +11,8 @@
 #include "librbd/image/CloseRequest.h"
 #include "librbd/image/RefreshRequest.h"
 #include "librbd/image/SetSnapRequest.h"
+#include <boost/algorithm/string/predicate.hpp>
+#include "include/assert.h"
 
 #define dout_subsys ceph_subsys_rbd
 #undef dout_prefix
 namespace librbd {
 namespace image {
 
+namespace {
+
+static uint64_t MAX_METADATA_ITEMS = 128;
+
+}
+
 using util::create_context_callback;
 using util::create_rados_ack_callback;
 
 template <typename I>
 OpenRequest<I>::OpenRequest(I *image_ctx, Context *on_finish)
-  : m_image_ctx(image_ctx), m_on_finish(on_finish), m_error_result(0) {
+  : m_image_ctx(image_ctx), m_on_finish(on_finish), m_error_result(0),
+    m_last_metadata_key(ImageCtx::METADATA_CONF_PREFIX) {
 }
 
 template <typename I>
@@ -63,6 +72,8 @@ Context *OpenRequest<I>::handle_v1_detect_header(int *result) {
 
     m_image_ctx->old_format = true;
     m_image_ctx->header_oid = util::old_header_name(m_image_ctx->name);
+    m_image_ctx->apply_metadata({});
+
     send_register_watch();
   }
   return nullptr;
@@ -260,9 +271,66 @@ Context *OpenRequest<I>::handle_v2_get_stripe_unit_count(int *result) {
     lderr(cct) << "failed to read striping metadata: " << cpp_strerror(*result)
                << dendl;
     send_close_image(*result);
-  } else {
-    send_register_watch();
+    return nullptr;
+  }
+
+  m_image_ctx->init_layout();
+
+  send_v2_apply_metadata();
+  return nullptr;
+}
+
+template <typename I>
+void OpenRequest<I>::send_v2_apply_metadata() {
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << this << " " << __func__ << ": "
+                 << "start_key=" << m_last_metadata_key << dendl;
+
+  librados::ObjectReadOperation op;
+  cls_client::metadata_list_start(&op, m_last_metadata_key, MAX_METADATA_ITEMS);
+
+  using klass = OpenRequest<I>;
+  librados::AioCompletion *comp =
+    create_rados_ack_callback<klass, &klass::handle_v2_apply_metadata>(this);
+  m_out_bl.clear();
+  m_image_ctx->md_ctx.aio_operate(m_image_ctx->header_oid, comp, &op,
+                                  &m_out_bl);
+  comp->release();
+}
+
+template <typename I>
+Context *OpenRequest<I>::handle_v2_apply_metadata(int *result) {
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << this << " " << __func__ << ": r=" << *result << dendl;
+
+  std::map<std::string, bufferlist> metadata;
+  if (*result == 0) {
+    bufferlist::iterator it = m_out_bl.begin();
+    *result = cls_client::metadata_list_finish(&it, &metadata);
+  }
+
+  if (*result == -EOPNOTSUPP || *result == -EIO) {
+    ldout(cct, 10) << "config metadata not supported by OSD" << dendl;
+  } else if (*result < 0) {
+    lderr(cct) << "failed to retrieve metadata: " << cpp_strerror(*result)
+               << dendl;
+    send_close_image(*result);
+    return nullptr;
   }
+
+  if (!metadata.empty()) {
+    m_metadata.insert(metadata.begin(), metadata.end());
+    m_last_metadata_key = metadata.rbegin()->first;
+    if (boost::starts_with(m_last_metadata_key,
+                           ImageCtx::METADATA_CONF_PREFIX)) {
+      send_v2_apply_metadata();
+      return nullptr;
+    }
+  }
+
+  m_image_ctx->apply_metadata(m_metadata);
+
+  send_register_watch();
   return nullptr;
 }
 
@@ -270,17 +338,18 @@ template <typename I>
 void OpenRequest<I>::send_register_watch() {
   m_image_ctx->init();
 
-  if (!m_image_ctx->read_only) {
-    CephContext *cct = m_image_ctx->cct;
-    ldout(cct, 10) << this << " " << __func__ << dendl;
-
-    using klass = OpenRequest<I>;
-    Context *ctx = create_context_callback<
-      klass, &klass::handle_register_watch>(this);
-    m_image_ctx->register_watch(ctx);
-  } else {
+  if (m_image_ctx->read_only) {
     send_refresh();
+    return;
   }
+
+  CephContext *cct = m_image_ctx->cct;
+  ldout(cct, 10) << this << " " << __func__ << dendl;
+
+  using klass = OpenRequest<I>;
+  Context *ctx = create_context_callback<
+    klass, &klass::handle_register_watch>(this);
+  m_image_ctx->register_watch(ctx);
 }
 
 template <typename I>
index 48aed3787ee7dcd656da6fd4c69d374ad9502399..cf506ebe9743b185e08d44b2d5571cb04610598b 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "include/int_types.h"
 #include "include/buffer.h"
+#include <map>
+#include <string>
 
 class Context;
 
@@ -30,33 +32,36 @@ private:
    *
    * <start>
    *    |
-   *    | (v1)                          (read only)
-   *    |-----> V1_DETECT_HEADER  . . . . . . . . . . . . . . . . .
-   *    |           |                                             .
-   *    |           \-------------------------------\             .
-   *    | (v2)                                      |             .
-   *    \-----> V2_DETECT_HEADER                    |             .
-   *                |                               |             .
-   *                v                               |             .
-   *            V2_GET_ID|NAME                      |             .
-   *                |                               |             .
-   *                v                               |             .
-   *            V2_GET_IMMUTABLE_METADATA           |             .
-   *                |                               |             .
-   *                v                               v             .
-   *            V2_GET_STRIPE_UNIT_COUNT  ----> REGISTER_WATCH    .
-   *                .                               |             .
-   *                .  (read only)                  v             .
-   *                . . . . . . . . . . . . . > REFRESH < . . . . .
-   *                                             .   |
-   *                                             .   |
-   *                                             .   \--> SET_SNAP
-   *                                   (no snap) .          |
-   *                                             .          v
-   *                                             . . . > <finish>
-   *                                                        ^
-   *     (on error)                                         |
-   *    * * * * * * > CLOSE --------------------------------/
+   *    | (v1)
+   *    |-----> V1_DETECT_HEADER
+   *    |           |
+   *    |           \-------------------------------\
+   *    | (v2)                                      |
+   *    \-----> V2_DETECT_HEADER                    |
+   *                |                               |
+   *                v                               |
+   *            V2_GET_ID|NAME                      |
+   *                |                               |
+   *                v                               |
+   *            V2_GET_IMMUTABLE_METADATA           |
+   *                |                               |
+   *                v                               |
+   *            V2_GET_STRIPE_UNIT_COUNT            |
+   *                |                               |
+   *                v                               v
+   *      /---> V2_APPLY_METADATA -------------> REGISTER_WATCH (skip if
+   *      |         |                               |            read-only)
+   *      \---------/                               v
+   *                                             REFRESH
+   *                                                |
+   *                                                v
+   *                                             SET_SNAP (skip if no snap)
+   *                                                |
+   *                                                v
+   *                                             <finish>
+   *                                                ^
+   *     (on error)                                 |
+   *    * * * * * * > CLOSE ------------------------/
    *
    * @endverbatim
    */
@@ -69,6 +74,9 @@ private:
   bufferlist m_out_bl;
   int m_error_result;
 
+  std::string m_last_metadata_key;
+  std::map<std::string, bufferlist> m_metadata;
+
   void send_v1_detect_header();
   Context *handle_v1_detect_header(int *result);
 
@@ -87,6 +95,9 @@ private:
   void send_v2_get_stripe_unit_count();
   Context *handle_v2_get_stripe_unit_count(int *result);
 
+  void send_v2_apply_metadata();
+  Context *handle_v2_apply_metadata(int *result);
+
   void send_register_watch();
   Context *handle_register_watch(int *result);