Skip to content

Commit 8fbef97

Browse files
author
Shilpa Jagannath
committed
rgw/multisite: account for zones opted out of sync and object filters
during bucket deletion Signed-off-by: Shilpa Jagannath <[email protected]>
1 parent 52df364 commit 8fbef97

File tree

4 files changed

+1123
-571
lines changed

4 files changed

+1123
-571
lines changed

src/rgw/driver/rados/rgw_rados.cc

Lines changed: 70 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5621,23 +5621,16 @@ int get_zone_ids(const DoutPrefixProvider *dpp,
56215621
int 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

src/rgw/rgw_sync_policy.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,11 @@ bool rgw_sync_pipe_filter::has_tags() const
150150
return !tags.empty();
151151
}
152152

153+
bool rgw_sync_pipe_filter::has_prefix() const
154+
{
155+
return prefix.has_value();
156+
}
157+
153158
bool rgw_sync_pipe_filter::check_tags(const std::vector<string>& _tags) const
154159
{
155160
if (tags.empty()) {

src/rgw/rgw_sync_policy.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ struct rgw_sync_pipe_filter {
240240
bool is_subset_of(const rgw_sync_pipe_filter& f) const;
241241

242242
bool has_tags() const;
243+
bool has_prefix() const;
243244
bool check_tag(const std::string& s) const;
244245
bool check_tag(const std::string& k, const std::string& v) const;
245246
bool check_tags(const std::vector<std::string>& tags) const;
@@ -685,6 +686,19 @@ struct rgw_sync_policy_info {
685686
return false;
686687
}
687688

689+
bool has_filter() const {
690+
for (auto& item : groups) {
691+
auto& group = item.second;
692+
for (auto& p : group.pipes) {
693+
auto& filter = p.params.source.filter;
694+
if (filter.has_prefix() || filter.has_tags()) {
695+
return true;
696+
}
697+
}
698+
}
699+
return false;
700+
}
701+
688702
void get_potential_related_buckets(const rgw_bucket& bucket,
689703
std::set<rgw_bucket> *sources,
690704
std::set<rgw_bucket> *dests) const;

0 commit comments

Comments
 (0)