Skip to content

Commit 1aca146

Browse files
authored
Merge pull request ceph#65415 from kchheda3/wip-re-create-bucket
rgw/create-bucket: Do not re-create the bucket instance & bucket index shard object if if bucket already exist..
2 parents b1cdf2f + 625e3ab commit 1aca146

File tree

3 files changed

+115
-124
lines changed

3 files changed

+115
-124
lines changed

src/rgw/rgw_op.cc

Lines changed: 113 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -3695,6 +3695,84 @@ static int select_bucket_placement(const DoutPrefixProvider* dpp,
36953695
return 0;
36963696
}
36973697

3698+
int put_swift_bucket_metadata(const DoutPrefixProvider* dpp,
3699+
req_state* s,
3700+
RGWAccessControlPolicy& policy,
3701+
bool const has_policy,
3702+
uint32_t policy_rw_mask,
3703+
const RGWCORSConfiguration& cors_config,
3704+
bool const has_cors,
3705+
std::optional<std::string> swift_ver_location,
3706+
const std::set<std::string>& rmattr_names,
3707+
optional_yield y) {
3708+
std::map<std::string, ceph::bufferlist> attrs;
3709+
int op_ret = rgw_get_request_metadata(dpp, s->cct, s->info, attrs, false);
3710+
if (op_ret < 0) {
3711+
return op_ret;
3712+
}
3713+
3714+
return retry_raced_bucket_write(
3715+
dpp, s->bucket.get(),
3716+
[s, has_policy, policy_rw_mask, &policy, cors_config, has_cors, &attrs,
3717+
dpp, rmattr_names, swift_ver_location] {
3718+
/* Encode special metadata first as we're using std::map::emplace under
3719+
* the hood. This method will add the new items only if the map doesn't
3720+
* contain such keys yet. */
3721+
if (has_policy) {
3722+
if (s->dialect.compare("swift") == 0) {
3723+
rgw::swift::merge_policy(policy_rw_mask, s->bucket_acl, policy);
3724+
}
3725+
buffer::list bl;
3726+
policy.encode(bl);
3727+
attrs.emplace(RGW_ATTR_ACL, std::move(bl));
3728+
}
3729+
3730+
if (has_cors) {
3731+
buffer::list bl;
3732+
cors_config.encode(bl);
3733+
attrs.emplace(RGW_ATTR_CORS, std::move(bl));
3734+
}
3735+
3736+
/* It's supposed that following functions WILL NOT change any
3737+
* special attributes (like RGW_ATTR_ACL) if they are already
3738+
* present in attrs. */
3739+
prepare_add_del_attrs(s->bucket_attrs, rmattr_names, attrs);
3740+
populate_with_generic_attrs(s, attrs);
3741+
3742+
/* According to the Swift's behaviour and its container_quota
3743+
* WSGI middleware implementation: anyone with write permissions
3744+
* is able to set the bucket quota. This stays in contrast to
3745+
* account quotas that can be set only by clients holding
3746+
* reseller admin privileges. */
3747+
int ret = filter_out_quota_info(attrs, rmattr_names,
3748+
s->bucket->get_info().quota);
3749+
if (ret < 0) {
3750+
return ret;
3751+
}
3752+
3753+
if (swift_ver_location) {
3754+
s->bucket->get_info().swift_ver_location = *swift_ver_location;
3755+
s->bucket->get_info().swift_versioning =
3756+
(!swift_ver_location->empty());
3757+
}
3758+
3759+
/* Web site of Swift API. */
3760+
filter_out_website(attrs, rmattr_names,
3761+
s->bucket->get_info().website_conf);
3762+
s->bucket->get_info().has_website =
3763+
!s->bucket->get_info().website_conf.is_empty();
3764+
3765+
/* Setting attributes also stores the provided bucket info. Due
3766+
* to this fact, the new quota settings can be serialized with
3767+
* the same call. */
3768+
s->bucket->set_attrs(attrs);
3769+
constexpr bool exclusive = false; // overwrite
3770+
constexpr ceph::real_time no_set_mtime{};
3771+
return s->bucket->put_info(dpp, exclusive, no_set_mtime, s->yield);
3772+
},
3773+
y);
3774+
}
3775+
36983776
void RGWCreateBucket::execute(optional_yield y)
36993777
{
37003778
op_ret = get_params(y);
@@ -3806,6 +3884,24 @@ void RGWCreateBucket::execute(optional_yield y)
38063884
return;
38073885
}
38083886

3887+
// prevent re-creation with different index type or shard count
3888+
if ((createparams.index_type && *createparams.index_type !=
3889+
info.layout.current_index.layout.type) ||
3890+
(createparams.index_shards && *createparams.index_shards !=
3891+
info.layout.current_index.layout.normal.num_shards)) {
3892+
s->err.message =
3893+
"Cannot modify existing bucket's index type or shard count";
3894+
op_ret = -EEXIST;
3895+
return;
3896+
}
3897+
3898+
// don't allow changes to object lock
3899+
if (createparams.obj_lock_enabled != info.obj_lock_enabled()) {
3900+
s->err.message = "Cannot modify existing bucket's object lock";
3901+
op_ret = -EEXIST;
3902+
return;
3903+
}
3904+
38093905
// don't allow changes to the acl policy
38103906
RGWAccessControlPolicy old_policy;
38113907
int r = rgw_op_get_bucket_policy_from_attr(this, s->cct, driver, info.owner,
@@ -3816,6 +3912,20 @@ void RGWCreateBucket::execute(optional_yield y)
38163912
op_ret = -EEXIST;
38173913
return;
38183914
}
3915+
3916+
// For s3::CreateBucket just return back if bucket exists, as we do not allow
3917+
// any changes in bucket config param. need_metadata_upload() is always false
3918+
// for S3, so use the check to decide if its s3 request and not swift request.
3919+
if (!need_metadata_upload()) {
3920+
op_ret = -ERR_BUCKET_EXISTS;
3921+
return;
3922+
} else {
3923+
// For swift, update the bucket metadata and do not call createbucket.
3924+
op_ret = put_swift_bucket_metadata(
3925+
this, s, policy, has_policy, policy_rw_mask, cors_config, has_cors,
3926+
createparams.swift_ver_location, rmattr_names, y);
3927+
return;
3928+
}
38193929
}
38203930

38213931
s->bucket_owner = policy.get_owner();
@@ -3888,68 +3998,6 @@ void RGWCreateBucket::execute(optional_yield y)
38883998
/* continue if EEXIST and create_bucket will fail below. this way we can
38893999
* recover from a partial create by retrying it. */
38904000
ldpp_dout(this, 20) << "Bucket::create() returned ret=" << op_ret << " bucket=" << s->bucket << dendl;
3891-
3892-
if (op_ret < 0 && op_ret != -EEXIST && op_ret != -ERR_BUCKET_EXISTS)
3893-
return;
3894-
3895-
const bool existed = s->bucket_exists;
3896-
if (need_metadata_upload() && existed) {
3897-
/* OK, it looks we lost race with another request. As it's required to
3898-
* handle metadata fusion and upload, the whole operation becomes very
3899-
* similar in nature to PutMetadataBucket. However, as the attrs may
3900-
* changed in the meantime, we have to refresh. */
3901-
short tries = 0;
3902-
do {
3903-
map<string, bufferlist> battrs;
3904-
3905-
op_ret = s->bucket->load_bucket(this, y);
3906-
if (op_ret < 0) {
3907-
return;
3908-
} else if (!s->auth.identity->is_owner_of(s->bucket->get_owner())) {
3909-
/* New bucket doesn't belong to the account we're operating on. */
3910-
op_ret = -EEXIST;
3911-
return;
3912-
} else {
3913-
s->bucket_attrs = s->bucket->get_attrs();
3914-
}
3915-
3916-
createparams.attrs.clear();
3917-
3918-
op_ret = rgw_get_request_metadata(this, s->cct, s->info, createparams.attrs, false);
3919-
if (op_ret < 0) {
3920-
return;
3921-
}
3922-
prepare_add_del_attrs(s->bucket_attrs, rmattr_names, createparams.attrs);
3923-
populate_with_generic_attrs(s, createparams.attrs);
3924-
op_ret = filter_out_quota_info(createparams.attrs, rmattr_names,
3925-
s->bucket->get_info().quota);
3926-
if (op_ret < 0) {
3927-
return;
3928-
}
3929-
3930-
/* Handle updates of the metadata for Swift's object versioning. */
3931-
if (createparams.swift_ver_location) {
3932-
s->bucket->get_info().swift_ver_location = *createparams.swift_ver_location;
3933-
s->bucket->get_info().swift_versioning = !createparams.swift_ver_location->empty();
3934-
}
3935-
3936-
/* Web site of Swift API. */
3937-
filter_out_website(createparams.attrs, rmattr_names,
3938-
s->bucket->get_info().website_conf);
3939-
s->bucket->get_info().has_website = !s->bucket->get_info().website_conf.is_empty();
3940-
3941-
/* This will also set the quota on the bucket. */
3942-
s->bucket->set_attrs(std::move(createparams.attrs));
3943-
constexpr bool exclusive = false; // overwrite
3944-
constexpr ceph::real_time no_set_mtime{};
3945-
op_ret = s->bucket->put_info(this, exclusive, no_set_mtime, y);
3946-
} while (op_ret == -ECANCELED && tries++ < 20);
3947-
3948-
/* Restore the proper return code. */
3949-
if (op_ret >= 0) {
3950-
op_ret = -ERR_BUCKET_EXISTS;
3951-
}
3952-
} /* if (need_metadata_upload() && existed) */
39534001
} /* RGWCreateBucket::execute() */
39544002

39554003
int RGWDeleteBucket::verify_permission(optional_yield y)
@@ -5304,71 +5352,15 @@ void RGWPutMetadataBucket::execute(optional_yield y)
53045352
if (op_ret < 0) {
53055353
return;
53065354
}
5307-
5308-
op_ret = rgw_get_request_metadata(this, s->cct, s->info, attrs, false);
5309-
if (op_ret < 0) {
5310-
return;
5311-
}
5312-
53135355
if (!placement_rule.empty() &&
53145356
placement_rule != s->bucket->get_placement_rule()) {
53155357
op_ret = -EEXIST;
53165358
return;
53175359
}
53185360

5319-
op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this] {
5320-
/* Encode special metadata first as we're using std::map::emplace under
5321-
* the hood. This method will add the new items only if the map doesn't
5322-
* contain such keys yet. */
5323-
if (has_policy) {
5324-
if (s->dialect.compare("swift") == 0) {
5325-
rgw::swift::merge_policy(policy_rw_mask, s->bucket_acl, policy);
5326-
}
5327-
buffer::list bl;
5328-
policy.encode(bl);
5329-
emplace_attr(RGW_ATTR_ACL, std::move(bl));
5330-
}
5331-
5332-
if (has_cors) {
5333-
buffer::list bl;
5334-
cors_config.encode(bl);
5335-
emplace_attr(RGW_ATTR_CORS, std::move(bl));
5336-
}
5337-
5338-
/* It's supposed that following functions WILL NOT change any
5339-
* special attributes (like RGW_ATTR_ACL) if they are already
5340-
* present in attrs. */
5341-
prepare_add_del_attrs(s->bucket_attrs, rmattr_names, attrs);
5342-
populate_with_generic_attrs(s, attrs);
5343-
5344-
/* According to the Swift's behaviour and its container_quota
5345-
* WSGI middleware implementation: anyone with write permissions
5346-
* is able to set the bucket quota. This stays in contrast to
5347-
* account quotas that can be set only by clients holding
5348-
* reseller admin privileges. */
5349-
op_ret = filter_out_quota_info(attrs, rmattr_names, s->bucket->get_info().quota);
5350-
if (op_ret < 0) {
5351-
return op_ret;
5352-
}
5353-
5354-
if (swift_ver_location) {
5355-
s->bucket->get_info().swift_ver_location = *swift_ver_location;
5356-
s->bucket->get_info().swift_versioning = (!swift_ver_location->empty());
5357-
}
5358-
5359-
/* Web site of Swift API. */
5360-
filter_out_website(attrs, rmattr_names, s->bucket->get_info().website_conf);
5361-
s->bucket->get_info().has_website = !s->bucket->get_info().website_conf.is_empty();
5362-
5363-
/* Setting attributes also stores the provided bucket info. Due
5364-
* to this fact, the new quota settings can be serialized with
5365-
* the same call. */
5366-
s->bucket->set_attrs(attrs);
5367-
constexpr bool exclusive = false; // overwrite
5368-
constexpr ceph::real_time no_set_mtime{};
5369-
op_ret = s->bucket->put_info(this, exclusive, no_set_mtime, s->yield);
5370-
return op_ret;
5371-
}, y);
5361+
op_ret = put_swift_bucket_metadata(this, s, policy, has_policy,
5362+
policy_rw_mask, cors_config, has_cors,
5363+
swift_ver_location, rmattr_names, y);
53725364
}
53735365

53745366
int RGWPutMetadataObject::verify_permission(optional_yield y)

src/rgw/rgw_op.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,8 @@ class RGWCreateBucket : public RGWOp {
11491149
RGWAccessControlPolicy policy;
11501150
std::string location_constraint;
11511151
bool has_cors = false;
1152+
bool has_policy = false;
1153+
uint32_t policy_rw_mask = 0;
11521154
bool relaxed_region_enforcement = false;
11531155
RGWCORSConfiguration cors_config;
11541156
std::set<std::string> rmattr_names;

src/rgw/rgw_rest_swift.cc

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -811,9 +811,6 @@ static int get_swift_versioning_settings(
811811

812812
int RGWCreateBucket_ObjStore_SWIFT::get_params(optional_yield y)
813813
{
814-
bool has_policy;
815-
uint32_t policy_rw_mask = 0;
816-
817814
int r = get_swift_container_settings(s, driver, policy, &has_policy,
818815
&policy_rw_mask, &cors_config, &has_cors);
819816
if (r < 0) {

0 commit comments

Comments
 (0)