]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw admin: implement a lc fix option
authorAbhishek Lekshmanan <abhishek@suse.com>
Mon, 4 Mar 2019 18:10:45 +0000 (19:10 +0100)
committerAbhishek Lekshmanan <abhishek@suse.com>
Fri, 12 Apr 2019 16:08:27 +0000 (18:08 +0200)
An radosgw-admin lc fix --bucket <> option is added which checks if the bucket
entry exists in the corresponding lc shard and creates it if not. In case of
resharded buckets not running a fixed rgw that writes/compares the marker this
would write a new entry with the marker as the old entry would've already been
deleted by a LC process. We currently don't cleanup the stale entry as it is
assumed this would be picked up by the LC processor already or would be picked
up in the next cycle.

Signed-off-by: Abhishek Lekshmanan <abhishek@suse.com>
(cherry picked from commit 4528db4b642c37f67b3338ce04979b1ba7772e3e)

src/rgw/rgw_admin.cc
src/rgw/rgw_lc.cc
src/rgw/rgw_lc.h
src/test/cli/radosgw-admin/help.t

index 4b457741c313db283e9c5085adde71cbbc274f39..0c711c74fe9086cc057d44414f518d4e6d049dd2 100644 (file)
@@ -193,6 +193,7 @@ void usage()
   cout << "  lc list                    list all bucket lifecycle progress\n";
   cout << "  lc get                     get a lifecycle bucket configuration\n";
   cout << "  lc process                 manually process lifecycle\n";
+  cout << "  lc fix                     fix LC for a resharded bucket\n";
   cout << "  metadata get               get metadata info\n";
   cout << "  metadata put               put metadata info\n";
   cout << "  metadata rm                remove metadata info\n";
@@ -435,6 +436,7 @@ enum {
   OPT_LC_LIST,
   OPT_LC_GET,
   OPT_LC_PROCESS,
+  OPT_LC_FIX,
   OPT_ORPHANS_FIND,
   OPT_ORPHANS_FINISH,
   OPT_ORPHANS_LIST_JOBS,
@@ -888,6 +890,8 @@ static int get_cmd(const char *cmd, const char *prev_cmd, const char *prev_prev_
       return OPT_LC_GET;
     if (strcmp(cmd, "process") == 0)
       return OPT_LC_PROCESS;
+    if (strcmp(cmd, "fix") == 0)
+      return OPT_LC_FIX;
   } else if (strcmp(prev_cmd, "orphans") == 0) {
     if (strcmp(cmd, "find") == 0)
       return OPT_ORPHANS_FIND;
@@ -6578,6 +6582,23 @@ next:
     }
   }
 
+
+  if (opt_cmd == OPT_LC_FIX) {
+    rgw_bucket bucket;
+    RGWBucketInfo bucket_info;
+    map<string, bufferlist> attrs;
+    ret = init_bucket(tenant, bucket_name, bucket_id, bucket_info, bucket, &attrs);
+    if (ret < 0) {
+      cerr << "ERROR: could not init bucket: " << cpp_strerror(-ret) << std::endl;
+      return -ret;
+    }
+
+    ret = rgw::lc::fix_lc_shard_entry(store, bucket_info, attrs);
+    if (ret < 0) {
+      cerr << "ERROR: fixing lc shard entry failed with" << cpp_strerror(-ret) << std::endl;
+    }
+  }
+
   if (opt_cmd == OPT_ORPHANS_FIND) {
     if (!yes_i_really_mean_it) {
       cerr << "accidental removal of active objects can not be reversed; "
index 2a779be0e4602ee0e01da5fac1c4ee7a127474ce..a66f2a3f3f0fc895c3fd6d3300ad7b0037cade7c 100644 (file)
@@ -16,6 +16,7 @@
 #include "rgw_common.h"
 #include "rgw_bucket.h"
 #include "rgw_lc.h"
+#include "rgw_string.h"
 
 #include "services/svc_sys_obj.h"
 
@@ -1290,7 +1291,7 @@ void RGWLifecycleConfiguration::generate_test_instances(list<RGWLifecycleConfigu
   o.push_back(new RGWLifecycleConfiguration);
 }
 
-static void get_lc_oid(CephContext *cct, const string& shard_id, string *oid)
+void get_lc_oid(CephContext *cct, const string& shard_id, string *oid)
 {
   int max_objs = (cct->_conf->rgw_lc_max_objs > HASH_PRIME ? HASH_PRIME : cct->_conf->rgw_lc_max_objs);
   int index = ceph_str_hash_linux(shard_id.c_str(), shard_id.size()) % HASH_PRIME % max_objs;
@@ -1301,11 +1302,17 @@ static void get_lc_oid(CephContext *cct, const string& shard_id, string *oid)
   return;
 }
 
+
+
+static std::string get_lc_shard_name(const rgw_bucket& bucket){
+  return string_join_reserve(':', bucket.tenant, bucket.name, bucket.marker);
+}
+
 template<typename F>
 static int guard_lc_modify(RGWRados* store, const rgw_bucket& bucket, const string& cookie, const F& f) {
   CephContext *cct = store->ctx();
 
-  string shard_id = bucket.tenant + ':' + bucket.name + ':' + bucket.marker;
+  string shard_id = get_lc_shard_name(bucket);
 
   string oid; 
   get_lc_oid(cct, shard_id, &oid);
@@ -1391,3 +1398,52 @@ int RGWLC::remove_bucket_config(RGWBucketInfo& bucket_info,
   return ret;
 }
 
+namespace rgw::lc {
+
+int fix_lc_shard_entry(RGWRados* store, const RGWBucketInfo& bucket_info,
+                      const map<std::string,bufferlist>& battrs)
+{
+  if (auto aiter = battrs.find(RGW_ATTR_LC);
+      aiter == battrs.end()) {
+    return 0;    // No entry, nothing to fix
+  }
+
+  auto shard_name = get_lc_shard_name(bucket_info.bucket);
+  std::string lc_oid;
+  get_lc_oid(store->ctx(), shard_name, &lc_oid);
+
+  rgw_lc_entry_t entry;
+  // There are multiple cases we need to encounter here
+  // 1. entry exists and is already set to marker, happens in plain buckets & newly resharded buckets
+  // 2. entry doesn't exist, which usually happens when reshard has happened prior to update and next LC process has already dropped the update
+  // 3. entry exists matching the current bucket id which was after a reshard (needs to be updated to the marker)
+  // We are not dropping the old marker here as that would be caught by the next LC process update
+  auto lc_pool_ctx = store->get_lc_pool_ctx();
+  int ret = cls_rgw_lc_get_entry(*lc_pool_ctx,
+                                lc_oid, shard_name, entry);
+  if (ret == 0) {
+    ldout(store->ctx(), 5) << "Entry already exists, nothing to do" << dendl;
+    return ret; // entry is already existing correctly set to marker
+  }
+  ldout(store->ctx(), 5) << "cls_rgw_lc_get_entry errored ret code=" << ret << dendl;
+  if (ret == -ENOENT) {
+    ldout(store->ctx(), 1) << "No entry for bucket=" << bucket_info.bucket.name
+                          << " creating " << dendl;
+    // TODO: we have too many ppl making cookies like this!
+    char cookie_buf[COOKIE_LEN + 1];
+    gen_rand_alphanumeric(store->ctx(), cookie_buf, sizeof(cookie_buf) - 1);
+    std::string cookie = cookie_buf;
+
+    ret = guard_lc_modify(store, bucket_info.bucket, cookie,
+                         [&lc_pool_ctx, &lc_oid](librados::IoCtx *ctx, const string& oid,
+                                           const pair<string, int>& entry) {
+                           return cls_rgw_lc_set_entry(*lc_pool_ctx,
+                                                       lc_oid, entry);
+                         });
+
+  }
+
+  return ret;
+}
+
+}
index 01fc01c70055091567251ac147e67c1b0fbacd4f..3566f7c1ce96839154a059785b098768d0d21c83 100644 (file)
@@ -502,6 +502,11 @@ class RGWLC : public DoutPrefixProvider {
   int handle_multipart_expiration(RGWRados::Bucket *target, const map<string, lc_op>& prefix_map);
 };
 
+namespace rgw::lc {
 
+int fix_lc_shard_entry(RGWRados *store, const RGWBucketInfo& bucket_info,
+                      const map<std::string,bufferlist>& battrs);
+
+} // namespace rgw::lc
 
 #endif
index e0079a19cb90be9404ad8c2ebaf0ad743e6c4c0c..8fdacf9ebe2d155cc9c141a40ca3b2610782cb87 100644 (file)
     lc list                    list all bucket lifecycle progress
     lc get                     get a lifecycle bucket configuration
     lc process                 manually process lifecycle
+    lc fix                     fix LC for a resharded bucket
     metadata get               get metadata info
     metadata put               put metadata info
     metadata rm                remove metadata info