@@ -3687,6 +3687,84 @@ static int select_bucket_placement(const DoutPrefixProvider* dpp,
36873687 return 0 ;
36883688}
36893689
3690+ int put_swift_bucket_metadata (const DoutPrefixProvider* dpp,
3691+ req_state* s,
3692+ RGWAccessControlPolicy& policy,
3693+ bool const has_policy,
3694+ uint32_t policy_rw_mask,
3695+ const RGWCORSConfiguration& cors_config,
3696+ bool const has_cors,
3697+ std::optional<std::string> swift_ver_location,
3698+ const std::set<std::string>& rmattr_names,
3699+ optional_yield y) {
3700+ std::map<std::string, ceph::bufferlist> attrs;
3701+ int op_ret = rgw_get_request_metadata (dpp, s->cct , s->info , attrs, false );
3702+ if (op_ret < 0 ) {
3703+ return op_ret;
3704+ }
3705+
3706+ return retry_raced_bucket_write (
3707+ dpp, s->bucket .get (),
3708+ [s, has_policy, policy_rw_mask, &policy, cors_config, has_cors, &attrs,
3709+ dpp, rmattr_names, swift_ver_location] {
3710+ /* Encode special metadata first as we're using std::map::emplace under
3711+ * the hood. This method will add the new items only if the map doesn't
3712+ * contain such keys yet. */
3713+ if (has_policy) {
3714+ if (s->dialect .compare (" swift" ) == 0 ) {
3715+ rgw::swift::merge_policy (policy_rw_mask, s->bucket_acl , policy);
3716+ }
3717+ buffer::list bl;
3718+ policy.encode (bl);
3719+ attrs.emplace (RGW_ATTR_ACL, std::move (bl));
3720+ }
3721+
3722+ if (has_cors) {
3723+ buffer::list bl;
3724+ cors_config.encode (bl);
3725+ attrs.emplace (RGW_ATTR_CORS, std::move (bl));
3726+ }
3727+
3728+ /* It's supposed that following functions WILL NOT change any
3729+ * special attributes (like RGW_ATTR_ACL) if they are already
3730+ * present in attrs. */
3731+ prepare_add_del_attrs (s->bucket_attrs , rmattr_names, attrs);
3732+ populate_with_generic_attrs (s, attrs);
3733+
3734+ /* According to the Swift's behaviour and its container_quota
3735+ * WSGI middleware implementation: anyone with write permissions
3736+ * is able to set the bucket quota. This stays in contrast to
3737+ * account quotas that can be set only by clients holding
3738+ * reseller admin privileges. */
3739+ int ret = filter_out_quota_info (attrs, rmattr_names,
3740+ s->bucket ->get_info ().quota );
3741+ if (ret < 0 ) {
3742+ return ret;
3743+ }
3744+
3745+ if (swift_ver_location) {
3746+ s->bucket ->get_info ().swift_ver_location = *swift_ver_location;
3747+ s->bucket ->get_info ().swift_versioning =
3748+ (!swift_ver_location->empty ());
3749+ }
3750+
3751+ /* Web site of Swift API. */
3752+ filter_out_website (attrs, rmattr_names,
3753+ s->bucket ->get_info ().website_conf );
3754+ s->bucket ->get_info ().has_website =
3755+ !s->bucket ->get_info ().website_conf .is_empty ();
3756+
3757+ /* Setting attributes also stores the provided bucket info. Due
3758+ * to this fact, the new quota settings can be serialized with
3759+ * the same call. */
3760+ s->bucket ->set_attrs (attrs);
3761+ constexpr bool exclusive = false ; // overwrite
3762+ constexpr ceph::real_time no_set_mtime{};
3763+ return s->bucket ->put_info (dpp, exclusive, no_set_mtime, s->yield );
3764+ },
3765+ y);
3766+ }
3767+
36903768void RGWCreateBucket::execute (optional_yield y)
36913769{
36923770 op_ret = get_params (y);
@@ -3833,6 +3911,12 @@ void RGWCreateBucket::execute(optional_yield y)
38333911 if (!need_metadata_upload ()) {
38343912 op_ret = -ERR_BUCKET_EXISTS;
38353913 return ;
3914+ } else {
3915+ // For swift, update the bucket metadata and do not call createbucket.
3916+ op_ret = put_swift_bucket_metadata (
3917+ this , s, policy, has_policy, policy_rw_mask, cors_config, has_cors,
3918+ createparams.swift_ver_location , rmattr_names, y);
3919+ return ;
38363920 }
38373921 }
38383922
@@ -3900,68 +3984,6 @@ void RGWCreateBucket::execute(optional_yield y)
39003984 /* continue if EEXIST and create_bucket will fail below. this way we can
39013985 * recover from a partial create by retrying it. */
39023986 ldpp_dout (this , 20 ) << " Bucket::create() returned ret=" << op_ret << " bucket=" << s->bucket << dendl;
3903-
3904- if (op_ret < 0 && op_ret != -EEXIST && op_ret != -ERR_BUCKET_EXISTS)
3905- return ;
3906-
3907- const bool existed = s->bucket_exists ;
3908- if (need_metadata_upload () && existed) {
3909- /* OK, it looks we lost race with another request. As it's required to
3910- * handle metadata fusion and upload, the whole operation becomes very
3911- * similar in nature to PutMetadataBucket. However, as the attrs may
3912- * changed in the meantime, we have to refresh. */
3913- short tries = 0 ;
3914- do {
3915- map<string, bufferlist> battrs;
3916-
3917- op_ret = s->bucket ->load_bucket (this , y);
3918- if (op_ret < 0 ) {
3919- return ;
3920- } else if (!s->auth .identity ->is_owner_of (s->bucket ->get_owner ())) {
3921- /* New bucket doesn't belong to the account we're operating on. */
3922- op_ret = -EEXIST;
3923- return ;
3924- } else {
3925- s->bucket_attrs = s->bucket ->get_attrs ();
3926- }
3927-
3928- createparams.attrs .clear ();
3929-
3930- op_ret = rgw_get_request_metadata (this , s->cct , s->info , createparams.attrs , false );
3931- if (op_ret < 0 ) {
3932- return ;
3933- }
3934- prepare_add_del_attrs (s->bucket_attrs , rmattr_names, createparams.attrs );
3935- populate_with_generic_attrs (s, createparams.attrs );
3936- op_ret = filter_out_quota_info (createparams.attrs , rmattr_names,
3937- s->bucket ->get_info ().quota );
3938- if (op_ret < 0 ) {
3939- return ;
3940- }
3941-
3942- /* Handle updates of the metadata for Swift's object versioning. */
3943- if (createparams.swift_ver_location ) {
3944- s->bucket ->get_info ().swift_ver_location = *createparams.swift_ver_location ;
3945- s->bucket ->get_info ().swift_versioning = !createparams.swift_ver_location ->empty ();
3946- }
3947-
3948- /* Web site of Swift API. */
3949- filter_out_website (createparams.attrs , rmattr_names,
3950- s->bucket ->get_info ().website_conf );
3951- s->bucket ->get_info ().has_website = !s->bucket ->get_info ().website_conf .is_empty ();
3952-
3953- /* This will also set the quota on the bucket. */
3954- s->bucket ->set_attrs (std::move (createparams.attrs ));
3955- constexpr bool exclusive = false ; // overwrite
3956- constexpr ceph::real_time no_set_mtime{};
3957- op_ret = s->bucket ->put_info (this , exclusive, no_set_mtime, y);
3958- } while (op_ret == -ECANCELED && tries++ < 20 );
3959-
3960- /* Restore the proper return code. */
3961- if (op_ret >= 0 ) {
3962- op_ret = -ERR_BUCKET_EXISTS;
3963- }
3964- } /* if (need_metadata_upload() && existed) */
39653987} /* RGWCreateBucket::execute() */
39663988
39673989int RGWDeleteBucket::verify_permission (optional_yield y)
@@ -5316,71 +5338,15 @@ void RGWPutMetadataBucket::execute(optional_yield y)
53165338 if (op_ret < 0 ) {
53175339 return ;
53185340 }
5319-
5320- op_ret = rgw_get_request_metadata (this , s->cct , s->info , attrs, false );
5321- if (op_ret < 0 ) {
5322- return ;
5323- }
5324-
53255341 if (!placement_rule.empty () &&
53265342 placement_rule != s->bucket ->get_placement_rule ()) {
53275343 op_ret = -EEXIST;
53285344 return ;
53295345 }
53305346
5331- op_ret = retry_raced_bucket_write (this , s->bucket .get (), [this ] {
5332- /* Encode special metadata first as we're using std::map::emplace under
5333- * the hood. This method will add the new items only if the map doesn't
5334- * contain such keys yet. */
5335- if (has_policy) {
5336- if (s->dialect .compare (" swift" ) == 0 ) {
5337- rgw::swift::merge_policy (policy_rw_mask, s->bucket_acl , policy);
5338- }
5339- buffer::list bl;
5340- policy.encode (bl);
5341- emplace_attr (RGW_ATTR_ACL, std::move (bl));
5342- }
5343-
5344- if (has_cors) {
5345- buffer::list bl;
5346- cors_config.encode (bl);
5347- emplace_attr (RGW_ATTR_CORS, std::move (bl));
5348- }
5349-
5350- /* It's supposed that following functions WILL NOT change any
5351- * special attributes (like RGW_ATTR_ACL) if they are already
5352- * present in attrs. */
5353- prepare_add_del_attrs (s->bucket_attrs , rmattr_names, attrs);
5354- populate_with_generic_attrs (s, attrs);
5355-
5356- /* According to the Swift's behaviour and its container_quota
5357- * WSGI middleware implementation: anyone with write permissions
5358- * is able to set the bucket quota. This stays in contrast to
5359- * account quotas that can be set only by clients holding
5360- * reseller admin privileges. */
5361- op_ret = filter_out_quota_info (attrs, rmattr_names, s->bucket ->get_info ().quota );
5362- if (op_ret < 0 ) {
5363- return op_ret;
5364- }
5365-
5366- if (swift_ver_location) {
5367- s->bucket ->get_info ().swift_ver_location = *swift_ver_location;
5368- s->bucket ->get_info ().swift_versioning = (!swift_ver_location->empty ());
5369- }
5370-
5371- /* Web site of Swift API. */
5372- filter_out_website (attrs, rmattr_names, s->bucket ->get_info ().website_conf );
5373- s->bucket ->get_info ().has_website = !s->bucket ->get_info ().website_conf .is_empty ();
5374-
5375- /* Setting attributes also stores the provided bucket info. Due
5376- * to this fact, the new quota settings can be serialized with
5377- * the same call. */
5378- s->bucket ->set_attrs (attrs);
5379- constexpr bool exclusive = false ; // overwrite
5380- constexpr ceph::real_time no_set_mtime{};
5381- op_ret = s->bucket ->put_info (this , exclusive, no_set_mtime, s->yield );
5382- return op_ret;
5383- }, y);
5347+ op_ret = put_swift_bucket_metadata (this , s, policy, has_policy,
5348+ policy_rw_mask, cors_config, has_cors,
5349+ swift_ver_location, rmattr_names, y);
53845350}
53855351
53865352int RGWPutMetadataObject::verify_permission (optional_yield y)
0 commit comments