]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: radosgw-admin should paginate internally when listing bucket 37802/head
authorJ. Eric Ivancich <ivancich@redhat.com>
Thu, 1 Oct 2020 17:33:01 +0000 (13:33 -0400)
committerNathan Cutler <ncutler@suse.com>
Mon, 26 Oct 2020 19:22:00 +0000 (20:22 +0100)
Currently `radosgw-admin bucket list ...`, when listing a bucket, asks
for the value of "--max-entries" internally. To list a large bucket
entirely the user would have to set "--max-entries" to a large value
(e.g., 10000000). Internally this doesn't paginate, so it will try to
produce the entire list at once. This can consume a lot of memory, and
there are known cases where this induces an out-of-memory crash.

So now we'll set a maximum pagination size of 10,000. So even with
large values of "--max-entries" it will still be able to produce the
full listing without stressing memory, because it will ask for at most
10,000 entries at a time.

Signed-off-by: J. Eric Ivancich <ivancich@redhat.com>
(cherry picked from commit 6d033061bf9eaebf3dab37b9ed45de22ce6fa6b7)

Conflicts:
src/rgw/rgw_admin.cc
- RGWRados::Bucket::List.list_objects() does not take null_yield
  argument in nautilus
- formatter does not have get() method in nautilus

src/rgw/rgw_admin.cc

index 10e353577dc0b211f594ef1f8abee91cdcb7e251..675cce34d129f6229148aa01539bdd5883268e80 100644 (file)
@@ -5561,10 +5561,17 @@ int main(int argc, const char **argv)
         return -ret;
       }
       formatter->open_array_section("entries");
-      bool truncated;
+
+      bool truncated = false;
       int count = 0;
-      if (max_entries < 0)
-        max_entries = 1000;
+
+      static constexpr int MAX_PAGINATE_SIZE = 10000;
+      static constexpr int DEFAULT_MAX_ENTRIES = 1000;
+
+      if (max_entries < 0) {
+       max_entries = DEFAULT_MAX_ENTRIES;
+      }
+      const int paginate_size = std::min(max_entries, MAX_PAGINATE_SIZE);
 
       string prefix;
       string delim;
@@ -5584,7 +5591,9 @@ int main(int argc, const char **argv)
       list_op.params.allow_unordered = bool(allow_unordered);
 
       do {
-        ret = list_op.list_objects(max_entries - count, &result, &common_prefixes, &truncated);
+        const int remaining = max_entries - count;
+        ret = list_op.list_objects(std::min(remaining, paginate_size),
+                                  &result, &common_prefixes, &truncated);
         if (ret < 0) {
           cerr << "ERROR: store->list_objects(): " << cpp_strerror(-ret) << std::endl;
           return -ret;
@@ -5592,8 +5601,7 @@ int main(int argc, const char **argv)
 
         count += result.size();
 
-        for (vector<rgw_bucket_dir_entry>::iterator iter = result.begin(); iter != result.end(); ++iter) {
-          rgw_bucket_dir_entry& entry = *iter;
+        for (const auto& entry : result) {
           encode_json("entry", entry, formatter);
         }
         formatter->flush(cout);