From 6bca3bc0ec0cd154e6e6c2289db4605ef45f0b17 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Sat, 16 Dec 2023 10:47:44 -0500 Subject: [PATCH] rgw/sal: move list_buckets() to Driver move User::list_buckets() to Driver and take rgw_owner to serve bucket listings for account owners also unifies the user/account stats interfaces around rgw_owner in Driver Signed-off-by: Casey Bodley (cherry picked from commit d76ef3294735a42253a3718dd519f55283bdd3b4) --- src/rgw/driver/daos/rgw_sal_daos.cc | 13 +-- src/rgw/driver/daos/rgw_sal_daos.h | 8 +- src/rgw/driver/motr/rgw_sal_motr.cc | 13 +-- src/rgw/driver/motr/rgw_sal_motr.h | 6 +- src/rgw/driver/posix/rgw_sal_posix.cc | 11 ++- src/rgw/driver/posix/rgw_sal_posix.h | 9 +- src/rgw/driver/rados/rgw_bucket.cc | 114 ++++++++++++++-------- src/rgw/driver/rados/rgw_bucket.h | 9 +- src/rgw/driver/rados/rgw_sal_rados.cc | 106 ++++++++++++++------- src/rgw/driver/rados/rgw_sal_rados.h | 38 ++++---- src/rgw/driver/rados/rgw_user.cc | 63 +++---------- src/rgw/driver/rados/rgw_user.h | 20 +--- src/rgw/rgw_account.cc | 43 ++++++--- src/rgw/rgw_account.h | 3 +- src/rgw/rgw_admin.cc | 15 ++- src/rgw/rgw_auth.cc | 5 +- src/rgw/rgw_op.cc | 88 ++++++++++++----- src/rgw/rgw_quota.cc | 130 +++++++++++++++----------- src/rgw/rgw_sal.h | 75 ++++++++------- src/rgw/rgw_sal_dbstore.cc | 62 ++++++------ src/rgw/rgw_sal_dbstore.h | 36 +++---- src/rgw/rgw_sal_filter.cc | 70 +++++++------- src/rgw/rgw_sal_filter.h | 42 +++++---- src/rgw/rgw_user.cc | 20 ++-- src/rgw/services/svc_user.h | 35 ------- src/rgw/services/svc_user_rados.cc | 97 ------------------- src/rgw/services/svc_user_rados.h | 41 -------- src/test/rgw/test_rgw_lua.cc | 12 --- 28 files changed, 567 insertions(+), 617 deletions(-) diff --git a/src/rgw/driver/daos/rgw_sal_daos.cc b/src/rgw/driver/daos/rgw_sal_daos.cc index 765655d7430..e62495c3ac9 100644 --- a/src/rgw/driver/daos/rgw_sal_daos.cc +++ b/src/rgw/driver/daos/rgw_sal_daos.cc @@ -45,10 +45,11 @@ namespace rgw::sal { using ::ceph::decode; using ::ceph::encode; -int DaosUser::list_buckets(const DoutPrefixProvider* dpp, const string& marker, - const string& end_marker, uint64_t max, - bool need_stats, BucketList& buckets, - optional_yield y) { +int DaosStore::list_buckets(const DoutPrefixProvider* dpp, + const rgw_owner& owner, const std::string& tenant, + const string& marker, const string& end_marker, + uint64_t max, bool need_stats, BucketList& buckets, + optional_yield y) { ldpp_dout(dpp, 20) << "DEBUG: list_user_buckets: marker=" << marker << " end_marker=" << end_marker << " max=" << max << dendl; int ret = 0; @@ -65,7 +66,7 @@ int DaosUser::list_buckets(const DoutPrefixProvider* dpp, const string& marker, char daos_marker[DS3_MAX_BUCKET_NAME]; std::strncpy(daos_marker, marker.c_str(), sizeof(daos_marker)); ret = ds3_bucket_list(&bcount, bucket_infos.data(), daos_marker, - &is_truncated, store->ds3, nullptr); + &is_truncated, ds3, nullptr); ldpp_dout(dpp, 20) << "DEBUG: ds3_bucket_list: bcount=" << bcount << " ret=" << ret << dendl; if (ret != 0) { @@ -82,7 +83,7 @@ int DaosUser::list_buckets(const DoutPrefixProvider* dpp, const string& marker, bl.append(reinterpret_cast(bi.encoded), bi.encoded_length); auto iter = bl.cbegin(); dbinfo.decode(iter); - buckets.add(std::make_unique(this->store, dbinfo.info, this)); + buckets.add(std::make_unique(this, dbinfo.info, this)); } buckets.set_truncated(is_truncated); diff --git a/src/rgw/driver/daos/rgw_sal_daos.h b/src/rgw/driver/daos/rgw_sal_daos.h index b4f65c5d82f..04263e50dd8 100644 --- a/src/rgw/driver/daos/rgw_sal_daos.h +++ b/src/rgw/driver/daos/rgw_sal_daos.h @@ -168,9 +168,6 @@ class DaosUser : public StoreUser { virtual std::unique_ptr clone() override { return std::make_unique(*this); } - int list_buckets(const DoutPrefixProvider* dpp, const std::string& marker, - const std::string& end_marker, uint64_t max, bool need_stats, - BucketList& buckets, optional_yield y) override; virtual int create_bucket( const DoutPrefixProvider* dpp, const rgw_bucket& b, const std::string& zonegroup_id, rgw_placement_rule& placement_rule, @@ -903,6 +900,11 @@ class DaosStore : public StoreDriver { int load_bucket(const DoutPrefixProvider* dpp, User* u, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) override; + int list_buckets(const DoutPrefixProvider* dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, + BucketList& buckets, optional_yield y) override; virtual bool is_meta_master() override; virtual Zone* get_zone() { return &zone; } virtual std::string zone_unique_id(uint64_t unique_num) override; diff --git a/src/rgw/driver/motr/rgw_sal_motr.cc b/src/rgw/driver/motr/rgw_sal_motr.cc index 32ede60d8df..ee90ba42a38 100644 --- a/src/rgw/driver/motr/rgw_sal_motr.cc +++ b/src/rgw/driver/motr/rgw_sal_motr.cc @@ -157,9 +157,10 @@ void MotrMetaCache::set_enabled(bool status) // TODO: properly handle the number of key/value pairs to get in // one query. Now the POC simply tries to retrieve all `max` number of pairs // with starting key `marker`. -int MotrUser::list_buckets(const DoutPrefixProvider *dpp, const string& marker, - const string& end_marker, uint64_t max, bool need_stats, - BucketList &buckets, optional_yield y) +int MotrStore::list_buckets(const DoutPrefixProvider *dpp, + const rgw_owner& owner, const std::string& tenant, + const string& marker, const string& end_marker, uint64_t max, + bool need_stats, BucketList &buckets, optional_yield y) { int rc; vector keys(max); @@ -172,9 +173,9 @@ int MotrUser::list_buckets(const DoutPrefixProvider *dpp, const string& marker, // Retrieve all `max` number of pairs. buckets.clear(); - string user_info_iname = "motr.rgw.user.info." + info.user_id.to_str(); + string user_info_iname = "motr.rgw.user.info." + to_string(owner); keys[0] = marker; - rc = store->next_query_by_name(user_info_iname, keys, vals); + rc = next_query_by_name(user_info_iname, keys, vals); if (rc < 0) { ldpp_dout(dpp, 0) << "ERROR: NEXT query failed. " << rc << dendl; return rc; @@ -197,7 +198,7 @@ int MotrUser::list_buckets(const DoutPrefixProvider *dpp, const string& marker, end_marker.compare(ent.bucket.marker) <= 0) break; - buckets.add(std::make_unique(this->store, ent, this)); + buckets.add(std::make_unique(this, ent, this)); bcount++; } if (bcount == max) diff --git a/src/rgw/driver/motr/rgw_sal_motr.h b/src/rgw/driver/motr/rgw_sal_motr.h index 8865b93be88..c9ffcffc2d4 100644 --- a/src/rgw/driver/motr/rgw_sal_motr.h +++ b/src/rgw/driver/motr/rgw_sal_motr.h @@ -219,8 +219,6 @@ class MotrUser : public StoreUser { virtual std::unique_ptr clone() override { return std::unique_ptr(new MotrUser(*this)); } - int list_buckets(const DoutPrefixProvider *dpp, const std::string& marker, const std::string& end_marker, - uint64_t max, bool need_stats, BucketList& buckets, optional_yield y) override; virtual int create_bucket(const DoutPrefixProvider* dpp, const rgw_bucket& b, const std::string& zonegroup_id, @@ -999,6 +997,10 @@ class MotrStore : public StoreDriver { std::unique_ptr get_bucket(User* u, const RGWBucketInfo& i) override; int load_bucket(const DoutPrefixProvider *dpp, User* u, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) override; + int list_buckets(const DoutPrefixProvider *dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, BucketList& buckets, optional_yield y) override; virtual bool is_meta_master() override; virtual Zone* get_zone() { return &zone; } virtual std::string zone_unique_id(uint64_t unique_num) override; diff --git a/src/rgw/driver/posix/rgw_sal_posix.cc b/src/rgw/driver/posix/rgw_sal_posix.cc index 1dc548c360c..9b1b34fa9e4 100644 --- a/src/rgw/driver/posix/rgw_sal_posix.cc +++ b/src/rgw/driver/posix/rgw_sal_posix.cc @@ -444,7 +444,8 @@ int POSIXDriver::close() } // TODO: marker and other params -int POSIXUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& marker, +int POSIXDriver::list_buckets(const DoutPrefixProvider* dpp, const rgw_owner& owner, + const std::string& tenant, const std::string& marker, const std::string& end_marker, uint64_t max, bool need_stats, BucketList &result, optional_yield y) { @@ -457,7 +458,7 @@ int POSIXUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& ma /* it's not sufficient to dup(root_fd), as as the new fd would share * the file position of root_fd */ - dfd = copy_dir_fd(driver->get_root_fd()); + dfd = copy_dir_fd(get_root_fd()); if (dfd == -1) { ret = errno; ldpp_dout(dpp, 0) << "ERROR: could not open root to list buckets: " @@ -470,7 +471,7 @@ int POSIXUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& ma ret = errno; ldpp_dout(dpp, 0) << "ERROR: could not open root to list buckets: " << cpp_strerror(ret) << dendl; - close(dfd); + ::close(dfd); return -ret; } @@ -486,7 +487,7 @@ int POSIXUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& ma while ((entry = readdir(dir)) != NULL) { struct statx stx; - ret = statx(driver->get_root_fd(), entry->d_name, AT_SYMLINK_NOFOLLOW, STATX_ALL, &stx); + ret = statx(get_root_fd(), entry->d_name, AT_SYMLINK_NOFOLLOW, STATX_ALL, &stx); if (ret < 0) { ret = errno; ldpp_dout(dpp, 0) << "ERROR: could not stat object " << entry->d_name << ": " @@ -516,7 +517,7 @@ int POSIXUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& ma } ret = errno; if (ret != 0) { - ldpp_dout(dpp, 0) << "ERROR: could not list buckets for " << get_display_name() << ": " + ldpp_dout(dpp, 0) << "ERROR: could not list buckets for " << owner << ": " << cpp_strerror(ret) << dendl; return -ret; } diff --git a/src/rgw/driver/posix/rgw_sal_posix.h b/src/rgw/driver/posix/rgw_sal_posix.h index 785192afee1..587bf783e90 100644 --- a/src/rgw/driver/posix/rgw_sal_posix.h +++ b/src/rgw/driver/posix/rgw_sal_posix.h @@ -55,6 +55,11 @@ public: virtual std::unique_ptr get_bucket(const RGWBucketInfo& i) override; virtual int load_bucket(const DoutPrefixProvider* dpp, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) override; + virtual int list_buckets(const DoutPrefixProvider* dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, BucketList& buckets, + optional_yield y) override; virtual std::string zone_unique_trans_id(const uint64_t unique_num) override; virtual std::unique_ptr get_append_writer(const DoutPrefixProvider *dpp, @@ -116,10 +121,6 @@ public: driver(_driver) {} virtual ~POSIXUser() = default; - virtual int list_buckets(const DoutPrefixProvider* dpp, - const std::string& marker, const std::string& end_marker, - uint64_t max, bool need_stats, BucketList& buckets, - optional_yield y) override; virtual Attrs& get_attrs() override { return next->get_attrs(); } virtual void set_attrs(Attrs& _attrs) override { next->set_attrs(_attrs); } virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) override; diff --git a/src/rgw/driver/rados/rgw_bucket.cc b/src/rgw/driver/rados/rgw_bucket.cc index 5af2230a024..e6c30497adb 100644 --- a/src/rgw/driver/rados/rgw_bucket.cc +++ b/src/rgw/driver/rados/rgw_bucket.cc @@ -93,17 +93,18 @@ static void dump_mulipart_index_results(list& objs_to_unlink, } } -void check_bad_user_bucket_mapping(rgw::sal::Driver* driver, rgw::sal::User& user, - bool fix, - optional_yield y, - const DoutPrefixProvider *dpp) +void check_bad_owner_bucket_mapping(rgw::sal::Driver* driver, + const rgw_owner& owner, + const std::string& tenant, + bool fix, optional_yield y, + const DoutPrefixProvider *dpp) { size_t max_entries = dpp->get_cct()->_conf->rgw_list_buckets_max_chunk; rgw::sal::BucketList listing; do { - int ret = user.list_buckets(dpp, listing.next_marker, string(), - max_entries, false, listing, y); + int ret = driver->list_buckets(dpp, owner, tenant, listing.next_marker, + string(), max_entries, false, listing, y); if (ret < 0) { ldpp_dout(dpp, 0) << "failed to read user buckets: " << cpp_strerror(-ret) << dendl; @@ -112,7 +113,7 @@ void check_bad_user_bucket_mapping(rgw::sal::Driver* driver, rgw::sal::User& use for (const auto& ent : listing.buckets) { std::unique_ptr bucket; - int r = driver->load_bucket(dpp, rgw_bucket(user.get_tenant(), ent.bucket.name), + int r = driver->load_bucket(dpp, rgw_bucket(tenant, ent.bucket.name), &bucket, y); if (r < 0) { ldpp_dout(dpp, 0) << "could not get bucket info for bucket=" << bucket << dendl; @@ -124,7 +125,7 @@ void check_bad_user_bucket_mapping(rgw::sal::Driver* driver, rgw::sal::User& use << " got " << bucket << std::endl; if (fix) { cout << "fixing" << std::endl; - r = bucket->chown(dpp, user.get_id(), y); + r = bucket->chown(dpp, owner, y); if (r < 0) { cerr << "failed to fix bucket: " << cpp_strerror(-r) << std::endl; } @@ -1383,7 +1384,7 @@ int RGWBucketAdminOp::limit_check(rgw::sal::Driver* driver, formatter->open_array_section("users"); for (const auto& user_id : user_ids) { - std::unique_ptr user = driver->get_user(rgw_user(user_id)); + const auto user = rgw_user{user_id}; formatter->open_object_section("user"); formatter->dump_string("user_id", user_id); @@ -1391,8 +1392,8 @@ int RGWBucketAdminOp::limit_check(rgw::sal::Driver* driver, rgw::sal::BucketList listing; do { - ret = user->list_buckets(dpp, listing.next_marker, string(), - max_entries, false, listing, y); + ret = driver->list_buckets(dpp, user, user.tenant, listing.next_marker, + string(), max_entries, false, listing, y); if (ret < 0) return ret; @@ -1466,6 +1467,47 @@ int RGWBucketAdminOp::limit_check(rgw::sal::Driver* driver, return ret; } /* RGWBucketAdminOp::limit_check */ +static int list_owner_bucket_info(const DoutPrefixProvider* dpp, + optional_yield y, + rgw::sal::Driver* driver, + const rgw_owner& owner, + const std::string& tenant, + const std::string& marker, + bool show_stats, + RGWFormatterFlusher& flusher) +{ + Formatter* formatter = flusher.get_formatter(); + formatter->open_array_section("buckets"); + + const std::string empty_end_marker; + const size_t max_entries = dpp->get_cct()->_conf->rgw_list_buckets_max_chunk; + constexpr bool no_need_stats = false; // set need_stats to false + + rgw::sal::BucketList listing; + listing.next_marker = marker; + do { + int ret = driver->list_buckets(dpp, owner, tenant, listing.next_marker, + empty_end_marker, max_entries, no_need_stats, + listing, y); + if (ret < 0) { + return ret; + } + + for (const auto& ent : listing.buckets) { + if (show_stats) { + bucket_stats(driver, tenant, ent.bucket.name, formatter, dpp, y); + } else { + formatter->dump_string("bucket", ent.bucket.name); + } + } // for loop + + flusher.flush(); + } while (!listing.next_marker.empty()); + + formatter->close_section(); + return 0; +} + int RGWBucketAdminOp::info(rgw::sal::Driver* driver, RGWBucketAdminOpState& op_state, RGWFormatterFlusher& flusher, @@ -1494,34 +1536,30 @@ int RGWBucketAdminOp::info(rgw::sal::Driver* driver, return ret; } } else if (op_state.is_user_op()) { - formatter->open_array_section("buckets"); - - std::unique_ptr user = driver->get_user(op_state.get_user_id()); - const std::string empty_end_marker; - const size_t max_entries = dpp->get_cct()->_conf->rgw_list_buckets_max_chunk; - constexpr bool no_need_stats = false; // set need_stats to false - - rgw::sal::BucketList listing; - listing.next_marker = op_state.marker; - do { - ret = user->list_buckets(dpp, listing.next_marker, empty_end_marker, - max_entries, no_need_stats, listing, y); - if (ret < 0) { - return ret; - } - - for (const auto& ent : listing.buckets) { - if (show_stats) { - bucket_stats(driver, user_id.tenant, ent.bucket.name, formatter, dpp, y); - } else { - formatter->dump_string("bucket", ent.bucket.name); - } - } // for loop - - flusher.flush(); - } while (!listing.next_marker.empty()); + const rgw_user& uid = op_state.get_user_id(); + ret = list_owner_bucket_info(dpp, y, driver, uid, uid.tenant, + op_state.marker, show_stats, flusher); + if (ret < 0) { + return ret; + } + } else if (op_state.is_account_op()) { + // look up the account's tenant + const rgw_account_id& account_id = op_state.get_account_id(); + RGWAccountInfo info; + rgw::sal::Attrs attrs; // ignored + RGWObjVersionTracker objv; // ignored + int ret = driver->load_account_by_id(dpp, y, account_id, info, attrs, objv); + if (ret < 0) { + ldpp_dout(dpp, 1) << "failed to load account " << account_id + << ": " << cpp_strerror(ret) << dendl; + return ret; + } - formatter->close_section(); + ret = list_owner_bucket_info(dpp, y, driver, account_id, info.tenant, + op_state.marker, show_stats, flusher); + if (ret < 0) { + return ret; + } } else { void *handle = nullptr; bool truncated = true; diff --git a/src/rgw/driver/rados/rgw_bucket.h b/src/rgw/driver/rados/rgw_bucket.h index d4acaeb4141..e91c0d7e139 100644 --- a/src/rgw/driver/rados/rgw_bucket.h +++ b/src/rgw/driver/rados/rgw_bucket.h @@ -213,10 +213,15 @@ extern int rgw_object_get_attr(rgw::sal::Driver* driver, rgw::sal::Object* obj, const char* attr_name, bufferlist& out_bl, optional_yield y); -extern void check_bad_user_bucket_mapping(rgw::sal::Driver* driver, rgw::sal::User& user, bool fix, optional_yield y, const DoutPrefixProvider *dpp); +void check_bad_owner_bucket_mapping(rgw::sal::Driver* driver, + const rgw_owner& owner, + const std::string& tenant, + bool fix, optional_yield y, + const DoutPrefixProvider *dpp); struct RGWBucketAdminOpState { rgw_user uid; + rgw_account_id account_id; std::string display_name; std::string bucket_name; std::string bucket_id; @@ -278,6 +283,7 @@ struct RGWBucketAdminOpState { void set_sync_bucket(bool value) { sync_bucket = value; } rgw_user& get_user_id() { return uid; } + rgw_account_id& get_account_id() { return account_id; } std::string& get_user_display_name() { return display_name; } std::string& get_bucket_name() { return bucket_name; } std::string& get_object_name() { return object_name; } @@ -299,6 +305,7 @@ struct RGWBucketAdminOpState { bool will_delete_children() { return delete_child_objects; } bool will_check_objects() { return check_objects; } bool is_user_op() { return !uid.empty(); } + bool is_account_op() { return !account_id.empty(); } bool is_system_op() { return uid.empty(); } bool has_bucket_stored() { return bucket_stored; } int get_max_aio() { return max_aio; } diff --git a/src/rgw/driver/rados/rgw_sal_rados.cc b/src/rgw/driver/rados/rgw_sal_rados.cc index a25a4a58d91..c9808d1a9c7 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.cc +++ b/src/rgw/driver/rados/rgw_sal_rados.cc @@ -102,12 +102,49 @@ static int drain_aio(std::list& handles) return ret; } -int RadosUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& marker, - const std::string& end_marker, uint64_t max, bool need_stats, - BucketList &result, optional_yield y) +// return the {user}.buckets or {account}.buckets object +static rgw_raw_obj get_owner_buckets_obj(RGWSI_User* svc_user, + RGWSI_Zone* svc_zone, + const rgw_owner& owner) { - return store->ctl()->user->list_buckets(dpp, get_id(), marker, end_marker, - max, need_stats, result, y); + struct visitor { + RGWSI_User* svc_user; + RGWSI_Zone* svc_zone; + + rgw_raw_obj operator()(const rgw_user& user) { + return svc_user->get_buckets_obj(user); + } + rgw_raw_obj operator()(const rgw_account_id& id) { + const RGWZoneParams& zone = svc_zone->get_zone_params(); + return rgwrados::account::get_buckets_obj(zone, id); + } + }; + return std::visit(visitor{svc_user, svc_zone}, owner); +} + +int RadosStore::list_buckets(const DoutPrefixProvider* dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, + BucketList& listing, optional_yield y) +{ + librados::Rados& rados = *getRados()->get_rados_handle(); + const rgw_raw_obj& obj = get_owner_buckets_obj(svc()->user, svc()->zone, owner); + + int ret = rgwrados::buckets::list(dpp, y, rados, obj, tenant, + marker, end_marker, max, listing); + if (ret < 0) { + return ret; + } + + if (need_stats) { + ret = ctl()->bucket->read_buckets_stats(listing.buckets, y, dpp); + if (ret < 0 && ret != -ENOENT) { + ldpp_dout(dpp, 0) << "ERROR: could not get stats for buckets" << dendl; + return ret; + } + } + return 0; } int RadosBucket::create(const DoutPrefixProvider* dpp, @@ -169,24 +206,6 @@ int RadosUser::merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_a return store_user(dpp, y, false); } -int RadosUser::read_stats(const DoutPrefixProvider *dpp, - optional_yield y, RGWStorageStats* stats, - ceph::real_time* last_stats_sync, - ceph::real_time* last_stats_update) -{ - return store->ctl()->user->read_stats(dpp, get_id(), stats, y, last_stats_sync, last_stats_update); -} - -int RadosUser::read_stats_async(const DoutPrefixProvider *dpp, boost::intrusive_ptr cb) -{ - return store->svc()->user->read_stats_async(dpp, get_id(), cb); -} - -int RadosUser::complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) -{ - return store->svc()->user->complete_flush_stats(dpp, get_id(), y); -} - int RadosUser::read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries, bool* is_truncated, RGWUsageIter& usage_iter, @@ -1097,29 +1116,46 @@ int RadosStore::delete_account(const DoutPrefixProvider* dpp, return write_mdlog_entry(dpp, y, *svc()->mdlog, "account", info.id, objv); } -int RadosStore::load_account_stats(const DoutPrefixProvider* dpp, - optional_yield y, std::string_view id, - RGWStorageStats& stats, - ceph::real_time& last_synced, - ceph::real_time& last_updated) +int RadosStore::load_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner, + RGWStorageStats& stats, + ceph::real_time& last_synced, + ceph::real_time& last_updated) { - const RGWZoneParams& zone = svc()->zone->get_zone_params(); - const rgw_raw_obj& obj = rgwrados::account::get_buckets_obj(zone, id); librados::Rados& rados = *getRados()->get_rados_handle(); + const rgw_raw_obj& obj = get_owner_buckets_obj(svc()->user, svc()->zone, owner); return rgwrados::buckets::read_stats(dpp, y, rados, obj, stats, &last_synced, &last_updated); } -int RadosStore::load_account_stats_async(const DoutPrefixProvider* dpp, - std::string_view id, - boost::intrusive_ptr cb) +int RadosStore::load_stats_async(const DoutPrefixProvider* dpp, + const rgw_owner& owner, + boost::intrusive_ptr cb) { - const RGWZoneParams& zone = svc()->zone->get_zone_params(); - const rgw_raw_obj& obj = rgwrados::account::get_buckets_obj(zone, id); librados::Rados& rados = *getRados()->get_rados_handle(); + const rgw_raw_obj& obj = get_owner_buckets_obj(svc()->user, svc()->zone, owner); return rgwrados::buckets::read_stats_async(dpp, rados, obj, std::move(cb)); } +int RadosStore::reset_stats(const DoutPrefixProvider *dpp, + optional_yield y, + const rgw_owner& owner) +{ + librados::Rados& rados = *getRados()->get_rados_handle(); + const rgw_raw_obj& obj = get_owner_buckets_obj(svc()->user, svc()->zone, owner); + return rgwrados::buckets::reset_stats(dpp, y, rados, obj); +} + +int RadosStore::complete_flush_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner) +{ + librados::Rados& rados = *getRados()->get_rados_handle(); + const rgw_raw_obj& obj = get_owner_buckets_obj(svc()->user, svc()->zone, owner); + return rgwrados::buckets::complete_flush_stats(dpp, y, rados, obj); +} + std::unique_ptr RadosStore::get_object(const rgw_obj_key& k) { return std::make_unique(this, k); diff --git a/src/rgw/driver/rados/rgw_sal_rados.h b/src/rgw/driver/rados/rgw_sal_rados.h index 5aebda3d32e..7839a54c262 100644 --- a/src/rgw/driver/rados/rgw_sal_rados.h +++ b/src/rgw/driver/rados/rgw_sal_rados.h @@ -174,19 +174,32 @@ class RadosStore : public StoreDriver { optional_yield y, const RGWAccountInfo& info, RGWObjVersionTracker& objv) override; - int load_account_stats(const DoutPrefixProvider* dpp, - optional_yield y, std::string_view id, - RGWStorageStats& stats, - ceph::real_time& last_synced, - ceph::real_time& last_updated) override; - int load_account_stats_async(const DoutPrefixProvider* dpp, - std::string_view id, - boost::intrusive_ptr cb) override; + + int load_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner, + RGWStorageStats& stats, + ceph::real_time& last_synced, + ceph::real_time& last_updated) override; + int load_stats_async(const DoutPrefixProvider* dpp, + const rgw_owner& owner, + boost::intrusive_ptr cb) override; + int reset_stats(const DoutPrefixProvider *dpp, + optional_yield y, + const rgw_owner& owner) override; + int complete_flush_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner) override; virtual std::unique_ptr get_object(const rgw_obj_key& k) override; std::unique_ptr get_bucket(const RGWBucketInfo& i) override; int load_bucket(const DoutPrefixProvider* dpp, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) override; + int list_buckets(const DoutPrefixProvider* dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, BucketList& buckets, + optional_yield y) override; virtual bool is_meta_master() override; virtual Zone* get_zone() { return zone.get(); } virtual std::string zone_unique_id(uint64_t unique_num) override; @@ -349,17 +362,8 @@ class RadosUser : public StoreUser { virtual std::unique_ptr clone() override { return std::unique_ptr(new RadosUser(*this)); } - int list_buckets(const DoutPrefixProvider* dpp, const std::string& marker, const std::string& end_marker, - uint64_t max, bool need_stats, BucketList& buckets, - optional_yield y) override; virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) override; virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y) override; - virtual int read_stats(const DoutPrefixProvider *dpp, - optional_yield y, RGWStorageStats* stats, - ceph::real_time* last_stats_sync = nullptr, - ceph::real_time* last_stats_update = nullptr) override; - virtual int read_stats_async(const DoutPrefixProvider *dpp, boost::intrusive_ptr cb) override; - virtual int complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) 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, std::map& usage) override; diff --git a/src/rgw/driver/rados/rgw_user.cc b/src/rgw/driver/rados/rgw_user.cc index c894349664c..33c9424a5eb 100644 --- a/src/rgw/driver/rados/rgw_user.cc +++ b/src/rgw/driver/rados/rgw_user.cc @@ -1568,8 +1568,9 @@ int RGWUser::execute_rename(const DoutPrefixProvider *dpp, RGWUserAdminOpState& rgw::sal::BucketList listing; do { - ret = old_user->list_buckets(dpp, listing.next_marker, "", - max_entries, false, listing, y); + ret = driver->list_buckets(dpp, old_user->get_id(), old_user->get_tenant(), + listing.next_marker, "", max_entries, false, + listing, y); if (ret < 0) { set_err_msg(err_msg, "unable to list user buckets"); return ret; @@ -1809,8 +1810,9 @@ int RGWUser::execute_remove(const DoutPrefixProvider *dpp, RGWUserAdminOpState& rgw::sal::BucketList listing; do { - ret = user->list_buckets(dpp, listing.next_marker, string(), - max_buckets, false, listing, y); + ret = driver->list_buckets(dpp, user->get_id(), user->get_tenant(), + listing.next_marker, string(), + max_buckets, false, listing, y); if (ret < 0) { set_err_msg(err_msg, "unable to list user buckets"); return ret; @@ -1965,8 +1967,9 @@ int RGWUser::execute_modify(const DoutPrefixProvider *dpp, RGWUserAdminOpState& rgw::sal::BucketList listing; do { - ret = user->list_buckets(dpp, listing.next_marker, string(), - max_buckets, false, listing, y); + ret = driver->list_buckets(dpp, user->get_id(), user->get_tenant(), + listing.next_marker, string(), + max_buckets, false, listing, y); if (ret < 0) { set_err_msg(err_msg, "could not get buckets for uid: " + user_id.to_str()); return ret; @@ -2178,7 +2181,7 @@ int RGWUserAdminOp_User::info(const DoutPrefixProvider *dpp, ruser = driver->get_user(info.user_id); if (op_state.sync_stats) { - ret = rgw_user_sync_all_stats(dpp, driver, ruser.get(), y); + ret = rgw_sync_all_stats(dpp, y, driver, ruser->get_id(), ruser->get_tenant()); if (ret < 0) { return ret; } @@ -2187,7 +2190,10 @@ int RGWUserAdminOp_User::info(const DoutPrefixProvider *dpp, RGWStorageStats stats; RGWStorageStats *arg_stats = NULL; if (op_state.fetch_stats) { - int ret = ruser->read_stats(dpp, y, &stats); + ceph::real_time last_synced; // ignored + ceph::real_time last_updated; // ignored + int ret = driver->load_stats(dpp, y, ruser->get_id(), stats, + last_synced, last_updated); if (ret < 0 && ret != -ENOENT) { return ret; } @@ -2783,47 +2789,6 @@ int RGWUserCtl::remove_info(const DoutPrefixProvider *dpp, }); } -int RGWUserCtl::list_buckets(const DoutPrefixProvider *dpp, - const rgw_user& user, - const string& marker, - const string& end_marker, - uint64_t max, - bool need_stats, - rgw::sal::BucketList& listing, - optional_yield y, - uint64_t default_max) -{ - if (!max) { - max = default_max; - } - - int ret = svc.user->list_buckets(dpp, user, marker, end_marker, - max, listing, y); - if (ret < 0) { - return ret; - } - if (need_stats) { - ret = ctl.bucket->read_buckets_stats(listing.buckets, y, dpp); - if (ret < 0 && ret != -ENOENT) { - ldpp_dout(dpp, 0) << "ERROR: could not get stats for buckets" << dendl; - return ret; - } - } - return 0; -} - -int RGWUserCtl::read_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, RGWStorageStats *stats, - optional_yield y, - ceph::real_time *last_stats_sync, - ceph::real_time *last_stats_update) -{ - return be_handler->call([&](RGWSI_MetaBackend_Handler::Op *op) { - return svc.user->read_stats(dpp, op->ctx(), user, stats, - last_stats_sync, last_stats_update, y); - }); -} - RGWMetadataHandler *RGWUserMetaHandlerAllocator::alloc(RGWSI_User *user_svc) { return new RGWUserMetadataHandler(user_svc); } diff --git a/src/rgw/driver/rados/rgw_user.h b/src/rgw/driver/rados/rgw_user.h index 7947b3094bd..906917e01e6 100644 --- a/src/rgw/driver/rados/rgw_user.h +++ b/src/rgw/driver/rados/rgw_user.h @@ -65,7 +65,9 @@ struct bucket_meta_entry { uint64_t count; }; -extern int rgw_user_sync_all_stats(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver, rgw::sal::User* user, optional_yield y); +int rgw_sync_all_stats(const DoutPrefixProvider *dpp, + optional_yield y, rgw::sal::Driver* driver, + const rgw_owner& owner, const std::string& tenant); extern int rgw_user_get_all_buckets_stats(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver, rgw::sal::User* user, std::map& buckets_usage_map, optional_yield y); @@ -873,22 +875,6 @@ public: int remove_info(const DoutPrefixProvider *dpp, const RGWUserInfo& info, optional_yield y, const RemoveParams& params = {}); - - int list_buckets(const DoutPrefixProvider *dpp, - const rgw_user& user, - const std::string& marker, - const std::string& end_marker, - uint64_t max, - bool need_stats, - rgw::sal::BucketList& listing, - optional_yield y, - uint64_t default_max = 1000); - - int read_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, RGWStorageStats *stats, - optional_yield y, - ceph::real_time *last_stats_sync = nullptr, /* last time a full stats sync completed */ - ceph::real_time *last_stats_update = nullptr); /* last time a stats update was done */ }; class RGWUserMetaHandlerAllocator { diff --git a/src/rgw/rgw_account.cc b/src/rgw/rgw_account.cc index 5d5371b963d..ee7b4aafa6d 100644 --- a/src/rgw/rgw_account.cc +++ b/src/rgw/rgw_account.cc @@ -312,37 +312,56 @@ int info(const DoutPrefixProvider* dpp, int stats(const DoutPrefixProvider* dpp, rgw::sal::Driver* driver, AdminOpState& op_state, + bool sync_stats, + bool reset_stats, std::string& err_msg, RGWFormatterFlusher& flusher, optional_yield y) { int ret = 0; - std::string account_id; + RGWAccountInfo info; + rgw::sal::Attrs attrs; // ignored + RGWObjVersionTracker objv; // ignored if (!op_state.account_id.empty()) { - account_id = op_state.account_id; + // look up account by id + ret = driver->load_account_by_id(dpp, y, op_state.account_id, + info, attrs, objv); } else if (!op_state.account_name.empty()) { - // look up account id by name - RGWAccountInfo info; - rgw::sal::Attrs attrs; - RGWObjVersionTracker objv; + // look up account by tenant/name ret = driver->load_account_by_name(dpp, y, op_state.tenant, op_state.account_name, info, attrs, objv); - if (ret < 0) { - return ret; - } - account_id = std::move(info.id); } else { err_msg = "requires account id or name"; return -EINVAL; } + if (ret < 0) { + err_msg = "failed to load account"; + return ret; + } + + const rgw_owner owner = rgw_account_id{info.id}; + + if (sync_stats) { + ret = rgw_sync_all_stats(dpp, y, driver, owner, info.tenant); + if (ret < 0) { + err_msg = "failed to sync account stats"; + return ret; + } + } else if (reset_stats) { + ret = driver->reset_stats(dpp, y, owner); + if (ret < 0) { + err_msg = "failed to reset account stats"; + return ret; + } + } RGWStorageStats stats; ceph::real_time last_synced; ceph::real_time last_updated; - ret = driver->load_account_stats(dpp, y, account_id, stats, - last_synced, last_updated); + ret = driver->load_stats(dpp, y, owner, stats, + last_synced, last_updated); if (ret < 0) { return ret; } diff --git a/src/rgw/rgw_account.h b/src/rgw/rgw_account.h index 77969363261..04af0b31817 100644 --- a/src/rgw/rgw_account.h +++ b/src/rgw/rgw_account.h @@ -73,7 +73,8 @@ int info(const DoutPrefixProvider* dpp, rgw::sal::Driver* driver, /// dump account storage stats int stats(const DoutPrefixProvider* dpp, rgw::sal::Driver* driver, - AdminOpState& op_state, std::string& err_msg, + AdminOpState& op_state, bool sync_stats, + bool reset_stats, std::string& err_msg, RGWFormatterFlusher& flusher, optional_yield y); } // namespace rgw::account diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index bd4d3e77291..eca5e653e1e 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -6545,6 +6545,7 @@ int main(int argc, const char **argv) } user_op.account_id = account_id; + bucket_op.account_id = account_id; // RGWUser to use for user operations RGWUser ruser; @@ -8845,7 +8846,8 @@ next: } if (opt_cmd == OPT::USER_CHECK) { - check_bad_user_bucket_mapping(driver, *user.get(), fix, null_yield, dpp()); + check_bad_owner_bucket_mapping(driver, user->get_id(), user->get_tenant(), + fix, null_yield, dpp()); } if (opt_cmd == OPT::USER_STATS) { @@ -8864,7 +8866,7 @@ next: "so at most one of the two should be specified" << std::endl; return EINVAL; } - ret = static_cast(driver)->svc()->user->reset_bucket_stats(dpp(), user->get_id(), null_yield); + ret = driver->reset_stats(dpp(), null_yield, user->get_id()); if (ret < 0) { cerr << "ERROR: could not reset user stats: " << cpp_strerror(-ret) << std::endl; @@ -8886,7 +8888,8 @@ next: return -ret; } } else { - int ret = rgw_user_sync_all_stats(dpp(), driver, user.get(), null_yield); + int ret = rgw_sync_all_stats(dpp(), null_yield, driver, + user->get_id(), user->get_tenant()); if (ret < 0) { cerr << "ERROR: could not sync user stats: " << cpp_strerror(-ret) << std::endl; @@ -8899,7 +8902,8 @@ next: RGWStorageStats stats(omit_utilized_stats); ceph::real_time last_stats_sync; ceph::real_time last_stats_update; - int ret = user->read_stats(dpp(), null_yield, &stats, &last_stats_sync, &last_stats_update); + int ret = driver->load_stats(dpp(), null_yield, user->get_id(), + stats, last_stats_sync, last_stats_update); if (ret < 0) { if (ret == -ENOENT) { /* in case of ENOENT */ cerr << "User has not been initialized or user does not exist" << std::endl; @@ -11126,7 +11130,8 @@ next: } if (opt_cmd == OPT::ACCOUNT_STATS) { - ret = rgw::account::stats(dpp(), driver, op_state, err_msg, + ret = rgw::account::stats(dpp(), driver, op_state, + sync_stats, reset_stats, err_msg, stream_flusher, null_yield); if (ret < 0) { cerr << "ERROR: failed to read account stats with " << cpp_strerror(-ret) diff --git a/src/rgw/rgw_auth.cc b/src/rgw/rgw_auth.cc index d8a16fba3f2..6f0cb5d80a2 100644 --- a/src/rgw/rgw_auth.cc +++ b/src/rgw/rgw_auth.cc @@ -457,7 +457,10 @@ void rgw::auth::WebIdentityApplier::load_acct_info(const DoutPrefixProvider* dpp //Check if user_id.buckets already exists, may have been from the time, when shadow users didnt exist RGWStorageStats stats; - int ret = user->read_stats(dpp, null_yield, &stats); + ceph::real_time last_synced; + ceph::real_time last_updated; + int ret = driver->load_stats(dpp, null_yield, federated_user, stats, + last_synced, last_updated); if (ret < 0 && ret != -ENOENT) { ldpp_dout(dpp, 0) << "ERROR: reading stats for the user returned error " << ret << dendl; return; diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 04f432c4303..6dbac832d91 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2604,13 +2604,20 @@ void RGWListBuckets::execute(optional_yield y) read_count = max_buckets; } - op_ret = s->user->list_buckets(this, marker, end_marker, read_count, should_get_stats(), listing, y); + if (s->auth.identity->is_anonymous()) { + ldpp_dout(this, 20) << "skipping list_buckets() for anonymous user" << dendl; + marker.clear(); + break; + } + + op_ret = driver->list_buckets(this, s->owner.id, s->auth.identity->get_tenant(), + marker, end_marker, read_count, should_get_stats(), listing, y); if (op_ret < 0) { /* hmm.. something wrong here.. the user was authenticated, so it should exist */ - ldpp_dout(this, 10) << "WARNING: failed on rgw_get_user_buckets uid=" - << s->user->get_id() << dendl; + ldpp_dout(this, 10) << "WARNING: failed on list_buckets owner=" + << s->owner.id << dendl; break; } @@ -2688,7 +2695,8 @@ void RGWGetUsage::execute(optional_yield y) } } - op_ret = rgw_user_sync_all_stats(this, driver, s->user.get(), y); + op_ret = rgw_sync_all_stats(this, y, driver, s->user->get_id(), + s->user->get_tenant()); if (op_ret < 0) { ldpp_dout(this, 0) << "ERROR: failed to sync user stats" << dendl; return; @@ -2700,7 +2708,10 @@ void RGWGetUsage::execute(optional_yield y) return; } - op_ret = s->user->read_stats(this, y, &stats); + ceph::real_time synced; // ignored + ceph::real_time updated; // ignored + op_ret = driver->load_stats(this, y, s->user->get_id(), + stats, synced, updated); if (op_ret < 0) { ldpp_dout(this, 0) << "ERROR: can't read user header" << dendl; return; @@ -2733,13 +2744,14 @@ void RGWStatAccount::execute(optional_yield y) rgw::sal::BucketList listing; do { - op_ret = s->user->list_buckets(this, listing.next_marker, string(), - max_buckets, true, listing, y); + op_ret = driver->list_buckets(this, s->owner.id, s->auth.identity->get_tenant(), + listing.next_marker, string(), + max_buckets, true, listing, y); if (op_ret < 0) { /* hmm.. something wrong here.. the user was authenticated, so it should exist */ - ldpp_dout(this, 10) << "WARNING: failed on list_buckets uid=" - << s->user->get_id() << " ret=" << op_ret << dendl; + ldpp_dout(this, 10) << "WARNING: failed on list_buckets owner=" + << s->owner.id << " ret=" << op_ret << dendl; return; } @@ -3152,23 +3164,59 @@ int RGWGetBucketLocation::verify_permission(optional_yield y) return verify_bucket_owner_or_policy(s, rgw::IAM::s3GetBucketLocation); } +static int get_account_max_buckets(const DoutPrefixProvider* dpp, + optional_yield y, + rgw::sal::Driver* driver, + const rgw_account_id& id, + int32_t& max_buckets) +{ + RGWAccountInfo info; + rgw::sal::Attrs attrs; + RGWObjVersionTracker objv; + + int ret = driver->load_account_by_id(dpp, y, id, info, attrs, objv); + if (ret < 0) { + ldpp_dout(dpp, 4) << "failed to load account owner: " << cpp_strerror(ret) << dendl; + return ret; + } + + max_buckets = info.max_buckets; + return 0; +} + // list the user's buckets to check whether they're at their maximum -static int check_user_max_buckets(const DoutPrefixProvider* dpp, - rgw::sal::User& user, optional_yield y) +static int check_owner_max_buckets(const DoutPrefixProvider* dpp, + rgw::sal::Driver* driver, req_state* s, + optional_yield y) { - int32_t remaining = user.get_max_buckets(); + int32_t remaining = 0; + + const rgw_account_id* account = std::get_if(&s->owner.id); + if (account) { + int ret = get_account_max_buckets(dpp, y, driver, *account, remaining); + if (ret < 0) { + return ret; + } + } else { + remaining = s->user->get_max_buckets(); + } + + if (remaining < 0) { + return -EPERM; + } if (!remaining) { // unlimited return 0; } - uint64_t max_buckets = dpp->get_cct()->_conf->rgw_list_buckets_max_chunk; + const uint64_t chunk_size = dpp->get_cct()->_conf->rgw_list_buckets_max_chunk; + const std::string& tenant = s->auth.identity->get_tenant(); rgw::sal::BucketList listing; do { - size_t to_read = std::max(max_buckets, remaining); + size_t to_read = std::max(chunk_size, remaining); - int ret = user.list_buckets(dpp, listing.next_marker, string(), - to_read, false, listing, y); + int ret = driver->list_buckets(dpp, s->owner.id, tenant, listing.next_marker, + "", to_read, false, listing, y); if (ret < 0) { return ret; } @@ -3210,11 +3258,7 @@ int RGWCreateBucket::verify_permission(optional_yield y) } } - if (s->user->get_max_buckets() < 0) { - return -EPERM; - } - - return check_user_max_buckets(this, *s->user, y); + return check_owner_max_buckets(this, driver, s, y); } void RGWCreateBucket::pre_exec() @@ -7671,7 +7715,7 @@ RGWBulkUploadOp::handle_upload_path(req_state *s) int RGWBulkUploadOp::handle_dir_verify_permission(optional_yield y) { - return check_user_max_buckets(this, *s->user, y); + return check_owner_max_buckets(this, driver, s, y); } static void forward_req_info(const DoutPrefixProvider *dpp, CephContext *cct, req_info& info, const std::string& bucket_name) diff --git a/src/rgw/rgw_quota.cc b/src/rgw/rgw_quota.cc index ca9eb6a2294..eadd712d664 100644 --- a/src/rgw/rgw_quota.cc +++ b/src/rgw/rgw_quota.cc @@ -398,23 +398,27 @@ class RGWOwnerStatsCache : public RGWQuotaCache { * users that didn't have quota turned on before (or existed before the user objclass * tracked stats) need to get their backend stats up to date. */ - class UserSyncThread : public Thread { + class OwnerSyncThread : public Thread { CephContext *cct; RGWOwnerStatsCache *stats; + const std::string metadata_section; - ceph::mutex lock = ceph::make_mutex("RGWOwnerStatsCache::UserSyncThread"); + ceph::mutex lock = ceph::make_mutex("RGWOwnerStatsCache::OwnerSyncThread"); ceph::condition_variable cond; public: - UserSyncThread(CephContext *_cct, RGWOwnerStatsCache *_s) : cct(_cct), stats(_s) {} + OwnerSyncThread(CephContext *_cct, RGWOwnerStatsCache *_s, + const std::string& metadata_section) + : cct(_cct), stats(_s), metadata_section(metadata_section) + {} void *entry() override { - ldout(cct, 20) << "UserSyncThread: start" << dendl; + ldout(cct, 20) << "OwnerSyncThread: start" << dendl; do { const DoutPrefix dp(cct, dout_subsys, "rgw user sync thread: "); - int ret = stats->sync_all_users(&dp, null_yield); + int ret = stats->sync_all_owners(&dp, metadata_section); if (ret < 0) { - ldout(cct, 5) << "ERROR: sync_all_users() returned ret=" << ret << dendl; + ldout(cct, 5) << "ERROR: sync_all_owners() returned ret=" << ret << dendl; } if (stats->going_down()) @@ -423,7 +427,7 @@ class RGWOwnerStatsCache : public RGWQuotaCache { std::unique_lock l{lock}; cond.wait_for(l, std::chrono::seconds(cct->_conf->rgw_user_quota_sync_interval)); } while (!stats->going_down()); - ldout(cct, 20) << "UserSyncThread: done" << dendl; + ldout(cct, 20) << "OwnerSyncThread: done" << dendl; return NULL; } @@ -436,8 +440,9 @@ class RGWOwnerStatsCache : public RGWQuotaCache { // TODO: AccountSyncThread and sync_all_accounts() - BucketsSyncThread *buckets_sync_thread; - UserSyncThread *user_sync_thread; + BucketsSyncThread* buckets_sync_thread = nullptr; + OwnerSyncThread* user_sync_thread = nullptr; + OwnerSyncThread* account_sync_thread = nullptr; protected: bool map_find(const rgw_owner& owner,const rgw_bucket& bucket, RGWQuotaCacheStats& qs) override { return stats_map.find(owner, qs); @@ -453,9 +458,9 @@ protected: int fetch_stats_from_storage(const rgw_owner& owner, const rgw_bucket& bucket, RGWStorageStats& stats, optional_yield y, const DoutPrefixProvider *dpp) override; int sync_bucket(const rgw_owner& owner, const rgw_bucket& bucket, optional_yield y, const DoutPrefixProvider *dpp); - int sync_user(const DoutPrefixProvider *dpp, const rgw_user& user, optional_yield y); - int sync_all_users(const DoutPrefixProvider *dpp, optional_yield y); - // TODO: sync_account/sync_all_accounts + int sync_owner(const DoutPrefixProvider *dpp, const rgw_owner& owner, optional_yield y); + int sync_all_owners(const DoutPrefixProvider *dpp, + const std::string& metadata_section); void data_modified(const rgw_owner& owner, const rgw_bucket& bucket) override; @@ -483,11 +488,10 @@ public: if (quota_threads) { buckets_sync_thread = new BucketsSyncThread(driver->ctx(), this); buckets_sync_thread->create("rgw_buck_st_syn"); - user_sync_thread = new UserSyncThread(driver->ctx(), this); + user_sync_thread = new OwnerSyncThread(driver->ctx(), this, "user"); user_sync_thread->create("rgw_user_st_syn"); - } else { - buckets_sync_thread = NULL; - user_sync_thread = NULL; + account_sync_thread = new OwnerSyncThread(driver->ctx(), this, "account"); + account_sync_thread->create("rgw_acct_st_syn"); } } ~RGWOwnerStatsCache() override { @@ -508,6 +512,7 @@ public: stop_thread(&buckets_sync_thread); } stop_thread(&user_sync_thread); + stop_thread(&account_sync_thread); } }; @@ -534,14 +539,7 @@ int RGWOwnerStatsCache::init_refresh(const rgw_owner& owner, const rgw_bucket& b ldpp_dout(dpp, 20) << "initiating async quota refresh for owner=" << owner << dendl; - int r = std::visit(fu2::overload( - [&] (const rgw_user& user) { - std::unique_ptr ruser = driver->get_user(user); - return ruser->read_stats_async(dpp, std::move(cb)); - }, - [&] (const rgw_account_id& accountid) { - return driver->load_account_stats_async(dpp, accountid, std::move(cb)); - }), owner); + int r = driver->load_stats_async(dpp, owner, std::move(cb)); if (r < 0) { ldpp_dout(dpp, 0) << "could not read stats for owner=" << owner << dendl; return r; @@ -566,16 +564,9 @@ int RGWOwnerStatsCache::fetch_stats_from_storage(const rgw_owner& owner, optional_yield y, const DoutPrefixProvider *dpp) { - int r = std::visit(fu2::overload( - [&] (const rgw_user& user) { - std::unique_ptr u = driver->get_user(user); - return u->read_stats(dpp, y, &stats); - }, - [&] (const rgw_account_id& acct) { - ceph::real_time synced; // ignored - ceph::real_time updated; // ignored - return driver->load_account_stats(dpp, y, acct, stats, synced, updated); - }), owner); + ceph::real_time synced; // ignored + ceph::real_time updated; // ignored + int r = driver->load_stats(dpp, y, owner, stats, synced, updated); if (r < 0) { ldpp_dout(dpp, 0) << "could not read stats for owner " << owner << dendl; return r; @@ -605,22 +596,46 @@ int RGWOwnerStatsCache::sync_bucket(const rgw_owner& owner, const rgw_bucket& b, return bucket->check_bucket_shards(dpp, ent.count, y); } -int RGWOwnerStatsCache::sync_user(const DoutPrefixProvider *dpp, const rgw_user& _u, optional_yield y) +// for account owners, we need to look up the tenant name by account id +static int get_owner_tenant(const DoutPrefixProvider* dpp, + optional_yield y, + rgw::sal::Driver* driver, + const rgw_owner& owner, + std::string& tenant) +{ + return std::visit(fu2::overload( + [&] (const rgw_user& user) { + tenant = user.tenant; + return 0; + }, + [&] (const rgw_account_id& account) { + RGWAccountInfo info; + rgw::sal::Attrs attrs; + RGWObjVersionTracker objv; + int ret = driver->load_account_by_id(dpp, y, account, info, attrs, objv); + if (ret >= 0) { + tenant = std::move(info.tenant); + } + return ret; + }), owner); +} + +int RGWOwnerStatsCache::sync_owner(const DoutPrefixProvider *dpp, + const rgw_owner& owner, optional_yield y) { RGWStorageStats stats; ceph::real_time last_stats_sync; ceph::real_time last_stats_update; - std::unique_ptr user = driver->get_user(_u); - int ret = user->read_stats(dpp, y, &stats, &last_stats_sync, &last_stats_update); + int ret = driver->load_stats(dpp, y, owner, stats, last_stats_sync, last_stats_update); if (ret < 0) { - ldpp_dout(dpp, 5) << "ERROR: can't read user header: ret=" << ret << dendl; + ldpp_dout(dpp, 5) << "ERROR: can't read owner stats: ret=" << ret << dendl; return ret; } if (!driver->ctx()->_conf->rgw_user_quota_sync_idle_users && last_stats_update < last_stats_sync) { - ldpp_dout(dpp, 20) << "user is idle, not doing a full sync (user=" << user << ")" << dendl; + ldpp_dout(dpp, 20) << "owner is idle, not doing a full sync (owner=" << owner << ")" << dendl; return 0; } @@ -628,9 +643,17 @@ int RGWOwnerStatsCache::sync_user(const DoutPrefixProvider *dpp, const rgw_user& when_need_full_sync += make_timespan(driver->ctx()->_conf->rgw_user_quota_sync_wait_time); // check if enough time passed since last full sync - /* FIXME: missing check? */ + if (when_need_full_sync > ceph::real_clock::now()) { + return 0; + } + + std::string tenant; + ret = get_owner_tenant(dpp, y, driver, owner, tenant); + if (ret < 0) { + return ret; + } - ret = rgw_user_sync_all_stats(dpp, driver, user.get(), y); + ret = rgw_sync_all_stats(dpp, y, driver, owner, tenant); if (ret < 0) { ldpp_dout(dpp, 0) << "ERROR: failed user stats sync, ret=" << ret << dendl; return ret; @@ -639,12 +662,11 @@ int RGWOwnerStatsCache::sync_user(const DoutPrefixProvider *dpp, const rgw_user& return 0; } -int RGWOwnerStatsCache::sync_all_users(const DoutPrefixProvider *dpp, optional_yield y) +int RGWOwnerStatsCache::sync_all_owners(const DoutPrefixProvider *dpp, + const std::string& metadata_section) { - string key = "user"; void *handle; - - int ret = driver->meta_list_keys_init(dpp, key, string(), &handle); + int ret = driver->meta_list_keys_init(dpp, metadata_section, string(), &handle); if (ret < 0) { ldpp_dout(dpp, 10) << "ERROR: can't get key: ret=" << ret << dendl; return ret; @@ -658,25 +680,23 @@ int RGWOwnerStatsCache::sync_all_users(const DoutPrefixProvider *dpp, optional_y ret = driver->meta_list_keys_next(dpp, handle, max, keys, &truncated); if (ret < 0) { ldpp_dout(dpp, 0) << "ERROR: lists_keys_next(): ret=" << ret << dendl; - goto done; + break; } for (list::iterator iter = keys.begin(); iter != keys.end() && !going_down(); ++iter) { - rgw_user user(*iter); - ldpp_dout(dpp, 20) << "RGWOwnerStatsCache: sync user=" << user << dendl; - int ret = sync_user(dpp, user, y); - if (ret < 0) { - ldpp_dout(dpp, 5) << "ERROR: sync_user() failed, user=" << user << " ret=" << ret << dendl; - - /* continuing to next user */ + const rgw_owner owner = parse_owner(*iter); + ldpp_dout(dpp, 20) << "RGWOwnerStatsCache: sync owner=" << owner << dendl; + int r = sync_owner(dpp, owner, null_yield); + if (r < 0) { + ldpp_dout(dpp, 5) << "ERROR: sync_owner() failed, owner=" << owner + << " ret=" << r << dendl; + /* continuing to next owner */ continue; } } } while (truncated); - ret = 0; -done: driver->meta_list_keys_complete(handle); return ret; } diff --git a/src/rgw/rgw_sal.h b/src/rgw/rgw_sal.h index 5a496105132..f43f261d2e9 100644 --- a/src/rgw/rgw_sal.h +++ b/src/rgw/rgw_sal.h @@ -231,6 +231,18 @@ class ObjectProcessor : public DataProcessor { uint32_t flags) = 0; }; +/** + * @brief A list of buckets + * + * This is the result from a bucket listing operation. + */ +struct BucketList { + /// The list of results, sorted by bucket name + std::vector buckets; + /// The next marker to resume listing, or empty + std::string next_marker; +}; + /** A list of key-value attributes */ using Attrs = std::map; @@ -304,17 +316,25 @@ class Driver { const RGWAccountInfo& info, RGWObjVersionTracker& objv) = 0; - /** Load account storage stats */ - virtual int load_account_stats(const DoutPrefixProvider* dpp, - optional_yield y, std::string_view id, - RGWStorageStats& stats, - ceph::real_time& last_synced, - ceph::real_time& last_updated) = 0; - /** Load account storage stats asynchronously */ - virtual int load_account_stats_async(const DoutPrefixProvider* dpp, - std::string_view id, - boost::intrusive_ptr cb) = 0; - + /** Load cumulative bucket storage stats for the given owner */ + virtual int load_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner, + RGWStorageStats& stats, + ceph::real_time& last_synced, + ceph::real_time& last_updated) = 0; + /** Load owner storage stats asynchronously */ + virtual int load_stats_async(const DoutPrefixProvider* dpp, + const rgw_owner& owner, + boost::intrusive_ptr cb) = 0; + /** Recalculate the sum of bucket stats */ + virtual int reset_stats(const DoutPrefixProvider *dpp, + optional_yield y, + const rgw_owner& owner) = 0; + /** Finish syncing owner stats by updating last_synced timestamp */ + virtual int complete_flush_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner) = 0; /** Get a basic Object. This Object is not looked up, and is incomplete, since is * does not have a bucket. This should only be used when an Object is needed before @@ -326,6 +346,12 @@ class Driver { * bucket must still be allocated to support bucket->create(). */ virtual int load_bucket(const DoutPrefixProvider* dpp, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) = 0; + /** List the buckets of a given owner */ + virtual int list_buckets(const DoutPrefixProvider* dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, BucketList& buckets, + optional_yield y) = 0; /** For multisite, this driver is the zone's master */ virtual bool is_meta_master() = 0; /** Get zone info for this driver */ @@ -535,18 +561,6 @@ class ReadStatsCB : public boost::intrusive_ref_counter { virtual void handle_response(int r, const RGWStorageStats& stats) = 0; }; -/** - * @brief A list of buckets - * - * This is the result from a bucket listing operation. - */ -struct BucketList { - /// The list of results, sorted by bucket name - std::vector buckets; - /// The next marker to resume listing, or empty - std::string next_marker; -}; - /** * @brief User abstraction * @@ -563,11 +577,6 @@ class User { /** Clone a copy of this user. Used when modification is necessary of the copy */ virtual std::unique_ptr clone() = 0; - /** List the buckets owned by a user */ - virtual int list_buckets(const DoutPrefixProvider* dpp, - const std::string& marker, const std::string& end_marker, - uint64_t max, bool need_stats, BucketList& buckets, - optional_yield y) = 0; /** Get the display name for this User */ virtual std::string& get_display_name() = 0; @@ -610,16 +619,6 @@ class User { /** 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) = 0; - /** Read the User stats from the backing Store, synchronous */ - virtual int read_stats(const DoutPrefixProvider *dpp, - optional_yield y, RGWStorageStats* stats, - ceph::real_time* last_stats_sync = nullptr, - ceph::real_time* last_stats_update = nullptr) = 0; - /** Read the User stats from the backing Store, asynchronous */ - virtual int read_stats_async(const DoutPrefixProvider *dpp, - boost::intrusive_ptr cb) = 0; - /** Flush accumulated stat changes for this User to the backing store */ - virtual int complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) = 0; /** Read detailed usage stats for this User from the backing store */ virtual int read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries, diff --git a/src/rgw/rgw_sal_dbstore.cc b/src/rgw/rgw_sal_dbstore.cc index fd7a268fb7a..5bcb906e32a 100644 --- a/src/rgw/rgw_sal_dbstore.cc +++ b/src/rgw/rgw_sal_dbstore.cc @@ -32,16 +32,17 @@ using namespace std; namespace rgw::sal { - int DBUser::list_buckets(const DoutPrefixProvider *dpp, const string& marker, - const string& end_marker, uint64_t max, bool need_stats, - BucketList &result, optional_yield y) + int DBStore::list_buckets(const DoutPrefixProvider *dpp, + const rgw_owner& owner, const std::string& tenant, + const string& marker, const string& end_marker, uint64_t max, + bool need_stats, BucketList &result, optional_yield y) { RGWUserBuckets ulist; bool is_truncated = false; - std::string owner = info.user_id.to_str(); - int ret = store->getDB()->list_buckets(dpp, "", owner, marker, - end_marker, max, need_stats, &ulist, &is_truncated); + std::string ownerstr = to_string(owner); + int ret = getDB()->list_buckets(dpp, "", ownerstr, + marker, end_marker, max, need_stats, &ulist, &is_truncated); if (ret < 0) return ret; @@ -82,25 +83,6 @@ namespace rgw::sal { return ret; } - int DBUser::read_stats(const DoutPrefixProvider *dpp, - optional_yield y, RGWStorageStats* stats, - ceph::real_time *last_stats_sync, - ceph::real_time *last_stats_update) - { - return 0; - } - - /* stats - Not for first pass */ - int DBUser::read_stats_async(const DoutPrefixProvider *dpp, boost::intrusive_ptr cb) - { - return 0; - } - - int DBUser::complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) - { - return 0; - } - int DBUser::read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries, bool *is_truncated, RGWUsageIter& usage_iter, map& usage) @@ -1592,21 +1574,33 @@ namespace rgw::sal { return -ENOTSUP; } - int DBStore::load_account_stats(const DoutPrefixProvider* dpp, - optional_yield y, std::string_view id, - RGWStorageStats& stats, - ceph::real_time& last_synced, - ceph::real_time& last_updated) + int DBStore::load_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner, + RGWStorageStats& stats, + ceph::real_time& last_synced, + ceph::real_time& last_updated) + { + return 0; + } + int DBStore::load_stats_async(const DoutPrefixProvider* dpp, + const rgw_owner& owner, + boost::intrusive_ptr cb) { return -ENOTSUP; } - - int DBStore::load_account_stats_async(const DoutPrefixProvider* dpp, - std::string_view id, - boost::intrusive_ptr cb) + int DBStore::reset_stats(const DoutPrefixProvider *dpp, + optional_yield y, + const rgw_owner& owner) { return -ENOTSUP; } + int DBStore::complete_flush_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner) + { + return 0; + } std::string DBStore::get_cluster_id(const DoutPrefixProvider* dpp, optional_yield y) { diff --git a/src/rgw/rgw_sal_dbstore.h b/src/rgw/rgw_sal_dbstore.h index 8df568e3c9d..67033ed9f70 100644 --- a/src/rgw/rgw_sal_dbstore.h +++ b/src/rgw/rgw_sal_dbstore.h @@ -88,15 +88,7 @@ protected: virtual std::unique_ptr clone() override { return std::unique_ptr(new DBUser(*this)); } - int list_buckets(const DoutPrefixProvider *dpp, const std::string& marker, const std::string& end_marker, - uint64_t max, bool need_stats, BucketList& buckets, optional_yield y) override; virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) override; - virtual int read_stats(const DoutPrefixProvider *dpp, - optional_yield y, RGWStorageStats* stats, - ceph::real_time *last_stats_sync = nullptr, - ceph::real_time *last_stats_update = nullptr) override; - virtual int read_stats_async(const DoutPrefixProvider *dpp, boost::intrusive_ptr cb) override; - virtual int complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) 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, std::map& usage) override; @@ -781,20 +773,32 @@ public: optional_yield y, const RGWAccountInfo& info, RGWObjVersionTracker& objv) override; - int load_account_stats(const DoutPrefixProvider* dpp, - optional_yield y, std::string_view id, - RGWStorageStats& stats, - ceph::real_time& last_synced, - ceph::real_time& last_updated) override; - int load_account_stats_async(const DoutPrefixProvider* dpp, - std::string_view id, - boost::intrusive_ptr cb) override; + + int load_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner, + RGWStorageStats& stats, + ceph::real_time& last_synced, + ceph::real_time& last_updated) override; + int load_stats_async(const DoutPrefixProvider* dpp, + const rgw_owner& owner, + boost::intrusive_ptr cb) override; + int reset_stats(const DoutPrefixProvider *dpp, + optional_yield y, + const rgw_owner& owner) override; + int complete_flush_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner) override; virtual std::unique_ptr get_object(const rgw_obj_key& k) override; virtual std::string get_cluster_id(const DoutPrefixProvider* dpp, optional_yield y); std::unique_ptr get_bucket(const RGWBucketInfo& i) override; int load_bucket(const DoutPrefixProvider *dpp, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) override; + int list_buckets(const DoutPrefixProvider *dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, BucketList& buckets, optional_yield y) override; virtual bool is_meta_master() override; virtual Zone* get_zone() { return &zone; } virtual std::string zone_unique_id(uint64_t unique_num) override; diff --git a/src/rgw/rgw_sal_filter.cc b/src/rgw/rgw_sal_filter.cc index 358f3a9ae38..3032bdbedad 100644 --- a/src/rgw/rgw_sal_filter.cc +++ b/src/rgw/rgw_sal_filter.cc @@ -204,20 +204,35 @@ int FilterDriver::delete_account(const DoutPrefixProvider* dpp, return next->delete_account(dpp, y, info, objv); } -int FilterDriver::load_account_stats(const DoutPrefixProvider* dpp, - optional_yield y, std::string_view id, - RGWStorageStats& stats, - ceph::real_time& last_synced, - ceph::real_time& last_updated) +int FilterDriver::load_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner, + RGWStorageStats& stats, + ceph::real_time& last_synced, + ceph::real_time& last_updated) { - return next->load_account_stats(dpp, y, id, stats, last_synced, last_updated); + return next->load_stats(dpp, y, owner, stats, last_synced, last_updated); } -int FilterDriver::load_account_stats_async(const DoutPrefixProvider* dpp, - std::string_view id, - boost::intrusive_ptr cb) +int FilterDriver::load_stats_async(const DoutPrefixProvider* dpp, + const rgw_owner& owner, + boost::intrusive_ptr cb) { - return next->load_account_stats_async(dpp, id, std::move(cb)); + return next->load_stats_async(dpp, owner, std::move(cb)); +} + +int FilterDriver::reset_stats(const DoutPrefixProvider *dpp, + optional_yield y, + const rgw_owner& owner) +{ + return next->reset_stats(dpp, y, owner); +} + +int FilterDriver::complete_flush_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner) +{ + return next->complete_flush_stats(dpp, y, owner); } std::unique_ptr FilterDriver::get_object(const rgw_obj_key& k) @@ -240,6 +255,15 @@ int FilterDriver::load_bucket(const DoutPrefixProvider* dpp, const rgw_bucket& b return ret; } +int FilterDriver::list_buckets(const DoutPrefixProvider* dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, BucketList &buckets, optional_yield y) +{ + return next->list_buckets(dpp, owner, tenant, marker, end_marker, + max, need_stats, buckets, y); +} + bool FilterDriver::is_meta_master() { return next->is_meta_master(); @@ -545,14 +569,6 @@ CephContext* FilterDriver::ctx(void) return next->ctx(); } -int FilterUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& marker, - const std::string& end_marker, uint64_t max, - bool need_stats, BucketList &buckets, optional_yield y) -{ - return next->list_buckets(dpp, marker, end_marker, max, - need_stats, buckets, y); -} - int FilterUser::read_attrs(const DoutPrefixProvider* dpp, optional_yield y) { return next->read_attrs(dpp, y); @@ -564,24 +580,6 @@ int FilterUser::merge_and_store_attrs(const DoutPrefixProvider* dpp, return next->merge_and_store_attrs(dpp, new_attrs, y); } -int FilterUser::read_stats(const DoutPrefixProvider *dpp, - optional_yield y, RGWStorageStats* stats, - ceph::real_time* last_stats_sync, - ceph::real_time* last_stats_update) -{ - return next->read_stats(dpp, y, stats, last_stats_sync, last_stats_update); -} - -int FilterUser::read_stats_async(const DoutPrefixProvider *dpp, boost::intrusive_ptr cb) -{ - return next->read_stats_async(dpp, cb); -} - -int FilterUser::complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) -{ - return next->complete_flush_stats(dpp, y); -} - int FilterUser::read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch, uint32_t max_entries, bool* is_truncated, RGWUsageIter& usage_iter, diff --git a/src/rgw/rgw_sal_filter.h b/src/rgw/rgw_sal_filter.h index d896f999923..ffe7955c71c 100644 --- a/src/rgw/rgw_sal_filter.h +++ b/src/rgw/rgw_sal_filter.h @@ -186,19 +186,33 @@ public: optional_yield y, const RGWAccountInfo& info, RGWObjVersionTracker& objv) override; - int load_account_stats(const DoutPrefixProvider* dpp, - optional_yield y, std::string_view id, - RGWStorageStats& stats, - ceph::real_time& last_synced, - ceph::real_time& last_updated) override; - int load_account_stats_async(const DoutPrefixProvider* dpp, - std::string_view id, - boost::intrusive_ptr cb) override; + + int load_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner, + RGWStorageStats& stats, + ceph::real_time& last_synced, + ceph::real_time& last_updated) override; + int load_stats_async(const DoutPrefixProvider* dpp, + const rgw_owner& owner, + boost::intrusive_ptr cb) override; + int reset_stats(const DoutPrefixProvider *dpp, + optional_yield y, + const rgw_owner& owner) override; + int complete_flush_stats(const DoutPrefixProvider* dpp, + optional_yield y, + const rgw_owner& owner) override; virtual std::unique_ptr get_object(const rgw_obj_key& k) override; std::unique_ptr get_bucket(const RGWBucketInfo& i) override; int load_bucket(const DoutPrefixProvider* dpp, const rgw_bucket& b, std::unique_ptr* bucket, optional_yield y) override; + int list_buckets(const DoutPrefixProvider* dpp, + const rgw_owner& owner, const std::string& tenant, + const std::string& marker, const std::string& end_marker, + uint64_t max, bool need_stats, BucketList& buckets, + optional_yield y) override; + virtual bool is_meta_master() override; virtual Zone* get_zone() override { return zone.get(); } virtual std::string zone_unique_id(uint64_t unique_num) override; @@ -395,11 +409,6 @@ public: virtual std::unique_ptr clone() override { return std::make_unique(*this); } - virtual int list_buckets(const DoutPrefixProvider* dpp, - const std::string& marker, const std::string& end_marker, - uint64_t max, bool need_stats, BucketList& buckets, - optional_yield y) override; - virtual std::string& get_display_name() override { return next->get_display_name(); } virtual const std::string& get_tenant() override { return next->get_tenant(); } virtual void set_tenant(std::string& _t) override { next->set_tenant(_t); } @@ -421,13 +430,6 @@ public: virtual int read_attrs(const DoutPrefixProvider* dpp, optional_yield y) override; virtual int merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y) override; - virtual int read_stats(const DoutPrefixProvider *dpp, - optional_yield y, RGWStorageStats* stats, - ceph::real_time* last_stats_sync = nullptr, - ceph::real_time* last_stats_update = nullptr) override; - virtual int read_stats_async(const DoutPrefixProvider *dpp, - boost::intrusive_ptr cb) override; - virtual int complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) 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, diff --git a/src/rgw/rgw_user.cc b/src/rgw/rgw_user.cc index d77b50a1117..6636d8bea19 100644 --- a/src/rgw/rgw_user.cc +++ b/src/rgw/rgw_user.cc @@ -13,18 +13,19 @@ using namespace std; -int rgw_user_sync_all_stats(const DoutPrefixProvider *dpp, rgw::sal::Driver* driver, - rgw::sal::User* user, optional_yield y) +int rgw_sync_all_stats(const DoutPrefixProvider *dpp, + optional_yield y, rgw::sal::Driver* driver, + const rgw_owner& owner, const std::string& tenant) { size_t max_entries = dpp->get_cct()->_conf->rgw_list_buckets_max_chunk; rgw::sal::BucketList listing; int ret = 0; do { - ret = user->list_buckets(dpp, listing.next_marker, string(), - max_entries, false, listing, y); + ret = driver->list_buckets(dpp, owner, tenant, listing.next_marker, + string(), max_entries, false, listing, y); if (ret < 0) { - ldpp_dout(dpp, 0) << "failed to read user buckets: ret=" << ret << dendl; + ldpp_dout(dpp, 0) << "failed to list buckets: " << cpp_strerror(ret) << dendl; return ret; } @@ -47,9 +48,9 @@ int rgw_user_sync_all_stats(const DoutPrefixProvider *dpp, rgw::sal::Driver* dri } } while (!listing.next_marker.empty()); - ret = user->complete_flush_stats(dpp, y); + ret = driver->complete_flush_stats(dpp, y, owner); if (ret < 0) { - cerr << "ERROR: failed to complete syncing user stats: ret=" << ret << std::endl; + ldpp_dout(dpp, 0) << "ERROR: failed to complete syncing owner stats: ret=" << ret << dendl; return ret; } @@ -66,8 +67,9 @@ int rgw_user_get_all_buckets_stats(const DoutPrefixProvider *dpp, rgw::sal::BucketList listing; do { - int ret = user->list_buckets(dpp, listing.next_marker, string(), - max_entries, false, listing, y); + int ret = driver->list_buckets(dpp, user->get_id(), user->get_tenant(), + listing.next_marker, string(), + max_entries, false, listing, y); if (ret < 0) { ldpp_dout(dpp, 0) << "failed to read user buckets: ret=" << ret << dendl; return ret; diff --git a/src/rgw/services/svc_user.h b/src/rgw/services/svc_user.h index 6ff412a8a26..6cb377b7007 100644 --- a/src/rgw/services/svc_user.h +++ b/src/rgw/services/svc_user.h @@ -90,40 +90,5 @@ public: real_time *pmtime, optional_yield y, const DoutPrefixProvider *dpp) = 0; - - virtual int add_bucket(const DoutPrefixProvider *dpp, - const rgw_user& user, - const rgw_bucket& bucket, - ceph::real_time creation_time, - optional_yield y) = 0; - virtual int remove_bucket(const DoutPrefixProvider *dpp, - const rgw_user& user, - const rgw_bucket& _bucket, optional_yield) = 0; - virtual int list_buckets(const DoutPrefixProvider *dpp, - const rgw_user& user, - const std::string& marker, - const std::string& end_marker, - uint64_t max, - rgw::sal::BucketList& listing, - optional_yield y) = 0; - - virtual int flush_bucket_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, - const RGWBucketEnt& ent, optional_yield y) = 0; - virtual int complete_flush_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, optional_yield y) = 0; - virtual int reset_bucket_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, - optional_yield y) = 0; - virtual int read_stats(const DoutPrefixProvider *dpp, - RGWSI_MetaBackend::Context *ctx, - const rgw_user& user, RGWStorageStats *stats, - ceph::real_time *last_stats_sync, /* last time a full stats sync completed */ - ceph::real_time *last_stats_update, - optional_yield y) = 0; /* last time a stats update was done */ - - virtual int read_stats_async(const DoutPrefixProvider *dpp, - const rgw_user& user, - boost::intrusive_ptr cb) = 0; }; diff --git a/src/rgw/services/svc_user_rados.cc b/src/rgw/services/svc_user_rados.cc index b8fdd3212fd..83322b04249 100644 --- a/src/rgw/services/svc_user_rados.cc +++ b/src/rgw/services/svc_user_rados.cc @@ -623,100 +623,3 @@ int RGWSI_User_RADOS::get_user_info_by_access_key(RGWSI_MetaBackend::Context *ct svc.zone->get_zone_params().user_keys_pool, info, objv_tracker, pmtime, y, dpp); } - -int RGWSI_User_RADOS::add_bucket(const DoutPrefixProvider *dpp, - const rgw_user& user, - const rgw_bucket& bucket, - ceph::real_time creation_time, - optional_yield y) -{ - rgw_raw_obj obj = get_buckets_obj(user); - int ret = rgwrados::buckets::add(dpp, y, *rados, obj, - bucket, creation_time); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: error adding bucket to user: ret=" << ret << dendl; - return ret; - } - - return 0; -} - - -int RGWSI_User_RADOS::remove_bucket(const DoutPrefixProvider *dpp, - const rgw_user& user, - const rgw_bucket& bucket, - optional_yield y) -{ - rgw_raw_obj obj = get_buckets_obj(user); - int ret = rgwrados::buckets::remove(dpp, y, *rados, obj, bucket); - if (ret < 0) { - ldpp_dout(dpp, 0) << "ERROR: error removing bucket from user: ret=" << ret << dendl; - } - - return 0; -} - -int RGWSI_User_RADOS::list_buckets(const DoutPrefixProvider *dpp, - const rgw_user& user, - const string& marker, - const string& end_marker, - uint64_t max, - rgw::sal::BucketList& listing, - optional_yield y) -{ - if (user.id == RGW_USER_ANON_ID) { - ldpp_dout(dpp, 20) << "RGWSI_User_RADOS::list_buckets(): anonymous user" << dendl; - listing.next_marker.clear(); - return 0; - } - - rgw_raw_obj obj = get_buckets_obj(user); - return rgwrados::buckets::list(dpp, y, *rados, obj, user.tenant, - marker, end_marker, max, listing); -} - -int RGWSI_User_RADOS::flush_bucket_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, - const RGWBucketEnt& ent, - optional_yield y) -{ - rgw_raw_obj obj = get_buckets_obj(user); - return rgwrados::buckets::write_stats(dpp, y, *rados, obj, ent); -} - -int RGWSI_User_RADOS::reset_bucket_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, - optional_yield y) -{ - rgw_raw_obj obj = get_buckets_obj(user); - return rgwrados::buckets::reset_stats(dpp, y, *rados, obj); -} - -int RGWSI_User_RADOS::complete_flush_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, optional_yield y) -{ - rgw_raw_obj obj = get_buckets_obj(user); - return rgwrados::buckets::complete_flush_stats(dpp, y, *rados, obj); -} - -int RGWSI_User_RADOS::read_stats(const DoutPrefixProvider *dpp, - RGWSI_MetaBackend::Context *ctx, - const rgw_user& user, RGWStorageStats *stats, - ceph::real_time *last_stats_sync, - ceph::real_time *last_stats_update, - optional_yield y) -{ - rgw_raw_obj obj = get_buckets_obj(user); - return rgwrados::buckets::read_stats( - dpp, y, *rados, obj, *stats, - last_stats_sync, last_stats_update); -} - -int RGWSI_User_RADOS::read_stats_async(const DoutPrefixProvider *dpp, - const rgw_user& user, - boost::intrusive_ptr cb) -{ - rgw_raw_obj obj = get_buckets_obj(user); - return rgwrados::buckets::read_stats_async(dpp, *rados, obj, std::move(cb)); -} - diff --git a/src/rgw/services/svc_user_rados.h b/src/rgw/services/svc_user_rados.h index aa43f9c0c18..69851d1db75 100644 --- a/src/rgw/services/svc_user_rados.h +++ b/src/rgw/services/svc_user_rados.h @@ -144,45 +144,4 @@ public: real_time *pmtime, optional_yield y, const DoutPrefixProvider *dpp) override; - - /* user buckets directory */ - - int add_bucket(const DoutPrefixProvider *dpp, - const rgw_user& user, - const rgw_bucket& bucket, - ceph::real_time creation_time, - optional_yield y) override; - int remove_bucket(const DoutPrefixProvider *dpp, - const rgw_user& user, - const rgw_bucket& _bucket, - optional_yield y) override; - int list_buckets(const DoutPrefixProvider *dpp, - const rgw_user& user, - const std::string& marker, - const std::string& end_marker, - uint64_t max, - rgw::sal::BucketList& listing, - optional_yield y) override; - - /* quota related */ - int flush_bucket_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, - const RGWBucketEnt& ent, optional_yield y) override; - - int complete_flush_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, optional_yield y) override; - - int reset_bucket_stats(const DoutPrefixProvider *dpp, - const rgw_user& user, - optional_yield y) override; - int read_stats(const DoutPrefixProvider *dpp, - RGWSI_MetaBackend::Context *ctx, - const rgw_user& user, RGWStorageStats *stats, - ceph::real_time *last_stats_sync, /* last time a full stats sync completed */ - ceph::real_time *last_stats_update, - optional_yield y) override; /* last time a stats update was done */ - - int read_stats_async(const DoutPrefixProvider *dpp, const rgw_user& user, - boost::intrusive_ptr cb) override; }; - diff --git a/src/test/rgw/test_rgw_lua.cc b/src/test/rgw/test_rgw_lua.cc index 57bfc08ea35..a1343e10b15 100644 --- a/src/test/rgw/test_rgw_lua.cc +++ b/src/test/rgw/test_rgw_lua.cc @@ -93,18 +93,6 @@ public: return 0; } - virtual int read_stats(const DoutPrefixProvider *dpp, optional_yield y, RGWStorageStats* stats, ceph::real_time *last_stats_sync, ceph::real_time *last_stats_update) override { - return 0; - } - - virtual int read_stats_async(const DoutPrefixProvider *dpp, boost::intrusive_ptr cb) override { - return 0; - } - - virtual int complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y) override { - return 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, map& usage) override { return 0; } -- 2.39.5