]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
RGW Zipper - don't reference instance in bucket APIs
authorDaniel Gryniewicz <dang@redhat.com>
Fri, 20 Aug 2021 16:05:00 +0000 (12:05 -0400)
committerDaniel Gryniewicz <dang@redhat.com>
Fri, 20 Aug 2021 17:03:52 +0000 (13:03 -0400)
Signed-off-by: Daniel Gryniewicz <dang@redhat.com>
src/rgw/rgw_admin.cc
src/rgw/rgw_bucket.cc
src/rgw/rgw_lc.cc
src/rgw/rgw_op.cc
src/rgw/rgw_sal.h
src/rgw/rgw_sal_dbstore.cc
src/rgw/rgw_sal_dbstore.h
src/rgw/rgw_sal_rados.cc
src/rgw/rgw_sal_rados.h

index 71ba340d12b5e76c793c8d6c6daef653c5c67d03..09d39433984ecf522c2bf0cac47d0971edd94d99 100644 (file)
@@ -1313,7 +1313,7 @@ int set_bucket_quota(rgw::sal::Store* store, OPT opt_cmd,
 
   set_quota_info(bucket->get_info().quota, opt_cmd, max_size, max_objects, have_max_size, have_max_objects);
 
-  r = bucket->put_instance_info(dpp(), false, real_time());
+  r = bucket->put_info(dpp(), false, real_time());
   if (r < 0) {
     cerr << "ERROR: failed writing bucket instance info: " << cpp_strerror(-r) << std::endl;
     return -r;
@@ -2918,7 +2918,7 @@ public:
       return 0;
     }
 
-    int ret = bucket->put_instance_info(dpp(), false, real_time());
+    int ret = bucket->put_info(dpp(), false, real_time());
     if (ret < 0) {
       cerr << "failed to store bucket info: " << cpp_strerror(-ret) << std::endl;
       return -ret;
index bc34ec821aa70ab851287558fe20a34a7722a341..edc7f8027311fd19cf7c01afa2d852cdb456818e 100644 (file)
@@ -422,7 +422,7 @@ int RGWBucket::set_quota(RGWBucketAdminOpState& op_state, const DoutPrefixProvid
   bucket = op_state.get_bucket()->clone();
 
   bucket->get_info().quota = op_state.quota;
-  int r = bucket->put_instance_info(dpp, false, real_time());
+  int r = bucket->put_info(dpp, false, real_time());
   if (r < 0) {
     set_err_msg(err_msg, "ERROR: failed writing bucket instance info: " + cpp_strerror(-r));
     return r;
@@ -663,7 +663,7 @@ int RGWBucket::sync(RGWBucketAdminOpState& op_state, const DoutPrefixProvider *d
     bucket->get_info().flags |= BUCKET_DATASYNC_DISABLED;
   }
 
-  int r = bucket->put_instance_info(dpp, false, real_time());
+  int r = bucket->put_info(dpp, false, real_time());
   if (r < 0) {
     set_err_msg(err_msg, "ERROR: failed writing bucket instance info:" + cpp_strerror(-r));
     return r;
@@ -911,7 +911,7 @@ int RGWBucketAdminOp::link(rgw::sal::Store* store, RGWBucketAdminOpState& op_sta
     exclusive = true;
   }
 
-  r = loc_bucket->put_instance_info(dpp, exclusive, ceph::real_time());
+  r = loc_bucket->put_info(dpp, exclusive, ceph::real_time());
   if (r < 0) {
     set_err_msg(err, "ERROR: failed writing bucket instance info: " + cpp_strerror(-r));
     return r;
index 3f186a5c970db5dcb12761959b95d1ed6d83ea9d..485848d22975a7cc21379f241c12e23a7ecf6371 100644 (file)
@@ -2009,7 +2009,7 @@ int RGWLC::set_bucket_config(rgw::sal::Bucket* bucket,
   attrs[RGW_ATTR_LC] = std::move(lc_bl);
 
   int ret =
-    bucket->set_instance_attrs(this, attrs, null_yield);
+    bucket->merge_and_store_attrs(this, attrs, null_yield);
   if (ret < 0)
     return ret;
 
@@ -2030,7 +2030,7 @@ int RGWLC::remove_bucket_config(rgw::sal::Bucket* bucket,
 {
   rgw::sal::Attrs attrs = bucket_attrs;
   attrs.erase(RGW_ATTR_LC);
-  int ret = bucket->set_instance_attrs(this, attrs, null_yield);
+  int ret = bucket->merge_and_store_attrs(this, attrs, null_yield);
 
   rgw_bucket& b = bucket->get_key();
 
index 6c9d19e43ec3767153a553fa5b232e9677c32077..1a04e5c21eb0edee7913e3de28f5a502c3027c4f 100644 (file)
@@ -1064,7 +1064,7 @@ void RGWPutBucketTags::execute(optional_yield y)
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this, y] {
     rgw::sal::Attrs attrs = s->bucket->get_attrs();
     attrs[RGW_ATTR_TAGS] = tags_bl;
-    return s->bucket->set_instance_attrs(this, attrs, y);
+    return s->bucket->merge_and_store_attrs(this, attrs, y);
   });
 
 }
@@ -1091,7 +1091,7 @@ void RGWDeleteBucketTags::execute(optional_yield y)
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this, y] {
     rgw::sal::Attrs attrs = s->bucket->get_attrs();
     attrs.erase(RGW_ATTR_TAGS);
-    op_ret = s->bucket->set_instance_attrs(this, attrs, y);
+    op_ret = s->bucket->merge_and_store_attrs(this, attrs, y);
     if (op_ret < 0) {
       ldpp_dout(this, 0) << "RGWDeleteBucketTags() failed to remove RGW_ATTR_TAGS on bucket="
                         << s->bucket->get_name()
@@ -1145,7 +1145,7 @@ void RGWPutBucketReplication::execute(optional_yield y) {
 
     s->bucket->get_info().set_sync_policy(std::move(sync_policy));
 
-    int ret = s->bucket->put_instance_info(this, false, real_time());
+    int ret = s->bucket->put_info(this, false, real_time());
     if (ret < 0) {
       ldpp_dout(this, 0) << "ERROR: put_bucket_instance_info (bucket=" << s->bucket << ") returned ret=" << ret << dendl;
       return ret;
@@ -1185,7 +1185,7 @@ void RGWDeleteBucketReplication::execute(optional_yield y)
 
     s->bucket->get_info().set_sync_policy(std::move(sync_policy));
 
-    int ret = s->bucket->put_instance_info(this, false, real_time());
+    int ret = s->bucket->put_info(this, false, real_time());
     if (ret < 0) {
       ldpp_dout(this, 0) << "ERROR: put_bucket_instance_info (bucket=" << s->bucket << ") returned ret=" << ret << dendl;
       return ret;
@@ -2535,7 +2535,7 @@ void RGWSetBucketVersioning::execute(optional_yield y)
        return op_ret;
       }
       s->bucket->set_attrs(rgw::sal::Attrs(s->bucket_attrs));
-      return s->bucket->put_instance_info(this, false, real_time());
+      return s->bucket->put_info(this, false, real_time());
     });
 
   if (!modified) {
@@ -2597,7 +2597,7 @@ void RGWSetBucketWebsite::execute(optional_yield y)
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this] {
       s->bucket->get_info().has_website = true;
       s->bucket->get_info().website_conf = website_conf;
-      op_ret = s->bucket->put_instance_info(this, false, real_time());
+      op_ret = s->bucket->put_info(this, false, real_time());
       return op_ret;
     });
 
@@ -2636,7 +2636,7 @@ void RGWDeleteBucketWebsite::execute(optional_yield y)
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this] {
       s->bucket->get_info().has_website = false;
       s->bucket->get_info().website_conf = RGWBucketWebsiteConf();
-      op_ret = s->bucket->put_instance_info(this, false, real_time());
+      op_ret = s->bucket->put_info(this, false, real_time());
       return op_ret;
     });
   if (op_ret < 0) {
@@ -3163,7 +3163,7 @@ void RGWCreateBucket::execute(optional_yield y)
       s->bucket->get_info().has_website = !s->bucket->get_info().website_conf.is_empty();
 
       /* This will also set the quota on the bucket. */
-      op_ret = s->bucket->set_instance_attrs(this, attrs, y);
+      op_ret = s->bucket->merge_and_store_attrs(this, attrs, y);
     } while (op_ret == -ECANCELED && tries++ < 20);
 
     /* Restore the proper return code. */
@@ -4493,7 +4493,7 @@ void RGWPutMetadataBucket::execute(optional_yield y)
       /* Setting attributes also stores the provided bucket info. Due
        * to this fact, the new quota settings can be serialized with
        * the same call. */
-      op_ret = s->bucket->set_instance_attrs(this, attrs, s->yield);
+      op_ret = s->bucket->merge_and_store_attrs(this, attrs, s->yield);
       return op_ret;
     });
 }
@@ -5520,7 +5520,7 @@ void RGWPutACLs::execute(optional_yield y)
   } else {
     map<string,bufferlist> attrs = s->bucket_attrs;
     attrs[RGW_ATTR_ACL] = bl;
-    op_ret = s->bucket->set_instance_attrs(this, attrs, y);
+    op_ret = s->bucket->merge_and_store_attrs(this, attrs, y);
   }
   if (op_ret == -ECANCELED) {
     op_ret = 0; /* lost a race, but it's ok because acls are immutable */
@@ -5675,7 +5675,7 @@ void RGWPutCORS::execute(optional_yield y)
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this] {
       rgw::sal::Attrs attrs(s->bucket_attrs);
       attrs[RGW_ATTR_CORS] = cors_bl;
-      return s->bucket->set_instance_attrs(this, attrs, s->yield);
+      return s->bucket->merge_and_store_attrs(this, attrs, s->yield);
     });
 }
 
@@ -5707,7 +5707,7 @@ void RGWDeleteCORS::execute(optional_yield y)
 
       rgw::sal::Attrs attrs(s->bucket_attrs);
       attrs.erase(RGW_ATTR_CORS);
-      op_ret = s->bucket->set_instance_attrs(this, attrs, s->yield);
+      op_ret = s->bucket->merge_and_store_attrs(this, attrs, s->yield);
       if (op_ret < 0) {
        ldpp_dout(this, 0) << "RGWLC::RGWDeleteCORS() failed to set attrs on bucket=" << s->bucket->get_name()
                         << " returned err=" << op_ret << dendl;
@@ -5810,7 +5810,7 @@ void RGWSetRequestPayment::execute(optional_yield y)
     return;
 
   s->bucket->get_info().requester_pays = requester_pays;
-  op_ret = s->bucket->put_instance_info(this, false, real_time());
+  op_ret = s->bucket->put_info(this, false, real_time());
   if (op_ret < 0) {
     ldpp_dout(this, 0) << "NOTICE: put_bucket_info on bucket=" << s->bucket->get_name()
                     << " returned err=" << op_ret << dendl;
@@ -7465,7 +7465,7 @@ void RGWSetAttrs::execute(optional_yield y)
     rgw::sal::Attrs a(attrs);
     op_ret = s->object->set_obj_attrs(this, s->obj_ctx, &a, nullptr, y);
   } else {
-    op_ret = s->bucket->set_instance_attrs(this, attrs, y);
+    op_ret = s->bucket->merge_and_store_attrs(this, attrs, y);
   }
 
 } /* RGWSetAttrs::execute() */
@@ -7506,7 +7506,7 @@ void RGWConfigBucketMetaSearch::execute(optional_yield y)
 
   s->bucket->get_info().mdsearch_config = mdsearch_config;
 
-  op_ret = s->bucket->put_instance_info(this, false, real_time());
+  op_ret = s->bucket->put_info(this, false, real_time());
   if (op_ret < 0) {
     ldpp_dout(this, 0) << "NOTICE: put_bucket_info on bucket=" << s->bucket->get_name()
         << " returned err=" << op_ret << dendl;
@@ -7547,7 +7547,7 @@ void RGWDelBucketMetaSearch::execute(optional_yield y)
 {
   s->bucket->get_info().mdsearch_config.clear();
 
-  op_ret = s->bucket->put_instance_info(this, false, real_time());
+  op_ret = s->bucket->put_info(this, false, real_time());
   if (op_ret < 0) {
     ldpp_dout(this, 0) << "NOTICE: put_bucket_info on bucket=" << s->bucket->get_name()
         << " returned err=" << op_ret << dendl;
@@ -7687,7 +7687,7 @@ void RGWPutBucketPolicy::execute(optional_yield y)
     op_ret = retry_raced_bucket_write(this, s->bucket.get(), [&p, this, &attrs] {
        attrs[RGW_ATTR_IAM_POLICY].clear();
        attrs[RGW_ATTR_IAM_POLICY].append(p.text);
-       op_ret = s->bucket->set_instance_attrs(this, attrs, s->yield);
+       op_ret = s->bucket->merge_and_store_attrs(this, attrs, s->yield);
        return op_ret;
       });
   } catch (rgw::IAM::PolicyParseException& e) {
@@ -7768,7 +7768,7 @@ void RGWDeleteBucketPolicy::execute(optional_yield y)
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this] {
       rgw::sal::Attrs attrs(s->bucket_attrs);
       attrs.erase(RGW_ATTR_IAM_POLICY);
-      op_ret = s->bucket->set_instance_attrs(this, attrs, s->yield);
+      op_ret = s->bucket->merge_and_store_attrs(this, attrs, s->yield);
       return op_ret;
     });
 }
@@ -7829,7 +7829,7 @@ void RGWPutBucketObjectLock::execute(optional_yield y)
 
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this] {
     s->bucket->get_info().obj_lock = obj_lock;
-    op_ret = s->bucket->put_instance_info(this, false, real_time());
+    op_ret = s->bucket->put_info(this, false, real_time());
     return op_ret;
   });
   return;
@@ -8166,7 +8166,7 @@ void RGWPutBucketPublicAccessBlock::execute(optional_yield y)
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this, &bl] {
       rgw::sal::Attrs attrs(s->bucket_attrs);
       attrs[RGW_ATTR_PUBLIC_ACCESS] = bl;
-      return s->bucket->set_instance_attrs(this, attrs, s->yield);
+      return s->bucket->merge_and_store_attrs(this, attrs, s->yield);
     });
 
 }
@@ -8232,7 +8232,7 @@ void RGWDeleteBucketPublicAccessBlock::execute(optional_yield y)
   op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this] {
       rgw::sal::Attrs attrs(s->bucket_attrs);
       attrs.erase(RGW_ATTR_PUBLIC_ACCESS);
-      op_ret = s->bucket->set_instance_attrs(this, attrs, s->yield);
+      op_ret = s->bucket->merge_and_store_attrs(this, attrs, s->yield);
       return op_ret;
     });
 }
@@ -8308,7 +8308,7 @@ void RGWPutBucketEncryption::execute(optional_yield y)
     rgw::sal::Attrs attrs = s->bucket->get_attrs();
     attrs[RGW_ATTR_BUCKET_ENCRYPTION_POLICY] = conf_bl;
     attrs[RGW_ATTR_BUCKET_ENCRYPTION_KEY_ID] = key_id_bl;
-    return s->bucket->set_instance_attrs(this, attrs, y);
+    return s->bucket->merge_and_store_attrs(this, attrs, y);
   });
 }
 
@@ -8362,7 +8362,7 @@ void RGWDeleteBucketEncryption::execute(optional_yield y)
     rgw::sal::Attrs attrs = s->bucket->get_attrs();
     attrs.erase(RGW_ATTR_BUCKET_ENCRYPTION_POLICY);
     attrs.erase(RGW_ATTR_BUCKET_ENCRYPTION_KEY_ID);
-    op_ret = s->bucket->set_instance_attrs(this, attrs, y);
+    op_ret = s->bucket->merge_and_store_attrs(this, attrs, y);
     return op_ret;
   });
 }
index fcd8de14eab704c5f8a0bacfeabd01b8041f4679..92c2bddee61116b6c75e46466908b25ae7f87c8e 100644 (file)
@@ -441,14 +441,21 @@ class Bucket {
     virtual int update_container_stats(const DoutPrefixProvider* dpp) = 0;
     virtual int check_bucket_shards(const DoutPrefixProvider* dpp) = 0;
     virtual int chown(const DoutPrefixProvider* dpp, User* new_user, User* old_user, optional_yield y, const std::string* marker = nullptr) = 0;
-    virtual int put_instance_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time mtime) = 0;
+    virtual int put_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time mtime) = 0;
     virtual int remove_metadata(const DoutPrefixProvider* dpp, RGWObjVersionTracker* objv, optional_yield y) = 0;
     virtual bool is_owner(User* user) = 0;
     virtual User* get_owner(void) { return owner; };
     virtual ACLOwner get_acl_owner(void) { return ACLOwner(info.owner); };
     virtual int check_empty(const DoutPrefixProvider* dpp, optional_yield y) = 0;
     virtual int check_quota(const DoutPrefixProvider *dpp, RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t obj_size, optional_yield y, bool check_size_only = false) = 0;
-    virtual int set_instance_attrs(const DoutPrefixProvider* dpp, Attrs& attrs, optional_yield y) = 0;
+    /** Set the attributes in attrs, leaving any other existing attrs set, and
+     * write them to the backing store; a merge operation */
+    virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y) {
+      for(auto& it : new_attrs) {
+       attrs[it.first] = it.second;
+      }
+      return 0;
+    }
     virtual int try_refresh_info(const DoutPrefixProvider* dpp, ceph::real_time* pmtime) = 0;
     virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
                           bool* is_truncated, RGWUsageIter& usage_iter,
index 99dc875316e00b8bd59b9cc5a6fb7d9fff450996..dcb968e6c34c40c5c443c4bfd247da3f963a6011 100644 (file)
@@ -206,7 +206,7 @@ namespace rgw::sal {
     return ret;
   }
 
-  int DBBucket::put_instance_info(const DoutPrefixProvider *dpp, bool exclusive, ceph::real_time _mtime)
+  int DBBucket::put_info(const DoutPrefixProvider *dpp, bool exclusive, ceph::real_time _mtime)
   {
     int ret;
 
@@ -245,13 +245,15 @@ namespace rgw::sal {
     return 0;
   }
 
-  int DBBucket::set_instance_attrs(const DoutPrefixProvider *dpp, Attrs& attrs, optional_yield y)
+  int DBBucket::merge_and_store_attrs(const DoutPrefixProvider *dpp, Attrs& new_attrs, optional_yield y)
   {
     int ret = 0;
 
+    Bucket::merge_and_store_attrs(dpp, new_attrs, y);
+
     /* XXX: handle has_instance_obj like in set_bucket_instance_attrs() */
 
-    ret = store->getDB()->update_bucket(dpp, "attrs", info, false, nullptr, &attrs, nullptr, &get_info().objv_tracker);
+    ret = store->getDB()->update_bucket(dpp, "attrs", info, false, nullptr, &new_attrs, nullptr, &get_info().objv_tracker);
 
     return ret;
   }
index 01eef17246d60b5b53ff8f4ae79ec06cbacc0abb..2b95af27216e47a481f07cca1834e9803c0e3ef9 100644 (file)
@@ -140,12 +140,12 @@ namespace rgw { namespace sal {
       virtual int update_container_stats(const DoutPrefixProvider *dpp) override;
       virtual int check_bucket_shards(const DoutPrefixProvider *dpp) override;
       virtual int chown(const DoutPrefixProvider *dpp, User* new_user, User* old_user, optional_yield y, const std::string* marker = nullptr) override;
-      virtual int put_instance_info(const DoutPrefixProvider *dpp, bool exclusive, ceph::real_time mtime) override;
+      virtual int put_info(const DoutPrefixProvider *dpp, bool exclusive, ceph::real_time mtime) override;
       virtual int remove_metadata(const DoutPrefixProvider* dpp, RGWObjVersionTracker* objv, optional_yield y) override;
       virtual bool is_owner(User* user) override;
       virtual int check_empty(const DoutPrefixProvider *dpp, optional_yield y) override;
       virtual int check_quota(const DoutPrefixProvider *dpp, RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t obj_size, optional_yield y, bool check_size_only = false) override;
-      virtual int set_instance_attrs(const DoutPrefixProvider *dpp, Attrs& attrs, optional_yield y) override;
+      virtual int merge_and_store_attrs(const DoutPrefixProvider *dpp, Attrs& attrs, optional_yield y) override;
       virtual int try_refresh_info(const DoutPrefixProvider *dpp, ceph::real_time *pmtime) override;
       virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
           bool *is_truncated, RGWUsageIter& usage_iter,
index 74b9960667c1795fd337299ede52c30eef1ba0e2..11428f1363ce71125c67ef1206d6ecf275ab2a3b 100644 (file)
@@ -594,7 +594,7 @@ int RadosBucket::chown(const DoutPrefixProvider* dpp, User* new_user, User* old_
                           old_user->get_display_name(), *marker, y, dpp);
 }
 
-int RadosBucket::put_instance_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time _mtime)
+int RadosBucket::put_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time _mtime)
 {
   mtime = _mtime;
   return store->getRados()->put_bucket_instance_info(info, exclusive, mtime, &attrs, dpp);
@@ -631,10 +631,11 @@ int RadosBucket::check_quota(const DoutPrefixProvider *dpp, RGWQuotaInfo& user_q
                                          user_quota, bucket_quota, obj_size, y, check_size_only);
 }
 
-int RadosBucket::set_instance_attrs(const DoutPrefixProvider* dpp, Attrs& attrs, optional_yield y)
+int RadosBucket::merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y)
 {
-    return store->ctl()->bucket->set_bucket_instance_attrs(get_info(),
-                               attrs, &get_info().objv_tracker, y, dpp);
+  Bucket::merge_and_store_attrs(dpp, new_attrs, y);
+  return store->ctl()->bucket->set_bucket_instance_attrs(get_info(),
+                               new_attrs, &get_info().objv_tracker, y, dpp);
 }
 
 int RadosBucket::try_refresh_info(const DoutPrefixProvider* dpp, ceph::real_time* pmtime)
index bb6bd4df099d68d465b11659e218e6008dd635fc..bf8a9539195828d043d2e2d29bdf87ebd0352e1e 100644 (file)
@@ -287,12 +287,12 @@ class RadosBucket : public Bucket {
     virtual int update_container_stats(const DoutPrefixProvider* dpp) override;
     virtual int check_bucket_shards(const DoutPrefixProvider* dpp) override;
     virtual int chown(const DoutPrefixProvider* dpp, User* new_user, User* old_user, optional_yield y, const std::string* marker = nullptr) override;
-    virtual int put_instance_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time mtime) override;
+    virtual int put_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time mtime) override;
     virtual int remove_metadata(const DoutPrefixProvider* dpp, RGWObjVersionTracker* objv, optional_yield y) override;
     virtual bool is_owner(User* user) override;
     virtual int check_empty(const DoutPrefixProvider* dpp, optional_yield y) override;
     virtual int check_quota(const DoutPrefixProvider *dpp, RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t obj_size, optional_yield y, bool check_size_only = false) override;
-    virtual int set_instance_attrs(const DoutPrefixProvider* dpp, Attrs& attrs, optional_yield y) override;
+    virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& attrs, optional_yield y) override;
     virtual int try_refresh_info(const DoutPrefixProvider* dpp, ceph::real_time* pmtime) override;
     virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries,
                           bool* is_truncated, RGWUsageIter& usage_iter,