]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: add indexless bucket logic to "bucket radoslist"
authorJ. Eric Ivancich <ivancich@redhat.com>
Mon, 17 Jan 2022 21:14:16 +0000 (16:14 -0500)
committerAdam C. Emerson <aemerson@redhat.com>
Wed, 2 Feb 2022 00:01:59 +0000 (19:01 -0500)
The "bucket radoslist" sub-command of radosgw-admin is supposed to
list all rados objects tied to one or all directories and thereby
provide a way to determine orphaned rados objects.

But indexless buckets don't provide an index to employ for this
purpose. So warnings or errors should be provided depending on the
circumstances.

Signed-off-by: J. Eric Ivancich <ivancich@redhat.com>
src/rgw/rgw_admin.cc
src/rgw/rgw_orphan.cc
src/rgw/rgw_orphan.h

index e7bb912b840f0789c84691d9b2cb8793e74d76aa..9ba9979f628d938688e7b1351abba488656587c3 100644 (file)
@@ -6860,7 +6860,9 @@ int main(int argc, const char **argv)
     }
 
     if (bucket_name.empty()) {
-      ret = lister.run(dpp());
+      // yes_i_really_mean_it means continue with listing even if
+      // there are indexless buckets
+      ret = lister.run(dpp(), yes_i_really_mean_it);
     } else {
       ret = lister.run(dpp(), bucket_name);
     }
index a43d2a6754b5de3727d8a9e0f24e91ea967fb560..e36231f2eb36b8b23be1b181131cee3a06379850 100644 (file)
@@ -1319,7 +1319,8 @@ int RGWRadosList::process_bucket(
 }
 
 
-int RGWRadosList::run(const DoutPrefixProvider *dpp)
+int RGWRadosList::run(const DoutPrefixProvider *dpp,
+                     const bool yes_i_really_mean_it)
 {
   int ret;
   void* handle = nullptr;
@@ -1332,17 +1333,36 @@ int RGWRadosList::run(const DoutPrefixProvider *dpp)
     return ret;
   }
 
-  const int max_keys = 1000;
+  constexpr int max_keys = 1000;
   bool truncated = true;
+  bool warned_indexless = false;
 
   do {
     std::list<std::string> buckets;
     ret = store->meta_list_keys_next(dpp, handle, max_keys, buckets, &truncated);
 
     for (std::string& bucket_id : buckets) {
-      ret = run(dpp, bucket_id);
+      ret = run(dpp, bucket_id, true);
       if (ret == -ENOENT) {
        continue;
+      } else if (ret == -EINVAL) {
+       if (! warned_indexless) {
+         if (yes_i_really_mean_it) {
+           std::cerr <<
+             "WARNING: because there is at least one indexless bucket (" <<
+             bucket_id <<
+             ") the results of radoslist are *incomplete*; continuing due to --yes-i-really-mean-it" <<
+             std::endl;
+           warned_indexless = true;
+         } else {
+           std::cerr << "ERROR: because there is at least one indexless bucket (" <<
+             bucket_id <<
+             ") the results of radoslist are *incomplete*; use --yes-i-really-mean-it to bypass error" <<
+             std::endl;
+           return ret;
+         }
+       }
+       continue;
       } else if (ret < 0) {
        return ret;
       }
@@ -1350,13 +1370,13 @@ int RGWRadosList::run(const DoutPrefixProvider *dpp)
   } while (truncated);
 
   return 0;
-} // RGWRadosList::run()
+} // RGWRadosList::run(DoutPrefixProvider, bool)
 
 
-int RGWRadosList::run(const DoutPrefixProvider *dpp, const std::string& start_bucket_name)
+int RGWRadosList::run(const DoutPrefixProvider *dpp,
+                     const std::string& start_bucket_name,
+                     const bool silent_indexless)
 {
-  RGWObjectCtx obj_ctx(store);
-  std::unique_ptr<rgw::sal::Bucket> bucket;
   int ret;
 
   add_bucket_entire(start_bucket_name);
@@ -1380,6 +1400,12 @@ int RGWRadosList::run(const DoutPrefixProvider *dpp, const std::string& start_bu
       std::cerr << "ERROR: could not get info for bucket " << bucket_name <<
        " -- " << cpp_strerror(-ret) << std::endl;
       return ret;
+    } else if (bucket->get_info().is_indexless()) {
+      if (! silent_indexless) {
+       std::cerr << "ERROR: unable to run radoslist on indexless bucket " <<
+         bucket_name << std::endl;
+      }
+      return -EINVAL;
     }
 
     const std::string bucket_id = bucket->get_key().get_key();
@@ -1428,12 +1454,13 @@ int RGWRadosList::run(const DoutPrefixProvider *dpp, const std::string& start_bu
   } // while (! bucket_process_map.empty())
 
   if (include_rgw_obj_name) {
-    goto done;
+    return 0;
   }
 
   // now handle incomplete multipart uploads by going back to the
   // initial bucket
 
+  std::unique_ptr<rgw::sal::Bucket> bucket;
   ret = store->get_bucket(dpp, nullptr, tenant_name, start_bucket_name, &bucket, null_yield);
   if (ret == -ENOENT) {
     // bucket deletion race?
@@ -1451,10 +1478,8 @@ int RGWRadosList::run(const DoutPrefixProvider *dpp, const std::string& start_bu
     return ret;
   }
 
-done:
-
   return 0;
-} // RGWRadosList::run(string)
+} // RGWRadosList::run(DoutPrefixProvider, string, bool)
 
 
 int RGWRadosList::do_incomplete_multipart(const DoutPrefixProvider *dpp,
index a5081374e88fdb44a4691c66c63bf681758a35de..4ecbd0e97ccd5e73500058fe7166292bf70d6e4e 100644 (file)
@@ -291,8 +291,11 @@ public:
 
   int build_linked_oids_index();
 
-  int run(const DoutPrefixProvider *dpp, const std::string& bucket_id);
-  int run(const DoutPrefixProvider *dpp);
+  int run(const DoutPrefixProvider *dpp,
+         const std::string& bucket_id,
+         const bool silent_indexless = false);
+  int run(const DoutPrefixProvider *dpp,
+         const bool yes_i_really_mean_it = false);
 
   // if there's a non-empty field separator, that means we'll display
   // bucket and object names