@@ -5621,23 +5621,16 @@ int get_zone_ids(const DoutPrefixProvider *dpp,
56215621int list_remote_buckets (const DoutPrefixProvider *dpp,
56225622 rgw::sal::RadosStore* const driver,
56235623 const rgw_zone_id source_zone,
5624+ std::vector<rgw_zone_id> zids,
56245625 const rgw_bucket& bucket,
56255626 optional_yield y)
56265627{
5627-
5628- std::vector<rgw_zone_id> zids;
5629- int ret = get_zone_ids (dpp, driver, source_zone, bucket, zids, y);
5630- if (ret < 0 ) {
5631- ldpp_dout (dpp, 10 ) << " failed to get remote zones (r=" << ret << " )" << dendl;
5632- return ret;
5633- }
5634-
56355628 std::vector<bucket_unordered_list_result> peer_status;
56365629 peer_status.resize (zids.size ());
56375630
56385631 RGWCoroutinesManager crs (driver->ctx (), driver->getRados ()->get_cr_registry ());
56395632 RGWHTTPManager http (driver->ctx (), crs.get_completion_mgr ());
5640- ret = http.start ();
5633+ int ret = http.start ();
56415634 if (ret < 0 ) {
56425635 ldpp_dout (dpp, 0 ) << " failed in http_manager.start() ret=" << ret << dendl;
56435636 return ret;
@@ -5657,6 +5650,62 @@ int list_remote_buckets(const DoutPrefixProvider *dpp,
56575650 return 0 ;
56585651}
56595652
5653+ int check_remote_bucket_empty (const DoutPrefixProvider* dpp,
5654+ rgw::sal::RadosStore* const driver,
5655+ const rgw_zone_id source_zone,
5656+ RGWBucketInfo& bucket_info,
5657+ std::map<rgw_zone_id, RGWZone> zones,
5658+ const rgw_sync_policy_info* zg_sync_policy,
5659+ optional_yield y)
5660+ {
5661+ std::vector<rgw_zone_id> zids;
5662+ int ret = get_zone_ids (dpp, driver, source_zone, bucket_info.bucket , zids, y);
5663+ if (ret < 0 ) {
5664+ ldpp_dout (dpp, 10 ) << " failed to get remote zones (r=" << ret << " )" << dendl;
5665+ return ret;
5666+ }
5667+
5668+ /* when sync policy is configured to be unidirectional or some zones
5669+ opted out of sync or due to object filtering with prefix or tags,
5670+ the source and destination buckets can diverge. check for all such
5671+ cases, list the buckets in those zones and return enotempty */
5672+
5673+ bool is_zg_policy_directional = false ;
5674+ if (zg_sync_policy) {
5675+ is_zg_policy_directional = zg_sync_policy->is_directional ();
5676+ }
5677+
5678+ bool is_bucket_policy_directional = false ;
5679+ bool bucket_has_filter = false ;
5680+ auto bucket_sync_policy = bucket_info.sync_policy ;
5681+ if (bucket_sync_policy) {
5682+ is_bucket_policy_directional = bucket_sync_policy->is_directional ();
5683+ bucket_has_filter = bucket_sync_policy->has_filter ();
5684+ }
5685+
5686+ if (is_zg_policy_directional || is_bucket_policy_directional ||
5687+ bucket_has_filter) {
5688+ ldpp_dout (dpp, 10 ) << " sync policy exists. listing remote zones" << dendl;
5689+ return list_remote_buckets (dpp, driver, source_zone, zids, bucket_info.bucket , y);
5690+ }
5691+
5692+ std::vector<rgw_zone_id> opt_out_zones; // zones not participating in sync
5693+ for (const auto & z : zones) {
5694+ if (std::find (zids.begin (), zids.end (), z.first ) == zids.end ()) {
5695+ if (z.first == source_zone) {
5696+ continue ;
5697+ }
5698+ opt_out_zones.push_back (z.first );
5699+ }
5700+ }
5701+
5702+ if (!opt_out_zones.empty ()) {
5703+ ldpp_dout (dpp, 10 ) << " sync policy exists. listing remote zones" << dendl;
5704+ return list_remote_buckets (dpp, driver, source_zone, opt_out_zones, bucket_info.bucket , y);
5705+ }
5706+ return 0 ;
5707+ }
5708+
56605709/* *
56615710 * Delete a bucket.
56625711 * bucket: the name of the bucket to delete
@@ -5678,30 +5727,19 @@ int RGWRados::delete_bucket(RGWBucketInfo& bucket_info, std::map<std::string, bu
56785727 }
56795728 }
56805729
5681- // delete_bucket checks for objects in the bucket on other zones,
5682- // if there is bucket sync policy configured, by doing unordered
5683- // listing with max_key=1. if objects are found, don't delete the bucket.
5730+ // check if asymmetric replication policy exists either at zonegroup or bucket level.
5731+ // if objects still exist in remote zones, don't delete the bucket.
56845732 if (svc.zone ->is_syncing_bucket_meta ()) {
5685- // check if asymmetric replication policy exists either at zonegroup or bucket level
5686- auto zg_sync_policy = svc.zone ->get_zonegroup ().sync_policy ;
5687- bool is_zg_policy_directional = zg_sync_policy.is_directional ();
5688-
5689- bool is_bucket_policy_directional = false ;
5690- auto bucket_sync_policy = bucket_info.sync_policy ;
5691- if (bucket_sync_policy) {
5692- is_bucket_policy_directional = bucket_sync_policy->is_directional ();
5693- }
5694- if (is_zg_policy_directional || is_bucket_policy_directional) {
5695- ldpp_dout (dpp, 10 ) << " sync policy exists. listing remote zones" << dendl;
5696- const rgw_zone_id source_zone = svc.zone ->get_zone_params ().get_id ();
5697- r = list_remote_buckets (dpp, driver, source_zone, bucket, y);
5698- if (r == -ENOTEMPTY) {
5699- ldpp_dout (dpp, 0 ) << " ERROR: cannot delete bucket. objects exist in the bucket on another zone " << dendl;
5700- return r;
5701- } else if (r < 0 ) {
5702- ldpp_dout (dpp, 10 ) << " failed to list remote buckets" << dendl;
5703- // don't return.
5704- }
5733+ const rgw_zone_id source_zone = svc.zone ->get_zone_params ().get_id ();
5734+ int r = check_remote_bucket_empty (dpp, driver, source_zone, bucket_info,
5735+ svc.zone ->get_zonegroup ().zones ,
5736+ &svc.zone ->get_zonegroup ().sync_policy , y);
5737+ if (r == -ENOTEMPTY) {
5738+ ldpp_dout (dpp, 0 ) << " ERROR: cannot delete bucket. objects exist in the bucket on another zone " << dendl;
5739+ return r;
5740+ } else if (r < 0 ) {
5741+ ldpp_dout (dpp, 10 ) << " failed to list remote buckets" << dendl;
5742+ // don't return.
57055743 }
57065744 }
57075745
0 commit comments