]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/multi: Fix error handling in public Datalog APIs
authorAdam C. Emerson <aemerson@redhat.com>
Tue, 15 Apr 2025 11:30:35 +0000 (07:30 -0400)
committerAdam C. Emerson <aemerson@redhat.com>
Thu, 7 Aug 2025 18:48:52 +0000 (14:48 -0400)
I had been thinking of list and trim as purely internal interfaces,
but they are called through HTTP and thus need to be prepared for bad
input.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
(cherry picked from commit 9d4968b4a075cb764b4139d864e0ec199890a89a)
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
src/rgw/driver/rados/rgw_datalog.cc
src/rgw/driver/rados/rgw_datalog.h
src/rgw/driver/rados/rgw_rest_log.cc
src/rgw/radosgw-admin/radosgw-admin.cc

index 3594d44e6f370774269c2560e8153f9f2981aa64..ffc6a5c3bd9d2fc6d86e87ed3e9ee7817562819c 100644 (file)
@@ -1043,6 +1043,7 @@ DataLogBackends::list(const DoutPrefixProvider *dpp, int shard,
                      std::span<rgw_data_change_log_entry> entries,
                      std::string marker)
 {
+  assert(shard < shards);
   const auto [start_id, // Starting generation
              start_cursor // Cursor to be used when listing the
                           // starting generation
@@ -1114,11 +1115,18 @@ int RGWDataChangesLog::list_entries(
   const DoutPrefixProvider *dpp, int shard,
   int max_entries, std::vector<rgw_data_change_log_entry>& entries,
   std::string_view marker, std::string* out_marker, bool* truncated,
-  optional_yield y)
+  std::string* errstr, optional_yield y)
 {
   std::exception_ptr eptr;
   std::tuple<std::span<rgw_data_change_log_entry>,
             std::string> out;
+  if (shard >= num_shards) [[unlikely]] {
+    if (errstr) {
+    *errstr = fmt::format("{} is not a valid shard. Valid shards are integers in [0, {})",
+                        shard, num_shards);
+    }
+    return -EINVAL;
+  }
   if (std::ssize(entries) < max_entries) {
     entries.resize(max_entries);
   }
@@ -1233,9 +1241,16 @@ int RGWDataChangesLog::list_entries(const DoutPrefixProvider *dpp,int max_entrie
 }
 
 int RGWDataChangesLog::get_info(const DoutPrefixProvider* dpp, int shard_id,
-                               RGWDataChangesLogInfo* info, optional_yield y)
+                               RGWDataChangesLogInfo* info,
+                               std::string* errstr, optional_yield y)
 {
-  assert(shard_id < num_shards);
+  if (shard_id >= num_shards) [[unlikely]] {
+    if (errstr) {
+      *errstr = fmt::format(
+       "{} is not a valid shard. Valid shards are integers in [0, {})",
+       shard_id, num_shards);
+    }
+  }
   auto be = bes->head();
   std::exception_ptr eptr;
   if (y) {
@@ -1263,6 +1278,7 @@ asio::awaitable<void> DataLogBackends::trim_entries(
   const DoutPrefixProvider *dpp, int shard_id,
   std::string_view marker)
 {
+  assert(shard_id < shards);
   auto [target_gen, cursor] = cursorgen(std::string{marker});
   std::unique_lock l(m);
 
@@ -1286,9 +1302,16 @@ asio::awaitable<void> DataLogBackends::trim_entries(
 }
 
 int RGWDataChangesLog::trim_entries(const DoutPrefixProvider *dpp, int shard_id,
-                                   std::string_view marker, optional_yield y)
+                                   std::string_view marker, std::string* errstr,
+                                   optional_yield y)
 {
-  assert(shard_id < num_shards);
+  if (shard_id >= num_shards) [[unlikely]] {
+    if (errstr) {
+      *errstr = fmt::format(
+       "{} is not a valid shard. Valid shards are integers in [0, {})",
+       shard_id, num_shards);
+    }
+  }
   std::exception_ptr eptr;
   if (y) {
     auto& yield = y.get_yield_context();
@@ -1310,7 +1333,11 @@ int RGWDataChangesLog::trim_entries(const DoutPrefixProvider *dpp, int shard_id,
 
 int RGWDataChangesLog::trim_entries(const DoutPrefixProvider* dpp, int shard_id,
                                    std::string_view marker,
-                                   librados::AioCompletion* c) {
+                                   librados::AioCompletion* c)
+{
+  if (shard_id >= num_shards) [[unlikely]] {
+    return -EINVAL;
+  }
   asio::co_spawn(rados->get_executor(),
                 bes->trim_entries(dpp, shard_id, marker),
                 c);
@@ -1502,6 +1529,7 @@ void RGWDataChangesLog::renew_stop()
 
 void RGWDataChangesLog::mark_modified(int shard_id, const rgw_bucket_shard& bs, uint64_t gen)
 {
+  assert(shard_id < num_shards);
   if (!cct->_conf->rgw_data_notify_interval_msec) {
     return;
   }
index 161b2d91776e0948eff42e857ba03aecbf145f76..81772d7388d83dc82db6db10ce625b8a910d9ab0 100644 (file)
@@ -469,7 +469,7 @@ public:
   int list_entries(const DoutPrefixProvider *dpp, int shard, int max_entries,
                   std::vector<rgw_data_change_log_entry>& entries,
                   std::string_view marker, std::string* out_marker,
-                  bool* truncated, optional_yield y);
+                  bool* truncated, std::string* errstr, optional_yield y);
   asio::awaitable<std::tuple<std::vector<rgw_data_change_log_entry>,
                             RGWDataChangesLogMarker>>
   list_entries(const DoutPrefixProvider *dpp, int max_entries,
@@ -480,11 +480,12 @@ public:
                   optional_yield y);
 
   int trim_entries(const DoutPrefixProvider *dpp, int shard_id,
-                  std::string_view marker, optional_yield y);
+                  std::string_view marker, std::string* errstr, optional_yield y);
   int trim_entries(const DoutPrefixProvider *dpp, int shard_id,
-                   std::string_view marker, librados::AioCompletion* c);
+                  std::string_view marker, librados::AioCompletion* c);
   int get_info(const DoutPrefixProvider *dpp, int shard_id,
-              RGWDataChangesLogInfo *info, optional_yield y);
+              RGWDataChangesLogInfo *info, std::string* errstr,
+              optional_yield y);
 
   void mark_modified(int shard_id, const rgw_bucket_shard& bs, uint64_t gen);
   auto read_clear_modified() {
index 0f1ea2a783e4f19938e59833c270ed3cc7daddc8..d3d71465d0a18a6b5b43b188fa95beaa5604007f 100644 (file)
@@ -690,11 +690,11 @@ void RGWOp_DATALog_List::execute(optional_yield y) {
   // entry listed
   op_ret = static_cast<rgw::sal::RadosStore*>(driver)->svc()->
     datalog_rados->list_entries(this, shard_id, max_entries, entries,
-                               marker, &last_marker, &truncated, y);
+                               marker, &last_marker, &truncated, nullptr, y);
 
   RGWDataChangesLogInfo info;
   op_ret = static_cast<rgw::sal::RadosStore*>(driver)->svc()->
-    datalog_rados->get_info(this, shard_id, &info, y);
+    datalog_rados->get_info(this, shard_id, &info, nullptr, y);
 
   last_update = info.last_update;
 }
@@ -757,7 +757,7 @@ void RGWOp_DATALog_ShardInfo::execute(optional_yield y) {
   }
 
   op_ret = static_cast<rgw::sal::RadosStore*>(driver)->svc()->
-    datalog_rados->get_info(this, shard_id, &info, y);
+    datalog_rados->get_info(this, shard_id, &info, nullptr, y);
 }
 
 void RGWOp_DATALog_ShardInfo::send_response() {
@@ -907,7 +907,7 @@ void RGWOp_DATALog_Delete::execute(optional_yield y) {
   }
 
   op_ret = static_cast<rgw::sal::RadosStore*>(driver)->svc()->
-    datalog_rados->trim_entries(this, shard_id, marker, y);
+    datalog_rados->trim_entries(this, shard_id, marker, nullptr, y);
 }
 
 // not in header to avoid pulling in rgw_sync.h
index d5f80ce2e0f16d8cf54d51081e4ca798ffdf702a..4e9ac3abfd3b990f3497e6ba464152f5fedc296f 100644 (file)
@@ -11045,19 +11045,21 @@ next:
     auto datalog_svc = static_cast<rgw::sal::RadosStore*>(driver)->svc()->datalog_rados;
     RGWDataChangesLogMarker log_marker;
 
+    std::string errstr;
     do {
       std::vector<rgw_data_change_log_entry> entries;
       if (specified_shard_id) {
         ret = datalog_svc->list_entries(dpp(), shard_id, max_entries - count,
                                        entries, marker,
                                        &marker, &truncated,
-                                       null_yield);
+                                       &errstr, null_yield);
       } else {
         ret = datalog_svc->list_entries(dpp(), max_entries - count, entries,
                                        log_marker, &truncated, null_yield);
       }
       if (ret < 0) {
-        cerr << "ERROR: datalog_svc->list_entries(): " << cpp_strerror(-ret) << std::endl;
+        cerr << "ERROR: datalog_svc->list_entries(): " << errstr << ": "
+            << cpp_strerror(-ret) << std::endl;
         return -ret;
       }
 
@@ -11086,7 +11088,7 @@ next:
 
       RGWDataChangesLogInfo info;
       static_cast<rgw::sal::RadosStore*>(driver)->svc()->
-       datalog_rados->get_info(dpp(), i, &info, null_yield);
+       datalog_rados->get_info(dpp(), i, &info, nullptr, null_yield);
 
       ::encode_json("info", info, formatter.get());
 
@@ -11149,7 +11151,7 @@ next:
     }
 
     auto datalog = static_cast<rgw::sal::RadosStore*>(driver)->svc()->datalog_rados;
-    ret = datalog->trim_entries(dpp(), shard_id, marker, null_yield);
+    ret = datalog->trim_entries(dpp(), shard_id, marker, nullptr, null_yield);
 
     if (ret < 0 && ret != -ENODATA) {
       cerr << "ERROR: trim_entries(): " << cpp_strerror(-ret) << std::endl;