]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: allow disabling bucket stats on head bucket
authorSeena Fallah <seenafallah@gmail.com>
Mon, 8 Apr 2024 13:06:14 +0000 (15:06 +0200)
committerSeena Fallah <seenafallah@gmail.com>
Fri, 13 Dec 2024 14:29:09 +0000 (15:29 +0100)
The HeadBucket API now reports the `X-RGW-Bytes-Used` and
`X-RGW-Object-Count` headers only when the `read-stats` querystring
is explicitly included in the API request.

Fixes: https://tracker.ceph.com/issues/65369
Signed-off-by: Seena Fallah <seenafallah@gmail.com>
PendingReleaseNotes
src/rgw/rgw_file_int.h
src/rgw/rgw_op.cc
src/rgw/rgw_op.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_rest_swift.h

index 146cab64d6fb744f1990331b33411c867781a94d..1b0a75e01a155a0bf0437fc5c1ea0bec584390ca 100644 (file)
   CephFS does not support disk space reservation. The only flags supported are
   `FALLOC_FL_KEEP_SIZE` and `FALLOC_FL_PUNCH_HOLE`.
 
+* The HeadBucket API now reports the `X-RGW-Bytes-Used` and `X-RGW-Object-Count`
+  headers only when the `read-stats` querystring is explicitly included in the
+  API request.
+
 >=19.2.1
 
 * CephFS: Command `fs subvolume create` now allows tagging subvolumes through option
index 0a1db64520722f015455668fcdb879697266c56b..84eff1e252e26518fba91db67af84ec49d722037 100644 (file)
@@ -2298,6 +2298,8 @@ public:
   std::string uri;
   std::map<std::string, buffer::list> attrs;
   RGWLibFS::BucketStats& bs;
+  real_time ctime;
+  bool name_matched = false;
 
   RGWStatBucketRequest(CephContext* _cct, std::unique_ptr<rgw::sal::User> _user,
                       const std::string& _path,
@@ -2312,9 +2314,7 @@ public:
     return (iter != attrs.end()) ? &(iter->second) : nullptr;
   }
 
-  real_time get_ctime() const {
-    return bucket->get_creation_time();
-  }
+  real_time get_ctime() { return ctime; }
 
   bool only_bucket() override { return false; }
 
@@ -2342,22 +2342,26 @@ public:
     return 0;
   }
 
-  virtual int get_params() {
-    return 0;
+  int get_params(optional_yield) override { return 0; }
+
+  void complete() override {
+    // get_state() will no longer be there after execute_req()
+    // so save what we need from get_state()->bucket
+    ctime = get_state()->bucket->get_creation_time();
+    name_matched = get_state()->bucket->get_name().length() > 0;
+
+    RGWOp::complete();
   }
 
   void send_response() override {
-    bucket->get_creation_time() = get_state()->bucket->get_info().creation_time;
     bs.size = stats.size;
     bs.size_rounded = stats.size_rounded;
-    bs.creation_time = bucket->get_creation_time();
+    bs.creation_time = get_state()->bucket->get_info().creation_time;
     bs.num_entries = stats.num_objects;
     std::swap(attrs, get_state()->bucket_attrs);
   }
 
-  bool matched() {
-    return (bucket->get_name().length() > 0);
-  }
+  bool matched() { return name_matched; }
 
 }; /* RGWStatBucketRequest */
 
index 8378d9ef22e0febf7643232856aea0ae7264072d..17140436eeb6407a52f7fcd31c4c2ab460e5dd15 100644 (file)
@@ -3135,17 +3135,19 @@ static int load_bucket_stats(const DoutPrefixProvider* dpp, optional_yield y,
 
 void RGWStatBucket::execute(optional_yield y)
 {
-  if (!s->bucket_exists) {
-    op_ret = -ERR_NO_SUCH_BUCKET;
+  op_ret = get_params(y);
+  if (op_ret < 0) {
     return;
   }
 
-  op_ret = driver->load_bucket(this, s->bucket->get_key(), &bucket, y);
-  if (op_ret) {
+  if (!s->bucket_exists) {
+    op_ret = -ERR_NO_SUCH_BUCKET;
     return;
   }
 
-  op_ret = load_bucket_stats(this, y, *s->bucket, stats);
+  if (report_stats) {
+    op_ret = load_bucket_stats(this, y, *s->bucket, stats);
+  }
 }
 
 int RGWListBucket::verify_permission(optional_yield y)
index 0098b67e032d9205d07d26e6925d763c233a1baa..9f747501729e0766d087837879f7ff8ef17fb40f 100644 (file)
@@ -1087,14 +1087,15 @@ public:
 
 class RGWStatBucket : public RGWOp {
 protected:
-  std::unique_ptr<rgw::sal::Bucket> bucket;
   RGWStorageStats stats;
+  bool report_stats{true};
 
 public:
   int verify_permission(optional_yield y) override;
   void pre_exec() override;
   void execute(optional_yield y) override;
 
+  virtual int get_params(optional_yield y) = 0;
   void send_response() override = 0;
   const char* name() const override { return "stat_bucket"; }
   RGWOpType get_type() override { return RGW_OP_STAT_BUCKET; }
index 03241b7369ac3c4144bb09e5c59ec092a84c4264..bf3d4ad9967ff43c0d818195083530823d2cb5e9 100644 (file)
@@ -1668,7 +1668,6 @@ int RGWDeleteMultiObj_ObjStore::get_params(optional_yield y)
   return op_ret;
 }
 
-
 void RGWRESTOp::send_response()
 {
   if (!flusher.did_start()) {
index b7046118ef32d31e5a9dcd990ad412a03dd19abd..4b337f317cee98cc8c2fbb020184fbfaceaa19aa 100644 (file)
@@ -2401,34 +2401,41 @@ void RGWGetBucketWebsite_ObjStore_S3::send_response()
   rgw_flush_formatter_and_reset(s, s->formatter);
 }
 
-static void dump_bucket_metadata(req_state *s, rgw::sal::Bucket* bucket,
+static void dump_bucket_metadata(req_state *s,
                                  RGWStorageStats& stats)
 {
   dump_header(s, "X-RGW-Object-Count", static_cast<long long>(stats.num_objects));
   dump_header(s, "X-RGW-Bytes-Used", static_cast<long long>(stats.size));
+}
 
-  // only bucket's owner is allowed to get the quota settings of the account
-  if (s->auth.identity->is_owner_of(bucket->get_owner())) {
-    const auto& user_info = s->user->get_info();
-    const auto& bucket_quota = s->bucket->get_info().quota; // bucket quota
-    dump_header(s, "X-RGW-Quota-Max-Buckets", static_cast<long long>(user_info.max_buckets));
-
-    if (user_info.quota.user_quota.enabled){
-      dump_header(s, "X-RGW-Quota-User-Size", static_cast<long long>(user_info.quota.user_quota.max_size));
-      dump_header(s, "X-RGW-Quota-User-Objects", static_cast<long long>(user_info.quota.user_quota.max_objects));
-    }
+int RGWStatBucket_ObjStore_S3::get_params(optional_yield y)
+{
+  report_stats = s->info.args.exists("read-stats");
 
-    if (bucket_quota.enabled){
-      dump_header(s, "X-RGW-Quota-Bucket-Size", static_cast<long long>(bucket_quota.max_size));
-      dump_header(s, "X-RGW-Quota-Bucket-Objects", static_cast<long long>(bucket_quota.max_objects));
-    }
-  }
+  return 0;
 }
 
 void RGWStatBucket_ObjStore_S3::send_response()
 {
   if (op_ret >= 0) {
-    dump_bucket_metadata(s, bucket.get(), stats);
+    if (report_stats) {
+      dump_bucket_metadata(s, stats);
+    }
+    // only bucket's owner is allowed to get the quota settings of the account
+    if (s->auth.identity->is_owner_of(s->bucket->get_owner())) {
+      const auto& user_info = s->user->get_info();
+      const auto& bucket_quota = s->bucket->get_info().quota; // bucket quota
+
+      dump_header(s, "X-RGW-Quota-Max-Buckets", static_cast<long long>(user_info.max_buckets));
+      if (user_info.quota.user_quota.enabled) {
+        dump_header(s, "X-RGW-Quota-User-Size", static_cast<long long>(user_info.quota.user_quota.max_size));
+        dump_header(s, "X-RGW-Quota-User-Objects", static_cast<long long>(user_info.quota.user_quota.max_objects));
+      }
+      if (bucket_quota.enabled) {
+        dump_header(s, "X-RGW-Quota-Bucket-Size", static_cast<long long>(bucket_quota.max_size));
+        dump_header(s, "X-RGW-Quota-Bucket-Objects", static_cast<long long>(bucket_quota.max_objects));
+      }
+    }
   }
 
   set_req_state_err(s, op_ret);
index c47edb3885558e57210a35d86d835c9fd393ca1f..50160d79a42396afb8b6aec627114f34b0552bab 100644 (file)
@@ -242,6 +242,7 @@ public:
   ~RGWStatBucket_ObjStore_S3() override {}
 
   void send_response() override;
+  int get_params(optional_yield y) override;
 };
 
 class RGWCreateBucket_ObjStore_S3 : public RGWCreateBucket_ObjStore {
index 35c36d1ae1a66cc94b916316d98be21668e29b9f..b8ff3ca2fe8c06aff4d49f378b783931025c1a0c 100644 (file)
@@ -447,7 +447,6 @@ int RGWListBucket_ObjStore_SWIFT::get_params(optional_yield y)
 }
 
 static void dump_container_metadata(req_state *,
-                                    const rgw::sal::Bucket*,
                                     const std::optional<RGWStorageStats>& stats,
                                     const RGWQuotaInfo&,
                                     const RGWBucketWebsiteConf&);
@@ -458,7 +457,7 @@ void RGWListBucket_ObjStore_SWIFT::send_response()
   map<string, bool>::iterator pref_iter = common_prefixes.begin();
 
   dump_start(s);
-  dump_container_metadata(s, s->bucket.get(), stats, quota.bucket_quota,
+  dump_container_metadata(s, stats, quota.bucket_quota,
                           s->bucket->get_info().website_conf);
 
   s->formatter->open_array_section_with_attrs("container",
@@ -558,7 +557,6 @@ next:
 } // RGWListBucket_ObjStore_SWIFT::send_response
 
 static void dump_container_metadata(req_state *s,
-                                    const rgw::sal::Bucket* bucket,
                                     const std::optional<RGWStorageStats>& stats,
                                     const RGWQuotaInfo& quota,
                                     const RGWBucketWebsiteConf& ws_conf)
@@ -683,7 +681,7 @@ void RGWStatBucket_ObjStore_SWIFT::send_response()
 {
   if (op_ret >= 0) {
     op_ret = STATUS_NO_CONTENT;
-    dump_container_metadata(s, bucket.get(), stats, quota.bucket_quota,
+    dump_container_metadata(s, stats, quota.bucket_quota,
                             s->bucket->get_info().website_conf);
   }
 
@@ -2640,7 +2638,7 @@ RGWOp* RGWSwiftWebsiteHandler::get_ws_listing_op()
       /* Generate the header now. */
       set_req_state_err(s, op_ret);
       dump_errno(s);
-      dump_container_metadata(s, s->bucket.get(), stats, quota.bucket_quota,
+      dump_container_metadata(s, stats, quota.bucket_quota,
                               s->bucket->get_info().website_conf);
       end_header(s, this, "text/html");
       if (op_ret < 0) {
index eb1c4422e34b85943d023726b273b0b2a7cf4031..ec206a5160f394f011e6c380173e85d2b4c95662 100644 (file)
@@ -86,6 +86,7 @@ public:
   RGWStatBucket_ObjStore_SWIFT() {}
   ~RGWStatBucket_ObjStore_SWIFT() override {}
 
+  int get_params(optional_yield y) override { return 0; }
   void send_response() override;
 };