1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
5 * Ceph - scalable distributed file system
7 * Copyright (C) 2020 Red Hat, Inc.
9 * This is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License version 2.1, as published by the Free Software
12 * Foundation. See file COPYING.
18 #include <system_error>
22 #include "common/Clock.h"
23 #include "common/errno.h"
26 #include "rgw_sal_rados.h"
27 #include "rgw_bucket.h"
28 #include "rgw_multi.h"
29 #include "rgw_acl_s3.h"
31 #include "rgw_aio_throttle.h"
32 #include "rgw_tracer.h"
35 #include "rgw_rest_conn.h"
36 #include "rgw_service.h"
38 #include "services/svc_sys_obj.h"
39 #include "services/svc_zone.h"
40 #include "services/svc_tier_rados.h"
41 #include "services/svc_quota.h"
42 #include "services/svc_config_key.h"
43 #include "services/svc_zone_utils.h"
44 #include "cls/rgw/cls_rgw_client.h"
46 #include "rgw_pubsub.h"
48 #define dout_subsys ceph_subsys_rgw
52 static string mp_ns
= RGW_OBJ_NS_MULTIPART
;
56 // default number of entries to list with each bucket listing call
57 // (use marker to bridge between calls)
58 static constexpr size_t listing_max_entries
= 1000;
60 static int decode_policy(CephContext
* cct
,
62 RGWAccessControlPolicy
* policy
)
64 auto iter
= bl
.cbegin();
67 } catch (buffer::error
& err
) {
68 ldout(cct
, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl
;
71 if (cct
->_conf
->subsys
.should_gather
<ceph_subsys_rgw
, 15>()) {
72 ldout(cct
, 15) << __func__
<< " Read AccessControlPolicy";
73 RGWAccessControlPolicy_S3
* s3policy
= static_cast<RGWAccessControlPolicy_S3
*>(policy
);
74 s3policy
->to_xml(*_dout
);
80 static int rgw_op_get_bucket_policy_from_attr(const DoutPrefixProvider
* dpp
,
84 RGWAccessControlPolicy
* policy
,
87 auto aiter
= bucket_attrs
.find(RGW_ATTR_ACL
);
89 if (aiter
!= bucket_attrs
.end()) {
90 int ret
= decode_policy(store
->ctx(), aiter
->second
, policy
);
94 ldout(store
->ctx(), 0) << "WARNING: couldn't find acl header for bucket, generating default" << dendl
;
95 /* object exists, but policy is broken */
96 int r
= user
->load_user(dpp
, y
);
100 policy
->create_default(user
->get_id(), user
->get_display_name());
105 int RadosCompletions::drain()
108 while (!handles
.empty()) {
109 librados::AioCompletion
* handle
= handles
.front();
111 handle
->wait_for_complete();
112 int r
= handle
->get_return_value();
121 int RadosUser::list_buckets(const DoutPrefixProvider
* dpp
, const std::string
& marker
,
122 const std::string
& end_marker
, uint64_t max
, bool need_stats
,
123 BucketList
&buckets
, optional_yield y
)
125 RGWUserBuckets ulist
;
126 bool is_truncated
= false;
130 ret
= store
->ctl()->user
->list_buckets(dpp
, info
.user_id
, marker
, end_marker
, max
,
131 need_stats
, &ulist
, &is_truncated
, y
);
135 buckets
.set_truncated(is_truncated
);
136 for (const auto& ent
: ulist
.get_buckets()) {
137 buckets
.add(std::unique_ptr
<Bucket
>(new RadosBucket(this->store
, ent
.second
, this)));
143 int RadosUser::create_bucket(const DoutPrefixProvider
* dpp
,
145 const std::string
& zonegroup_id
,
146 rgw_placement_rule
& placement_rule
,
147 std::string
& swift_ver_location
,
148 const RGWQuotaInfo
* pquota_info
,
149 const RGWAccessControlPolicy
& policy
,
152 obj_version
& ep_objv
,
154 bool obj_lock_enabled
,
157 std::unique_ptr
<Bucket
>* bucket_out
,
162 RGWBucketInfo master_info
;
163 rgw_bucket
* pmaster_bucket
;
164 uint32_t* pmaster_num_shards
;
165 real_time creation_time
;
166 std::unique_ptr
<Bucket
> bucket
;
167 obj_version objv
,* pobjv
= NULL
;
169 /* If it exists, look it up; otherwise create it */
170 ret
= store
->get_bucket(dpp
, this, b
, &bucket
, y
);
171 if (ret
< 0 && ret
!= -ENOENT
)
174 if (ret
!= -ENOENT
) {
175 RGWAccessControlPolicy
old_policy(store
->ctx());
177 if (swift_ver_location
.empty()) {
178 swift_ver_location
= bucket
->get_info().swift_ver_location
;
180 placement_rule
.inherit_from(bucket
->get_info().placement_rule
);
182 // don't allow changes to the acl policy
183 int r
= rgw_op_get_bucket_policy_from_attr(dpp
, store
, this, bucket
->get_attrs(),
185 if (r
>= 0 && old_policy
!= policy
) {
186 bucket_out
->swap(bucket
);
190 bucket
= std::unique_ptr
<Bucket
>(new RadosBucket(store
, b
, this));
192 bucket
->set_attrs(attrs
);
195 if (!store
->svc()->zone
->is_meta_master()) {
197 ret
= store
->forward_request_to_master(dpp
, this, NULL
, in_data
, &jp
, req_info
, y
);
202 JSONDecoder::decode_json("entry_point_object_ver", ep_objv
, &jp
);
203 JSONDecoder::decode_json("object_ver", objv
, &jp
);
204 JSONDecoder::decode_json("bucket_info", master_info
, &jp
);
205 ldpp_dout(dpp
, 20) << "parsed: objv.tag=" << objv
.tag
<< " objv.ver=" << objv
.ver
<< dendl
;
206 std::time_t ctime
= ceph::real_clock::to_time_t(master_info
.creation_time
);
207 ldpp_dout(dpp
, 20) << "got creation time: << " << std::put_time(std::localtime(&ctime
), "%F %T") << dendl
;
208 pmaster_bucket
= &master_info
.bucket
;
209 creation_time
= master_info
.creation_time
;
210 pmaster_num_shards
= &master_info
.layout
.current_index
.layout
.normal
.num_shards
;
212 if (master_info
.obj_lock_enabled()) {
213 info
.flags
= BUCKET_VERSIONED
| BUCKET_OBJ_LOCK_ENABLED
;
216 pmaster_bucket
= NULL
;
217 pmaster_num_shards
= NULL
;
218 if (obj_lock_enabled
)
219 info
.flags
= BUCKET_VERSIONED
| BUCKET_OBJ_LOCK_ENABLED
;
222 std::string zid
= zonegroup_id
;
224 zid
= store
->svc()->zone
->get_zonegroup().get_id();
228 rgw_placement_rule selected_placement_rule
;
229 ret
= store
->svc()->zone
->select_bucket_placement(dpp
, this->get_info(),
231 &selected_placement_rule
, nullptr, y
);
232 if (selected_placement_rule
!= info
.placement_rule
) {
234 bucket_out
->swap(bucket
);
239 ret
= store
->getRados()->create_bucket(this->get_info(), bucket
->get_key(),
240 zid
, placement_rule
, swift_ver_location
, pquota_info
,
241 attrs
, info
, pobjv
, &ep_objv
, creation_time
,
242 pmaster_bucket
, pmaster_num_shards
, y
, dpp
,
244 if (ret
== -EEXIST
) {
246 /* bucket already existed, might have raced with another bucket creation,
247 * or might be partial bucket creation that never completed. Read existing
248 * bucket info, verify that the reported bucket owner is the current user.
249 * If all is ok then update the user's list of buckets. Otherwise inform
250 * client about a name conflict.
252 if (info
.owner
.compare(this->get_id()) != 0) {
256 } else if (ret
!= 0) {
261 bucket
->set_version(ep_objv
);
262 bucket
->get_info() = info
;
264 RadosBucket
* rbucket
= static_cast<RadosBucket
*>(bucket
.get());
265 ret
= rbucket
->link(dpp
, this, y
, false);
266 if (ret
&& !*existed
&& ret
!= -EEXIST
) {
267 /* if it exists (or previously existed), don't remove it! */
268 ret
= rbucket
->unlink(dpp
, this, y
);
270 ldpp_dout(dpp
, 0) << "WARNING: failed to unlink bucket: ret=" << ret
273 } else if (ret
== -EEXIST
|| (ret
== 0 && *existed
)) {
274 ret
= -ERR_BUCKET_EXISTS
;
277 bucket_out
->swap(bucket
);
282 int RadosUser::read_attrs(const DoutPrefixProvider
* dpp
, optional_yield y
)
284 return store
->ctl()->user
->get_attrs_by_uid(dpp
, get_id(), &attrs
, y
, &objv_tracker
);
287 int RadosUser::merge_and_store_attrs(const DoutPrefixProvider
* dpp
, Attrs
& new_attrs
, optional_yield y
)
289 for(auto& it
: new_attrs
) {
290 attrs
[it
.first
] = it
.second
;
292 return store_user(dpp
, y
, false);
295 int RadosUser::read_stats(const DoutPrefixProvider
*dpp
,
296 optional_yield y
, RGWStorageStats
* stats
,
297 ceph::real_time
* last_stats_sync
,
298 ceph::real_time
* last_stats_update
)
300 return store
->ctl()->user
->read_stats(dpp
, get_id(), stats
, y
, last_stats_sync
, last_stats_update
);
303 int RadosUser::read_stats_async(const DoutPrefixProvider
*dpp
, RGWGetUserStats_CB
* cb
)
305 return store
->ctl()->user
->read_stats_async(dpp
, get_id(), cb
);
308 int RadosUser::complete_flush_stats(const DoutPrefixProvider
*dpp
, optional_yield y
)
310 return store
->ctl()->user
->complete_flush_stats(dpp
, get_id(), y
);
313 int RadosUser::read_usage(const DoutPrefixProvider
*dpp
, uint64_t start_epoch
, uint64_t end_epoch
,
314 uint32_t max_entries
, bool* is_truncated
,
315 RGWUsageIter
& usage_iter
,
316 map
<rgw_user_bucket
, rgw_usage_log_entry
>& usage
)
318 std::string bucket_name
;
319 return store
->getRados()->read_usage(dpp
, get_id(), bucket_name
, start_epoch
,
320 end_epoch
, max_entries
, is_truncated
,
324 int RadosUser::trim_usage(const DoutPrefixProvider
*dpp
, uint64_t start_epoch
, uint64_t end_epoch
)
326 std::string bucket_name
;
328 return store
->getRados()->trim_usage(dpp
, get_id(), bucket_name
, start_epoch
, end_epoch
);
331 int RadosUser::load_user(const DoutPrefixProvider
* dpp
, optional_yield y
)
333 return store
->ctl()->user
->get_info_by_uid(dpp
, info
.user_id
, &info
, y
, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker
).set_attrs(&attrs
));
336 int RadosUser::store_user(const DoutPrefixProvider
* dpp
, optional_yield y
, bool exclusive
, RGWUserInfo
* old_info
)
338 return store
->ctl()->user
->store_info(dpp
, info
, y
,
339 RGWUserCtl::PutParams().set_objv_tracker(&objv_tracker
)
340 .set_exclusive(exclusive
)
342 .set_old_info(old_info
));
345 int RadosUser::remove_user(const DoutPrefixProvider
* dpp
, optional_yield y
)
347 return store
->ctl()->user
->remove_info(dpp
, info
, y
,
348 RGWUserCtl::RemoveParams().set_objv_tracker(&objv_tracker
));
351 RadosBucket::~RadosBucket() {}
353 int RadosBucket::remove_bucket(const DoutPrefixProvider
* dpp
,
354 bool delete_children
,
355 bool forward_to_master
,
362 ret
= load_bucket(dpp
, y
);
368 params
.list_versions
= true;
369 params
.allow_unordered
= true;
374 results
.objs
.clear();
376 ret
= list(dpp
, params
, 1000, results
, y
);
381 if (!results
.objs
.empty() && !delete_children
) {
382 ldpp_dout(dpp
, -1) << "ERROR: could not remove non-empty bucket " << info
.bucket
.name
<<
387 for (const auto& obj
: results
.objs
) {
388 rgw_obj_key
key(obj
.key
);
390 ret
= rgw_remove_object(dpp
, store
, this, key
);
391 if (ret
< 0 && ret
!= -ENOENT
) {
395 } while(results
.is_truncated
);
397 ret
= abort_multiparts(dpp
, store
->ctx());
402 // remove lifecycle config, if any (XXX note could be made generic)
403 (void) store
->getRados()->get_lc()->remove_bucket_config(
406 ret
= store
->ctl()->bucket
->sync_user_stats(dpp
, info
.owner
, info
, y
, nullptr);
408 ldout(store
->ctx(), 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret
<< dendl
;
411 RGWObjVersionTracker ot
;
413 // if we deleted children above we will force delete, as any that
414 // remain is detrius from a prior bug
415 ret
= store
->getRados()->delete_bucket(info
, ot
, y
, dpp
, !delete_children
);
417 ldpp_dout(dpp
, -1) << "ERROR: could not remove bucket " <<
418 info
.bucket
.name
<< dendl
;
422 // if bucket has notification definitions associated with it
423 // they should be removed (note that any pending notifications on the bucket are still going to be sent)
424 RGWPubSub
ps(store
, info
.owner
.tenant
);
425 RGWPubSub::Bucket
ps_bucket(&ps
, info
.bucket
);
426 const auto ps_ret
= ps_bucket
.remove_notifications(dpp
, y
);
427 if (ps_ret
< 0 && ps_ret
!= -ENOENT
) {
428 ldpp_dout(dpp
, -1) << "ERROR: unable to remove notifications from bucket. ret=" << ps_ret
<< dendl
;
431 ret
= store
->ctl()->bucket
->unlink_bucket(info
.owner
, info
.bucket
, y
, dpp
, false);
433 ldpp_dout(dpp
, -1) << "ERROR: unable to remove user bucket information" << dendl
;
436 if (forward_to_master
) {
438 ret
= store
->forward_request_to_master(dpp
, owner
, &ot
.read_version
, in_data
, nullptr, *req_info
, y
);
440 if (ret
== -ENOENT
) {
441 /* adjust error, we want to return with NoSuchBucket and not
443 ret
= -ERR_NO_SUCH_BUCKET
;
452 int RadosBucket::remove_bucket_bypass_gc(int concurrent_max
, bool
453 keep_index_consistent
,
454 optional_yield y
, const
455 DoutPrefixProvider
*dpp
)
458 map
<RGWObjCategory
, RGWStorageStats
> stats
;
459 map
<string
, bool> common_prefixes
;
460 RGWObjectCtx
obj_ctx(store
);
461 CephContext
*cct
= store
->ctx();
463 string bucket_ver
, master_ver
;
465 ret
= load_bucket(dpp
, null_yield
);
469 ret
= read_stats(dpp
, RGW_NO_SHARD
, &bucket_ver
, &master_ver
, stats
, NULL
);
473 ret
= abort_multiparts(dpp
, cct
);
478 rgw::sal::Bucket::ListParams params
;
479 rgw::sal::Bucket::ListResults results
;
481 params
.list_versions
= true;
482 params
.allow_unordered
= true;
484 std::unique_ptr
<rgw::sal::Completions
> handles
= store
->get_completions();
486 int max_aio
= concurrent_max
;
487 results
.is_truncated
= true;
489 while (results
.is_truncated
) {
490 ret
= list(dpp
, params
, listing_max_entries
, results
, null_yield
);
494 std::vector
<rgw_bucket_dir_entry
>::iterator it
= results
.objs
.begin();
495 for (; it
!= results
.objs
.end(); ++it
) {
496 RGWObjState
*astate
= NULL
;
497 std::unique_ptr
<rgw::sal::Object
> obj
= get_object((*it
).key
);
499 ret
= obj
->get_obj_state(dpp
, &obj_ctx
, &astate
, y
, false);
500 if (ret
== -ENOENT
) {
501 ldpp_dout(dpp
, 1) << "WARNING: cannot find obj state for obj " << obj
<< dendl
;
505 ldpp_dout(dpp
, -1) << "ERROR: get obj state returned with error " << ret
<< dendl
;
509 if (astate
->manifest
) {
510 RGWObjManifest
& manifest
= *astate
->manifest
;
511 RGWObjManifest::obj_iterator miter
= manifest
.obj_begin(dpp
);
512 std::unique_ptr
<rgw::sal::Object
> head_obj
= get_object(manifest
.get_obj().key
);
513 rgw_raw_obj raw_head_obj
;
514 dynamic_cast<RadosObject
*>(head_obj
.get())->get_raw_obj(&raw_head_obj
);
516 for (; miter
!= manifest
.obj_end(dpp
) && max_aio
--; ++miter
) {
518 ret
= handles
->drain();
520 ldpp_dout(dpp
, -1) << "ERROR: could not drain handles as aio completion returned with " << ret
<< dendl
;
523 max_aio
= concurrent_max
;
526 rgw_raw_obj last_obj
= miter
.get_location().get_raw_obj(store
);
527 if (last_obj
== raw_head_obj
) {
528 // have the head obj deleted at the end
532 ret
= store
->delete_raw_obj_aio(dpp
, last_obj
, handles
.get());
534 ldpp_dout(dpp
, -1) << "ERROR: delete obj aio failed with " << ret
<< dendl
;
537 } // for all shadow objs
539 ret
= head_obj
->delete_obj_aio(dpp
, astate
, handles
.get(), keep_index_consistent
, null_yield
);
541 ldpp_dout(dpp
, -1) << "ERROR: delete obj aio failed with " << ret
<< dendl
;
547 ret
= handles
->drain();
549 ldpp_dout(dpp
, -1) << "ERROR: could not drain handles as aio completion returned with " << ret
<< dendl
;
552 max_aio
= concurrent_max
;
554 obj_ctx
.invalidate(obj
->get_obj());
555 } // for all RGW objects in results
556 } // while is_truncated
558 ret
= handles
->drain();
560 ldpp_dout(dpp
, -1) << "ERROR: could not drain handles as aio completion returned with " << ret
<< dendl
;
564 sync_user_stats(dpp
, y
);
566 ldpp_dout(dpp
, 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret
<< dendl
;
569 RGWObjVersionTracker objv_tracker
;
571 // this function can only be run if caller wanted children to be
572 // deleted, so we can ignore the check for children as any that
573 // remain are detritus from a prior bug
574 ret
= remove_bucket(dpp
, true, false, nullptr, y
);
576 ldpp_dout(dpp
, -1) << "ERROR: could not remove bucket " << this << dendl
;
583 int RadosBucket::load_bucket(const DoutPrefixProvider
* dpp
, optional_yield y
, bool get_stats
)
585 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
588 RGWSI_MetaBackend_CtxParams bectx_params
= RGWSI_MetaBackend_CtxParams_SObj(&obj_ctx
);
589 RGWObjVersionTracker ep_ot
;
590 if (info
.bucket
.bucket_id
.empty()) {
591 ret
= store
->ctl()->bucket
->read_bucket_info(info
.bucket
, &info
, y
, dpp
,
592 RGWBucketCtl::BucketInstance::GetParams()
595 .set_bectx_params(bectx_params
),
598 ret
= store
->ctl()->bucket
->read_bucket_instance_info(info
.bucket
, &info
, y
, dpp
,
599 RGWBucketCtl::BucketInstance::GetParams()
602 .set_bectx_params(bectx_params
));
608 bucket_version
= ep_ot
.read_version
;
611 ret
= store
->ctl()->bucket
->read_bucket_stats(info
.bucket
, &ent
, y
, dpp
);
617 int RadosBucket::read_stats(const DoutPrefixProvider
*dpp
, int shard_id
,
618 std::string
* bucket_ver
, std::string
* master_ver
,
619 std::map
<RGWObjCategory
, RGWStorageStats
>& stats
,
620 std::string
* max_marker
, bool* syncstopped
)
622 return store
->getRados()->get_bucket_stats(dpp
, info
, shard_id
, bucket_ver
, master_ver
, stats
, max_marker
, syncstopped
);
625 int RadosBucket::read_stats_async(const DoutPrefixProvider
*dpp
, int shard_id
, RGWGetBucketStats_CB
* ctx
)
627 return store
->getRados()->get_bucket_stats_async(dpp
, get_info(), shard_id
, ctx
);
630 int RadosBucket::sync_user_stats(const DoutPrefixProvider
*dpp
, optional_yield y
)
632 return store
->ctl()->bucket
->sync_user_stats(dpp
, owner
->get_id(), info
, y
, &ent
);
635 int RadosBucket::update_container_stats(const DoutPrefixProvider
* dpp
)
638 map
<std::string
, RGWBucketEnt
> m
;
640 m
[info
.bucket
.name
] = ent
;
641 ret
= store
->getRados()->update_containers_stats(m
, dpp
);
647 map
<std::string
, RGWBucketEnt
>::iterator iter
= m
.find(info
.bucket
.name
);
651 ent
.count
= iter
->second
.count
;
652 ent
.size
= iter
->second
.size
;
653 ent
.size_rounded
= iter
->second
.size_rounded
;
654 ent
.creation_time
= iter
->second
.creation_time
;
655 ent
.placement_rule
= std::move(iter
->second
.placement_rule
);
657 info
.creation_time
= ent
.creation_time
;
658 info
.placement_rule
= ent
.placement_rule
;
663 int RadosBucket::check_bucket_shards(const DoutPrefixProvider
* dpp
)
665 return store
->getRados()->check_bucket_shards(info
, info
.bucket
, get_count(), dpp
);
668 int RadosBucket::link(const DoutPrefixProvider
* dpp
, User
* new_user
, optional_yield y
, bool update_entrypoint
, RGWObjVersionTracker
* objv
)
670 RGWBucketEntryPoint ep
;
671 ep
.bucket
= info
.bucket
;
672 ep
.owner
= new_user
->get_id();
673 ep
.creation_time
= get_creation_time();
676 rgw_ep_info ep_data
{ep
, ep_attrs
};
678 int r
= store
->ctl()->bucket
->link_bucket(new_user
->get_id(), info
.bucket
,
679 get_creation_time(), y
, dpp
, update_entrypoint
,
685 *objv
= ep_data
.ep_objv
;
690 int RadosBucket::unlink(const DoutPrefixProvider
* dpp
, User
* new_user
, optional_yield y
, bool update_entrypoint
)
692 return store
->ctl()->bucket
->unlink_bucket(new_user
->get_id(), info
.bucket
, y
, dpp
, update_entrypoint
);
695 int RadosBucket::chown(const DoutPrefixProvider
* dpp
, User
* new_user
, User
* old_user
, optional_yield y
, const std::string
* marker
)
697 std::string obj_marker
;
699 if (marker
== nullptr)
700 marker
= &obj_marker
;
702 int r
= this->link(dpp
, new_user
, y
);
710 return store
->ctl()->bucket
->chown(store
, this, new_user
->get_id(),
711 old_user
->get_display_name(), *marker
, y
, dpp
);
714 int RadosBucket::put_info(const DoutPrefixProvider
* dpp
, bool exclusive
, ceph::real_time _mtime
)
717 return store
->getRados()->put_bucket_instance_info(info
, exclusive
, mtime
, &attrs
, dpp
);
720 /* Make sure to call get_bucket_info() if you need it first */
721 bool RadosBucket::is_owner(User
* user
)
723 return (info
.owner
.compare(user
->get_id()) == 0);
726 int RadosBucket::check_empty(const DoutPrefixProvider
* dpp
, optional_yield y
)
728 return store
->getRados()->check_bucket_empty(dpp
, info
, y
);
731 int RadosBucket::check_quota(const DoutPrefixProvider
*dpp
, RGWQuotaInfo
& user_quota
, RGWQuotaInfo
& bucket_quota
, uint64_t obj_size
,
732 optional_yield y
, bool check_size_only
)
734 return store
->getRados()->check_quota(dpp
, owner
->get_id(), get_key(),
735 user_quota
, bucket_quota
, obj_size
, y
, check_size_only
);
738 int RadosBucket::merge_and_store_attrs(const DoutPrefixProvider
* dpp
, Attrs
& new_attrs
, optional_yield y
)
740 for(auto& it
: new_attrs
) {
741 attrs
[it
.first
] = it
.second
;
743 return store
->ctl()->bucket
->set_bucket_instance_attrs(get_info(),
744 new_attrs
, &get_info().objv_tracker
, y
, dpp
);
747 int RadosBucket::try_refresh_info(const DoutPrefixProvider
* dpp
, ceph::real_time
* pmtime
)
749 return store
->getRados()->try_refresh_bucket_info(info
, pmtime
, dpp
, &attrs
);
752 int RadosBucket::read_usage(const DoutPrefixProvider
*dpp
, uint64_t start_epoch
, uint64_t end_epoch
,
753 uint32_t max_entries
, bool* is_truncated
,
754 RGWUsageIter
& usage_iter
,
755 map
<rgw_user_bucket
, rgw_usage_log_entry
>& usage
)
757 return store
->getRados()->read_usage(dpp
, owner
->get_id(), get_name(), start_epoch
,
758 end_epoch
, max_entries
, is_truncated
,
762 int RadosBucket::trim_usage(const DoutPrefixProvider
*dpp
, uint64_t start_epoch
, uint64_t end_epoch
)
764 return store
->getRados()->trim_usage(dpp
, owner
->get_id(), get_name(), start_epoch
, end_epoch
);
767 int RadosBucket::remove_objs_from_index(const DoutPrefixProvider
*dpp
, std::list
<rgw_obj_index_key
>& objs_to_unlink
)
769 return store
->getRados()->remove_objs_from_index(dpp
, info
, objs_to_unlink
);
772 int RadosBucket::check_index(const DoutPrefixProvider
*dpp
, std::map
<RGWObjCategory
, RGWStorageStats
>& existing_stats
, std::map
<RGWObjCategory
, RGWStorageStats
>& calculated_stats
)
774 return store
->getRados()->bucket_check_index(dpp
, info
, &existing_stats
, &calculated_stats
);
777 int RadosBucket::rebuild_index(const DoutPrefixProvider
*dpp
)
779 return store
->getRados()->bucket_rebuild_index(dpp
, info
);
782 int RadosBucket::set_tag_timeout(const DoutPrefixProvider
*dpp
, uint64_t timeout
)
784 return store
->getRados()->cls_obj_set_bucket_tag_timeout(dpp
, info
, timeout
);
787 int RadosBucket::purge_instance(const DoutPrefixProvider
* dpp
)
789 int max_shards
= (info
.layout
.current_index
.layout
.normal
.num_shards
> 0 ? info
.layout
.current_index
.layout
.normal
.num_shards
: 1);
790 for (int i
= 0; i
< max_shards
; i
++) {
791 RGWRados::BucketShard
bs(store
->getRados());
792 int shard_id
= (info
.layout
.current_index
.layout
.normal
.num_shards
> 0 ? i
: -1);
793 int ret
= bs
.init(info
.bucket
, shard_id
, info
.layout
.current_index
, nullptr, dpp
);
795 cerr
<< "ERROR: bs.init(bucket=" << info
.bucket
<< ", shard=" << shard_id
796 << "): " << cpp_strerror(-ret
) << std::endl
;
799 ret
= store
->getRados()->bi_remove(dpp
, bs
);
801 cerr
<< "ERROR: failed to remove bucket index object: "
802 << cpp_strerror(-ret
) << std::endl
;
809 int RadosBucket::set_acl(const DoutPrefixProvider
* dpp
, RGWAccessControlPolicy
&acl
, optional_yield y
)
815 map
<string
, bufferlist
>& attrs
= get_attrs();
817 attrs
[RGW_ATTR_ACL
] = aclbl
;
818 info
.owner
= acl
.get_owner().get_id();
820 int r
= store
->ctl()->bucket
->store_bucket_instance_info(info
.bucket
,
822 RGWBucketCtl::BucketInstance::PutParams().set_attrs(&attrs
));
824 cerr
<< "ERROR: failed to set bucket owner: " << cpp_strerror(-r
) << std::endl
;
831 std::unique_ptr
<Object
> RadosBucket::get_object(const rgw_obj_key
& k
)
833 return std::make_unique
<RadosObject
>(this->store
, k
, this);
836 int RadosBucket::list(const DoutPrefixProvider
* dpp
, ListParams
& params
, int max
, ListResults
& results
, optional_yield y
)
838 RGWRados::Bucket
target(store
->getRados(), get_info());
839 if (params
.shard_id
>= 0) {
840 target
.set_shard_id(params
.shard_id
);
842 RGWRados::Bucket::List
list_op(&target
);
844 list_op
.params
.prefix
= params
.prefix
;
845 list_op
.params
.delim
= params
.delim
;
846 list_op
.params
.marker
= params
.marker
;
847 list_op
.params
.ns
= params
.ns
;
848 list_op
.params
.end_marker
= params
.end_marker
;
849 list_op
.params
.ns
= params
.ns
;
850 list_op
.params
.enforce_ns
= params
.enforce_ns
;
851 list_op
.params
.access_list_filter
= params
.access_list_filter
;
852 list_op
.params
.force_check_filter
= params
.force_check_filter
;
853 list_op
.params
.list_versions
= params
.list_versions
;
854 list_op
.params
.allow_unordered
= params
.allow_unordered
;
856 int ret
= list_op
.list_objects(dpp
, max
, &results
.objs
, &results
.common_prefixes
, &results
.is_truncated
, y
);
858 results
.next_marker
= list_op
.get_next_marker();
859 params
.marker
= results
.next_marker
;
865 std::unique_ptr
<MultipartUpload
> RadosBucket::get_multipart_upload(
866 const std::string
& oid
,
867 std::optional
<std::string
> upload_id
,
868 ACLOwner owner
, ceph::real_time mtime
)
870 return std::make_unique
<RadosMultipartUpload
>(this->store
, this, oid
, upload_id
,
871 std::move(owner
), mtime
);
874 int RadosBucket::list_multiparts(const DoutPrefixProvider
*dpp
,
875 const string
& prefix
,
878 const int& max_uploads
,
879 vector
<std::unique_ptr
<MultipartUpload
>>& uploads
,
880 map
<string
, bool> *common_prefixes
,
883 rgw::sal::Bucket::ListParams params
;
884 rgw::sal::Bucket::ListResults results
;
885 MultipartMetaFilter mp_filter
;
887 params
.prefix
= prefix
;
888 params
.delim
= delim
;
889 params
.marker
= marker
;
890 params
.ns
= RGW_OBJ_NS_MULTIPART
;
891 params
.access_list_filter
= &mp_filter
;
893 int ret
= list(dpp
, params
, max_uploads
, results
, null_yield
);
898 if (!results
.objs
.empty()) {
899 for (const rgw_bucket_dir_entry
& dentry
: results
.objs
) {
900 rgw_obj_key
key(dentry
.key
);
901 ACLOwner
owner(rgw_user(dentry
.meta
.owner
));
902 owner
.set_name(dentry
.meta
.owner_display_name
);
903 uploads
.push_back(this->get_multipart_upload(key
.name
,
904 std::nullopt
, std::move(owner
)));
907 if (common_prefixes
) {
908 *common_prefixes
= std::move(results
.common_prefixes
);
910 *is_truncated
= results
.is_truncated
;
911 marker
= params
.marker
.name
;
916 int RadosBucket::abort_multiparts(const DoutPrefixProvider
* dpp
,
919 constexpr int max
= 1000;
920 int ret
, num_deleted
= 0;
921 vector
<std::unique_ptr
<MultipartUpload
>> uploads
;
922 RGWObjectCtx
obj_ctx(store
);
926 const std::string empty_delim
;
927 const std::string empty_prefix
;
930 ret
= list_multiparts(dpp
, empty_prefix
, marker
, empty_delim
,
931 max
, uploads
, nullptr, &is_truncated
);
933 ldpp_dout(dpp
, 0) << __func__
<<
934 " ERROR : calling list_bucket_multiparts; ret=" << ret
<<
935 "; bucket=\"" << this << "\"" << dendl
;
938 ldpp_dout(dpp
, 20) << __func__
<<
939 " INFO: aborting and cleaning up multipart upload(s); bucket=\"" <<
940 this << "\"; uploads.size()=" << uploads
.size() <<
941 "; is_truncated=" << is_truncated
<< dendl
;
943 if (!uploads
.empty()) {
944 for (const auto& upload
: uploads
) {
945 ret
= upload
->abort(dpp
, cct
, &obj_ctx
);
947 // we're doing a best-effort; if something cannot be found,
948 // log it and keep moving forward
949 if (ret
!= -ENOENT
&& ret
!= -ERR_NO_SUCH_UPLOAD
) {
950 ldpp_dout(dpp
, 0) << __func__
<<
951 " ERROR : failed to abort and clean-up multipart upload \"" <<
952 upload
->get_meta() << "\"" << dendl
;
955 ldpp_dout(dpp
, 10) << __func__
<<
956 " NOTE : unable to find part(s) of "
957 "aborted multipart upload of \"" << upload
->get_meta() <<
958 "\" for cleaning up" << dendl
;
964 ldpp_dout(dpp
, 0) << __func__
<<
965 " WARNING : aborted " << num_deleted
<<
966 " incomplete multipart uploads" << dendl
;
969 } while (is_truncated
);
974 std::unique_ptr
<User
> RadosStore::get_user(const rgw_user
&u
)
976 return std::make_unique
<RadosUser
>(this, u
);
979 std::string
RadosStore::get_cluster_id(const DoutPrefixProvider
* dpp
, optional_yield y
)
981 return getRados()->get_cluster_fsid(dpp
, y
);
984 int RadosStore::get_user_by_access_key(const DoutPrefixProvider
* dpp
, const std::string
& key
, optional_yield y
, std::unique_ptr
<User
>* user
)
988 RGWObjVersionTracker objv_tracker
;
990 int r
= ctl()->user
->get_info_by_access_key(dpp
, key
, &uinfo
, y
, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker
));
994 u
= new RadosUser(this, uinfo
);
998 u
->get_version_tracker() = objv_tracker
;
1004 int RadosStore::get_user_by_email(const DoutPrefixProvider
* dpp
, const std::string
& email
, optional_yield y
, std::unique_ptr
<User
>* user
)
1008 RGWObjVersionTracker objv_tracker
;
1010 int r
= ctl()->user
->get_info_by_email(dpp
, email
, &uinfo
, y
, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker
));
1014 u
= new RadosUser(this, uinfo
);
1018 u
->get_version_tracker() = objv_tracker
;
1024 int RadosStore::get_user_by_swift(const DoutPrefixProvider
* dpp
, const std::string
& user_str
, optional_yield y
, std::unique_ptr
<User
>* user
)
1028 RGWObjVersionTracker objv_tracker
;
1030 int r
= ctl()->user
->get_info_by_swift(dpp
, user_str
, &uinfo
, y
, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker
));
1034 u
= new RadosUser(this, uinfo
);
1038 u
->get_version_tracker() = objv_tracker
;
1044 std::unique_ptr
<Object
> RadosStore::get_object(const rgw_obj_key
& k
)
1046 return std::make_unique
<RadosObject
>(this, k
);
1049 int RadosStore::get_bucket(const DoutPrefixProvider
* dpp
, User
* u
, const rgw_bucket
& b
, std::unique_ptr
<Bucket
>* bucket
, optional_yield y
)
1054 bp
= new RadosBucket(this, b
, u
);
1055 ret
= bp
->load_bucket(dpp
, y
);
1065 int RadosStore::get_bucket(User
* u
, const RGWBucketInfo
& i
, std::unique_ptr
<Bucket
>* bucket
)
1069 bp
= new RadosBucket(this, i
, u
);
1070 /* Don't need to fetch the bucket info, use the provided one */
1076 int RadosStore::get_bucket(const DoutPrefixProvider
* dpp
, User
* u
, const std::string
& tenant
, const std::string
& name
, std::unique_ptr
<Bucket
>* bucket
, optional_yield y
)
1083 return get_bucket(dpp
, u
, b
, bucket
, y
);
1086 bool RadosStore::is_meta_master()
1088 return svc()->zone
->is_meta_master();
1091 int RadosStore::forward_request_to_master(const DoutPrefixProvider
*dpp
, User
* user
, obj_version
* objv
,
1092 bufferlist
& in_data
,
1093 JSONParser
* jp
, req_info
& info
,
1096 if (is_meta_master()) {
1097 /* We're master, don't forward */
1101 if (!svc()->zone
->get_master_conn()) {
1102 ldpp_dout(dpp
, 0) << "rest connection is invalid" << dendl
;
1105 ldpp_dout(dpp
, 0) << "sending request to master zonegroup" << dendl
;
1106 bufferlist response
;
1107 std::string uid_str
= user
->get_id().to_str();
1108 #define MAX_REST_RESPONSE (128 * 1024) // we expect a very small response
1109 int ret
= svc()->zone
->get_master_conn()->forward(dpp
, rgw_user(uid_str
), info
,
1110 objv
, MAX_REST_RESPONSE
,
1111 &in_data
, &response
, y
);
1115 ldpp_dout(dpp
, 20) << "response: " << response
.c_str() << dendl
;
1116 if (jp
&& !jp
->parse(response
.c_str(), response
.length())) {
1117 ldpp_dout(dpp
, 0) << "failed parsing response from master zonegroup" << dendl
;
1124 std::string
RadosStore::zone_unique_id(uint64_t unique_num
)
1126 return svc()->zone_utils
->unique_id(unique_num
);
1129 std::string
RadosStore::zone_unique_trans_id(const uint64_t unique_num
)
1131 return svc()->zone_utils
->unique_trans_id(unique_num
);
1134 int RadosStore::cluster_stat(RGWClusterStat
& stats
)
1136 rados_cluster_stat_t rados_stats
;
1139 ret
= rados
->get_rados_handle()->cluster_stat(rados_stats
);
1143 stats
.kb
= rados_stats
.kb
;
1144 stats
.kb_used
= rados_stats
.kb_used
;
1145 stats
.kb_avail
= rados_stats
.kb_avail
;
1146 stats
.num_objects
= rados_stats
.num_objects
;
1151 std::unique_ptr
<Lifecycle
> RadosStore::get_lifecycle(void)
1153 return std::make_unique
<RadosLifecycle
>(this);
1156 std::unique_ptr
<Completions
> RadosStore::get_completions(void)
1158 return std::make_unique
<RadosCompletions
>();
1161 std::unique_ptr
<Notification
> RadosStore::get_notification(
1162 rgw::sal::Object
* obj
, rgw::sal::Object
* src_obj
, struct req_state
* s
, rgw::notify::EventType event_type
, const std::string
* object_name
)
1164 return std::make_unique
<RadosNotification
>(s
, this, obj
, src_obj
, s
, event_type
, object_name
);
1167 std::unique_ptr
<Notification
> RadosStore::get_notification(const DoutPrefixProvider
* dpp
, rgw::sal::Object
* obj
, rgw::sal::Object
* src_obj
, RGWObjectCtx
* rctx
, rgw::notify::EventType event_type
, rgw::sal::Bucket
* _bucket
, std::string
& _user_id
, std::string
& _user_tenant
, std::string
& _req_id
, optional_yield y
)
1169 return std::make_unique
<RadosNotification
>(dpp
, this, obj
, src_obj
, rctx
, event_type
, _bucket
, _user_id
, _user_tenant
, _req_id
, y
);
1172 int RadosStore::delete_raw_obj(const DoutPrefixProvider
*dpp
, const rgw_raw_obj
& obj
)
1174 return rados
->delete_raw_obj(dpp
, obj
);
1177 int RadosStore::delete_raw_obj_aio(const DoutPrefixProvider
*dpp
, const rgw_raw_obj
& obj
, Completions
* aio
)
1179 RadosCompletions
* raio
= static_cast<RadosCompletions
*>(aio
);
1181 return rados
->delete_raw_obj_aio(dpp
, obj
, raio
->handles
);
1184 void RadosStore::get_raw_obj(const rgw_placement_rule
& placement_rule
, const rgw_obj
& obj
, rgw_raw_obj
* raw_obj
)
1186 rados
->obj_to_raw(placement_rule
, obj
, raw_obj
);
1189 int RadosStore::get_raw_chunk_size(const DoutPrefixProvider
* dpp
, const rgw_raw_obj
& obj
, uint64_t* chunk_size
)
1191 return rados
->get_max_chunk_size(obj
.pool
, chunk_size
, dpp
);
1194 int RadosStore::log_usage(const DoutPrefixProvider
*dpp
, map
<rgw_user_bucket
, RGWUsageBatch
>& usage_info
)
1196 return rados
->log_usage(dpp
, usage_info
);
1199 int RadosStore::log_op(const DoutPrefixProvider
*dpp
, std::string
& oid
, bufferlist
& bl
)
1201 rgw_raw_obj
obj(svc()->zone
->get_zone_params().log_pool
, oid
);
1203 int ret
= rados
->append_async(dpp
, obj
, bl
.length(), bl
);
1204 if (ret
== -ENOENT
) {
1205 ret
= rados
->create_pool(dpp
, svc()->zone
->get_zone_params().log_pool
);
1209 ret
= rados
->append_async(dpp
, obj
, bl
.length(), bl
);
1215 int RadosStore::register_to_service_map(const DoutPrefixProvider
*dpp
, const std::string
& daemon_type
,
1216 const map
<std::string
, std::string
>& meta
)
1218 return rados
->register_to_service_map(dpp
, daemon_type
, meta
);
1221 void RadosStore::get_quota(RGWQuotaInfo
& bucket_quota
, RGWQuotaInfo
& user_quota
)
1223 bucket_quota
= svc()->quota
->get_bucket_quota();
1224 user_quota
= svc()->quota
->get_user_quota();
1227 void RadosStore::get_ratelimit(RGWRateLimitInfo
& bucket_ratelimit
, RGWRateLimitInfo
& user_ratelimit
, RGWRateLimitInfo
& anon_ratelimit
)
1229 bucket_ratelimit
= svc()->zone
->get_current_period().get_config().bucket_ratelimit
;
1230 user_ratelimit
= svc()->zone
->get_current_period().get_config().user_ratelimit
;
1231 anon_ratelimit
= svc()->zone
->get_current_period().get_config().anon_ratelimit
;
1234 int RadosStore::set_buckets_enabled(const DoutPrefixProvider
* dpp
, vector
<rgw_bucket
>& buckets
, bool enabled
)
1236 return rados
->set_buckets_enabled(buckets
, enabled
, dpp
);
1239 int RadosStore::get_sync_policy_handler(const DoutPrefixProvider
* dpp
,
1240 std::optional
<rgw_zone_id
> zone
,
1241 std::optional
<rgw_bucket
> bucket
,
1242 RGWBucketSyncPolicyHandlerRef
* phandler
,
1245 return ctl()->bucket
->get_sync_policy_handler(zone
, bucket
, phandler
, y
, dpp
);
1248 RGWDataSyncStatusManager
* RadosStore::get_data_sync_manager(const rgw_zone_id
& source_zone
)
1250 return rados
->get_data_sync_manager(source_zone
);
1253 int RadosStore::read_all_usage(const DoutPrefixProvider
*dpp
, uint64_t start_epoch
, uint64_t end_epoch
,
1254 uint32_t max_entries
, bool* is_truncated
,
1255 RGWUsageIter
& usage_iter
,
1256 map
<rgw_user_bucket
, rgw_usage_log_entry
>& usage
)
1259 std::string bucket_name
;
1261 return rados
->read_usage(dpp
, uid
, bucket_name
, start_epoch
, end_epoch
, max_entries
,
1262 is_truncated
, usage_iter
, usage
);
1265 int RadosStore::trim_all_usage(const DoutPrefixProvider
*dpp
, uint64_t start_epoch
, uint64_t end_epoch
)
1268 std::string bucket_name
;
1270 return rados
->trim_usage(dpp
, uid
, bucket_name
, start_epoch
, end_epoch
);
1273 int RadosStore::get_config_key_val(std::string name
, bufferlist
* bl
)
1275 return svc()->config_key
->get(name
, true, bl
);
1278 int RadosStore::meta_list_keys_init(const DoutPrefixProvider
*dpp
, const std::string
& section
, const std::string
& marker
, void** phandle
)
1280 return ctl()->meta
.mgr
->list_keys_init(dpp
, section
, marker
, phandle
);
1283 int RadosStore::meta_list_keys_next(const DoutPrefixProvider
*dpp
, void* handle
, int max
, list
<std::string
>& keys
, bool* truncated
)
1285 return ctl()->meta
.mgr
->list_keys_next(dpp
, handle
, max
, keys
, truncated
);
1288 void RadosStore::meta_list_keys_complete(void* handle
)
1290 ctl()->meta
.mgr
->list_keys_complete(handle
);
1293 std::string
RadosStore::meta_get_marker(void* handle
)
1295 return ctl()->meta
.mgr
->get_marker(handle
);
1298 int RadosStore::meta_remove(const DoutPrefixProvider
* dpp
, std::string
& metadata_key
, optional_yield y
)
1300 return ctl()->meta
.mgr
->remove(metadata_key
, y
, dpp
);
1303 void RadosStore::finalize(void)
1309 std::unique_ptr
<LuaScriptManager
> RadosStore::get_lua_script_manager()
1311 return std::make_unique
<RadosLuaScriptManager
>(this);
1314 std::unique_ptr
<RGWRole
> RadosStore::get_role(std::string name
,
1317 std::string trust_policy
,
1318 std::string max_session_duration_str
,
1319 std::multimap
<std::string
,std::string
> tags
)
1321 return std::make_unique
<RadosRole
>(this, name
, tenant
, path
, trust_policy
, max_session_duration_str
, tags
);
1324 std::unique_ptr
<RGWRole
> RadosStore::get_role(std::string id
)
1326 return std::make_unique
<RadosRole
>(this, id
);
1329 int RadosStore::get_roles(const DoutPrefixProvider
*dpp
,
1331 const std::string
& path_prefix
,
1332 const std::string
& tenant
,
1333 vector
<std::unique_ptr
<RGWRole
>>& roles
)
1335 auto pool
= get_zone()->get_params().roles_pool
;
1338 // List all roles if path prefix is empty
1339 if (! path_prefix
.empty()) {
1340 prefix
= tenant
+ RGWRole::role_path_oid_prefix
+ path_prefix
;
1342 prefix
= tenant
+ RGWRole::role_path_oid_prefix
;
1345 //Get the filtered objects
1346 list
<std::string
> result
;
1348 RGWListRawObjsCtx ctx
;
1350 list
<std::string
> oids
;
1351 int r
= rados
->list_raw_objects(dpp
, pool
, prefix
, 1000, ctx
, oids
, &is_truncated
);
1353 ldpp_dout(dpp
, 0) << "ERROR: listing filtered objects failed: "
1354 << prefix
<< ": " << cpp_strerror(-r
) << dendl
;
1357 for (const auto& iter
: oids
) {
1358 result
.push_back(iter
.substr(RGWRole::role_path_oid_prefix
.size()));
1360 } while (is_truncated
);
1362 for (const auto& it
: result
) {
1363 //Find the role oid prefix from the end
1364 size_t pos
= it
.rfind(RGWRole::role_oid_prefix
);
1365 if (pos
== std::string::npos
) {
1368 // Split the result into path and info_oid + id
1369 std::string path
= it
.substr(0, pos
);
1371 /*Make sure that prefix is part of path (False results could've been returned)
1372 because of the role info oid + id appended to the path)*/
1373 if(path_prefix
.empty() || path
.find(path_prefix
) != std::string::npos
) {
1374 //Get id from info oid prefix + id
1375 std::string id
= it
.substr(pos
+ RGWRole::role_oid_prefix
.length());
1377 std::unique_ptr
<rgw::sal::RGWRole
> role
= get_role(id
);
1378 int ret
= role
->read_info(dpp
, y
);
1382 roles
.push_back(std::move(role
));
1389 std::unique_ptr
<RGWOIDCProvider
> RadosStore::get_oidc_provider()
1391 return std::make_unique
<RadosOIDCProvider
>(this);
1394 int RadosStore::get_oidc_providers(const DoutPrefixProvider
*dpp
,
1395 const std::string
& tenant
,
1396 vector
<std::unique_ptr
<RGWOIDCProvider
>>& providers
)
1398 std::string prefix
= tenant
+ RGWOIDCProvider::oidc_url_oid_prefix
;
1399 auto pool
= zone
.get_params().oidc_pool
;
1400 auto obj_ctx
= svc()->sysobj
->init_obj_ctx();
1402 //Get the filtered objects
1403 list
<std::string
> result
;
1405 RGWListRawObjsCtx ctx
;
1407 list
<std::string
> oids
;
1408 int r
= rados
->list_raw_objects(dpp
, pool
, prefix
, 1000, ctx
, oids
, &is_truncated
);
1410 ldpp_dout(dpp
, 0) << "ERROR: listing filtered objects failed: OIDC pool: "
1411 << pool
.name
<< ": " << prefix
<< ": " << cpp_strerror(-r
) << dendl
;
1414 for (const auto& iter
: oids
) {
1415 std::unique_ptr
<rgw::sal::RGWOIDCProvider
> provider
= get_oidc_provider();
1418 r
= rgw_get_system_obj(obj_ctx
, pool
, iter
, bl
, nullptr, nullptr, null_yield
, dpp
);
1425 auto iter
= bl
.cbegin();
1426 decode(*provider
, iter
);
1427 } catch (buffer::error
& err
) {
1428 ldpp_dout(dpp
, 0) << "ERROR: failed to decode oidc provider info from pool: "
1429 << pool
.name
<< ": " << iter
<< dendl
;
1433 providers
.push_back(std::move(provider
));
1435 } while (is_truncated
);
1440 std::unique_ptr
<Writer
> RadosStore::get_append_writer(const DoutPrefixProvider
*dpp
,
1442 std::unique_ptr
<rgw::sal::Object
> _head_obj
,
1443 const rgw_user
& owner
, RGWObjectCtx
& obj_ctx
,
1444 const rgw_placement_rule
*ptail_placement_rule
,
1445 const std::string
& unique_tag
,
1447 uint64_t *cur_accounted_size
)
1449 auto aio
= rgw::make_throttle(ctx()->_conf
->rgw_put_obj_min_window_size
, y
);
1450 return std::make_unique
<RadosAppendWriter
>(dpp
, y
,
1451 std::move(_head_obj
),
1452 this, std::move(aio
), owner
, obj_ctx
,
1453 ptail_placement_rule
,
1454 unique_tag
, position
,
1455 cur_accounted_size
);
1458 std::unique_ptr
<Writer
> RadosStore::get_atomic_writer(const DoutPrefixProvider
*dpp
,
1460 std::unique_ptr
<rgw::sal::Object
> _head_obj
,
1461 const rgw_user
& owner
, RGWObjectCtx
& obj_ctx
,
1462 const rgw_placement_rule
*ptail_placement_rule
,
1464 const std::string
& unique_tag
)
1466 auto aio
= rgw::make_throttle(ctx()->_conf
->rgw_put_obj_min_window_size
, y
);
1467 return std::make_unique
<RadosAtomicWriter
>(dpp
, y
,
1468 std::move(_head_obj
),
1469 this, std::move(aio
), owner
, obj_ctx
,
1470 ptail_placement_rule
,
1471 olh_epoch
, unique_tag
);
1474 int RadosStore::get_obj_head_ioctx(const DoutPrefixProvider
*dpp
, const RGWBucketInfo
& bucket_info
, const rgw_obj
& obj
, librados::IoCtx
* ioctx
)
1476 return rados
->get_obj_head_ioctx(dpp
, bucket_info
, obj
, ioctx
);
1479 RadosObject::~RadosObject() {}
1481 int RadosObject::get_obj_state(const DoutPrefixProvider
* dpp
, RGWObjectCtx
* rctx
, RGWObjState
**state
, optional_yield y
, bool follow_olh
)
1483 return store
->getRados()->get_obj_state(dpp
, rctx
, bucket
->get_info(), get_obj(), state
, follow_olh
, y
);
1486 int RadosObject::read_attrs(const DoutPrefixProvider
* dpp
, RGWRados::Object::Read
&read_op
, optional_yield y
, rgw_obj
* target_obj
)
1488 read_op
.params
.attrs
= &attrs
;
1489 read_op
.params
.target_obj
= target_obj
;
1490 read_op
.params
.obj_size
= &obj_size
;
1491 read_op
.params
.lastmod
= &mtime
;
1493 return read_op
.prepare(y
, dpp
);
1496 int RadosObject::set_obj_attrs(const DoutPrefixProvider
* dpp
, RGWObjectCtx
* rctx
, Attrs
* setattrs
, Attrs
* delattrs
, optional_yield y
, rgw_obj
* target_obj
)
1499 rgw_obj target
= get_obj();
1502 target_obj
= &target
;
1504 return store
->getRados()->set_attrs(dpp
, rctx
,
1507 setattrs
? *setattrs
: empty
,
1508 delattrs
? delattrs
: nullptr,
1512 int RadosObject::get_obj_attrs(RGWObjectCtx
* rctx
, optional_yield y
, const DoutPrefixProvider
* dpp
, rgw_obj
* target_obj
)
1514 RGWRados::Object
op_target(store
->getRados(), bucket
->get_info(), *rctx
, get_obj());
1515 RGWRados::Object::Read
read_op(&op_target
);
1517 return read_attrs(dpp
, read_op
, y
, target_obj
);
1520 int RadosObject::modify_obj_attrs(RGWObjectCtx
* rctx
, const char* attr_name
, bufferlist
& attr_val
, optional_yield y
, const DoutPrefixProvider
* dpp
)
1522 rgw_obj target
= get_obj();
1523 int r
= get_obj_attrs(rctx
, y
, dpp
, &target
);
1528 attrs
[attr_name
] = attr_val
;
1529 return set_obj_attrs(dpp
, rctx
, &attrs
, nullptr, y
, &target
);
1532 int RadosObject::delete_obj_attrs(const DoutPrefixProvider
* dpp
, RGWObjectCtx
* rctx
, const char* attr_name
, optional_yield y
)
1538 rmattr
[attr_name
] = bl
;
1539 return set_obj_attrs(dpp
, rctx
, nullptr, &rmattr
, y
);
1542 void RadosObject::set_compressed(RGWObjectCtx
* rctx
) {
1543 rgw_obj obj
= get_obj();
1544 store
->getRados()->set_compressed(rctx
, obj
);
1547 void RadosObject::set_atomic(RGWObjectCtx
* rctx
) const
1549 rgw_obj obj
= get_obj();
1550 store
->getRados()->set_atomic(rctx
, obj
);
1553 void RadosObject::set_prefetch_data(RGWObjectCtx
* rctx
)
1555 rgw_obj obj
= get_obj();
1556 store
->getRados()->set_prefetch_data(rctx
, obj
);
1559 bool RadosObject::is_expired() {
1560 auto iter
= attrs
.find(RGW_ATTR_DELETE_AT
);
1561 if (iter
!= attrs
.end()) {
1564 auto bufit
= iter
->second
.cbegin();
1565 decode(delete_at
, bufit
);
1566 } catch (buffer::error
& err
) {
1567 ldout(store
->ctx(), 0) << "ERROR: " << __func__
<< ": failed to decode " RGW_ATTR_DELETE_AT
" attr" << dendl
;
1571 if (delete_at
<= ceph_clock_now() && !delete_at
.is_zero()) {
1579 void RadosObject::gen_rand_obj_instance_name()
1581 store
->getRados()->gen_rand_obj_instance_name(&key
);
1584 void RadosObject::raw_obj_to_obj(const rgw_raw_obj
& raw_obj
)
1586 rgw_obj tobj
= get_obj();
1587 RGWSI_Tier_RADOS::raw_obj_to_obj(get_bucket()->get_key(), raw_obj
, &tobj
);
1591 void RadosObject::get_raw_obj(rgw_raw_obj
* raw_obj
)
1593 store
->getRados()->obj_to_raw((bucket
->get_info()).placement_rule
, get_obj(), raw_obj
);
1596 int RadosObject::omap_get_vals(const DoutPrefixProvider
*dpp
, const std::string
& marker
, uint64_t count
,
1597 std::map
<std::string
, bufferlist
> *m
,
1598 bool* pmore
, optional_yield y
)
1600 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
1601 rgw_raw_obj raw_obj
;
1602 get_raw_obj(&raw_obj
);
1603 auto sysobj
= obj_ctx
.get_obj(raw_obj
);
1605 return sysobj
.omap().get_vals(dpp
, marker
, count
, m
, pmore
, y
);
1608 int RadosObject::omap_get_all(const DoutPrefixProvider
*dpp
, std::map
<std::string
, bufferlist
> *m
,
1611 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
1612 rgw_raw_obj raw_obj
;
1613 get_raw_obj(&raw_obj
);
1614 auto sysobj
= obj_ctx
.get_obj(raw_obj
);
1616 return sysobj
.omap().get_all(dpp
, m
, y
);
1619 int RadosObject::omap_get_vals_by_keys(const DoutPrefixProvider
*dpp
, const std::string
& oid
,
1620 const std::set
<std::string
>& keys
,
1624 rgw_raw_obj head_obj
;
1625 librados::IoCtx cur_ioctx
;
1626 rgw_obj obj
= get_obj();
1628 store
->getRados()->obj_to_raw(bucket
->get_placement_rule(), obj
, &head_obj
);
1629 ret
= store
->get_obj_head_ioctx(dpp
, bucket
->get_info(), obj
, &cur_ioctx
);
1634 return cur_ioctx
.omap_get_vals_by_keys(oid
, keys
, vals
);
1637 int RadosObject::omap_set_val_by_key(const DoutPrefixProvider
*dpp
, const std::string
& key
, bufferlist
& val
,
1638 bool must_exist
, optional_yield y
)
1640 rgw_raw_obj raw_meta_obj
;
1641 rgw_obj obj
= get_obj();
1643 store
->getRados()->obj_to_raw(bucket
->get_placement_rule(), obj
, &raw_meta_obj
);
1645 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
1646 auto sysobj
= obj_ctx
.get_obj(raw_meta_obj
);
1648 return sysobj
.omap().set_must_exist(must_exist
).set(dpp
, key
, val
, y
);
1651 MPSerializer
* RadosObject::get_serializer(const DoutPrefixProvider
*dpp
, const std::string
& lock_name
)
1653 return new MPRadosSerializer(dpp
, store
, this, lock_name
);
1656 int RadosObject::transition(RGWObjectCtx
& rctx
,
1658 const rgw_placement_rule
& placement_rule
,
1659 const real_time
& mtime
,
1661 const DoutPrefixProvider
* dpp
,
1664 return store
->getRados()->transition_obj(rctx
, bucket
, *this, placement_rule
, mtime
, olh_epoch
, dpp
, y
);
1667 int RadosObject::get_max_chunk_size(const DoutPrefixProvider
* dpp
, rgw_placement_rule placement_rule
, uint64_t* max_chunk_size
, uint64_t* alignment
)
1669 return store
->getRados()->get_max_chunk_size(placement_rule
, get_obj(), max_chunk_size
, dpp
, alignment
);
1672 void RadosObject::get_max_aligned_size(uint64_t size
, uint64_t alignment
,
1675 store
->getRados()->get_max_aligned_size(size
, alignment
, max_size
);
1678 bool RadosObject::placement_rules_match(rgw_placement_rule
& r1
, rgw_placement_rule
& r2
)
1688 if (!store
->getRados()->get_obj_data_pool(r1
, obj
, &p1
)) {
1691 if (!store
->getRados()->get_obj_data_pool(r2
, obj
, &p2
)) {
1698 int RadosObject::dump_obj_layout(const DoutPrefixProvider
*dpp
, optional_yield y
, Formatter
* f
, RGWObjectCtx
* obj_ctx
)
1701 RGWObjManifest
*manifest
{nullptr};
1702 rgw_raw_obj head_obj
;
1704 RGWRados::Object
op_target(store
->getRados(), get_bucket()->get_info(),
1705 *obj_ctx
, get_obj());
1706 RGWRados::Object::Read
parent_op(&op_target
);
1709 parent_op
.params
.obj_size
= &obj_size
;
1710 parent_op
.params
.attrs
= &get_attrs();
1712 ret
= parent_op
.prepare(y
, dpp
);
1717 head_obj
= parent_op
.state
.head_obj
;
1719 ret
= op_target
.get_manifest(dpp
, &manifest
, y
);
1724 ::encode_json("head", head_obj
, f
);
1725 ::encode_json("manifest", *manifest
, f
);
1726 f
->open_array_section("data_location");
1727 for (auto miter
= manifest
->obj_begin(dpp
); miter
!= manifest
->obj_end(dpp
); ++miter
) {
1728 f
->open_object_section("obj");
1729 rgw_raw_obj raw_loc
= miter
.get_location().get_raw_obj(store
);
1730 uint64_t ofs
= miter
.get_ofs();
1731 uint64_t left
= manifest
->get_obj_size() - ofs
;
1732 ::encode_json("ofs", miter
.get_ofs(), f
);
1733 ::encode_json("loc", raw_loc
, f
);
1734 ::encode_json("loc_ofs", miter
.location_ofs(), f
);
1735 uint64_t loc_size
= miter
.get_stripe_size();
1736 if (loc_size
> left
) {
1739 ::encode_json("loc_size", loc_size
, f
);
1747 std::unique_ptr
<Object::ReadOp
> RadosObject::get_read_op(RGWObjectCtx
* ctx
)
1749 return std::make_unique
<RadosObject::RadosReadOp
>(this, ctx
);
1752 RadosObject::RadosReadOp::RadosReadOp(RadosObject
*_source
, RGWObjectCtx
*_rctx
) :
1755 op_target(_source
->store
->getRados(),
1756 _source
->get_bucket()->get_info(),
1757 *static_cast<RGWObjectCtx
*>(rctx
),
1758 _source
->get_obj()),
1759 parent_op(&op_target
)
1762 int RadosObject::RadosReadOp::prepare(optional_yield y
, const DoutPrefixProvider
* dpp
)
1766 parent_op
.conds
.mod_ptr
= params
.mod_ptr
;
1767 parent_op
.conds
.unmod_ptr
= params
.unmod_ptr
;
1768 parent_op
.conds
.high_precision_time
= params
.high_precision_time
;
1769 parent_op
.conds
.mod_zone_id
= params
.mod_zone_id
;
1770 parent_op
.conds
.mod_pg_ver
= params
.mod_pg_ver
;
1771 parent_op
.conds
.if_match
= params
.if_match
;
1772 parent_op
.conds
.if_nomatch
= params
.if_nomatch
;
1773 parent_op
.params
.lastmod
= params
.lastmod
;
1774 parent_op
.params
.target_obj
= params
.target_obj
;
1775 parent_op
.params
.obj_size
= &obj_size
;
1776 parent_op
.params
.attrs
= &source
->get_attrs();
1778 int ret
= parent_op
.prepare(y
, dpp
);
1782 source
->set_key(parent_op
.state
.obj
.key
);
1783 source
->set_obj_size(obj_size
);
1788 int RadosObject::RadosReadOp::read(int64_t ofs
, int64_t end
, bufferlist
& bl
, optional_yield y
, const DoutPrefixProvider
* dpp
)
1790 return parent_op
.read(ofs
, end
, bl
, y
, dpp
);
1793 int RadosObject::RadosReadOp::get_attr(const DoutPrefixProvider
* dpp
, const char* name
, bufferlist
& dest
, optional_yield y
)
1795 return parent_op
.get_attr(dpp
, name
, dest
, y
);
1798 std::unique_ptr
<Object::DeleteOp
> RadosObject::get_delete_op(RGWObjectCtx
* ctx
)
1800 return std::make_unique
<RadosObject::RadosDeleteOp
>(this, ctx
);
1803 RadosObject::RadosDeleteOp::RadosDeleteOp(RadosObject
*_source
, RGWObjectCtx
*_rctx
) :
1806 op_target(_source
->store
->getRados(),
1807 _source
->get_bucket()->get_info(),
1808 *static_cast<RGWObjectCtx
*>(rctx
),
1809 _source
->get_obj()),
1810 parent_op(&op_target
)
1813 int RadosObject::RadosDeleteOp::delete_obj(const DoutPrefixProvider
* dpp
, optional_yield y
)
1815 parent_op
.params
.bucket_owner
= params
.bucket_owner
.get_id();
1816 parent_op
.params
.versioning_status
= params
.versioning_status
;
1817 parent_op
.params
.obj_owner
= params
.obj_owner
;
1818 parent_op
.params
.olh_epoch
= params
.olh_epoch
;
1819 parent_op
.params
.marker_version_id
= params
.marker_version_id
;
1820 parent_op
.params
.bilog_flags
= params
.bilog_flags
;
1821 parent_op
.params
.remove_objs
= params
.remove_objs
;
1822 parent_op
.params
.expiration_time
= params
.expiration_time
;
1823 parent_op
.params
.unmod_since
= params
.unmod_since
;
1824 parent_op
.params
.mtime
= params
.mtime
;
1825 parent_op
.params
.high_precision_time
= params
.high_precision_time
;
1826 parent_op
.params
.zones_trace
= params
.zones_trace
;
1827 parent_op
.params
.abortmp
= params
.abortmp
;
1828 parent_op
.params
.parts_accounted_size
= params
.parts_accounted_size
;
1830 int ret
= parent_op
.delete_obj(y
, dpp
);
1834 result
.delete_marker
= parent_op
.result
.delete_marker
;
1835 result
.version_id
= parent_op
.result
.version_id
;
1840 int RadosObject::delete_object(const DoutPrefixProvider
* dpp
,
1841 RGWObjectCtx
* obj_ctx
,
1843 bool prevent_versioning
)
1845 RGWRados::Object
del_target(store
->getRados(), bucket
->get_info(), *obj_ctx
, get_obj());
1846 RGWRados::Object::Delete
del_op(&del_target
);
1848 del_op
.params
.bucket_owner
= bucket
->get_info().owner
;
1849 del_op
.params
.versioning_status
= prevent_versioning
? 0 : bucket
->get_info().versioning_status();
1851 return del_op
.delete_obj(y
, dpp
);
1854 int RadosObject::delete_obj_aio(const DoutPrefixProvider
* dpp
, RGWObjState
* astate
,
1855 Completions
* aio
, bool keep_index_consistent
,
1858 RadosCompletions
* raio
= static_cast<RadosCompletions
*>(aio
);
1860 return store
->getRados()->delete_obj_aio(dpp
, get_obj(), bucket
->get_info(), astate
,
1861 raio
->handles
, keep_index_consistent
, y
);
1864 int RadosObject::copy_object(RGWObjectCtx
& obj_ctx
,
1867 const rgw_zone_id
& source_zone
,
1868 rgw::sal::Object
* dest_object
,
1869 rgw::sal::Bucket
* dest_bucket
,
1870 rgw::sal::Bucket
* src_bucket
,
1871 const rgw_placement_rule
& dest_placement
,
1872 ceph::real_time
* src_mtime
,
1873 ceph::real_time
* mtime
,
1874 const ceph::real_time
* mod_ptr
,
1875 const ceph::real_time
* unmod_ptr
,
1876 bool high_precision_time
,
1877 const char* if_match
,
1878 const char* if_nomatch
,
1882 RGWObjCategory category
,
1884 boost::optional
<ceph::real_time
> delete_at
,
1885 std::string
* version_id
,
1888 void (*progress_cb
)(off_t
, void *),
1889 void* progress_data
,
1890 const DoutPrefixProvider
* dpp
,
1893 return store
->getRados()->copy_obj(obj_ctx
,
1906 high_precision_time
,
1909 static_cast<RGWRados::AttrsMod
>(attrs_mod
),
1914 (delete_at
? *delete_at
: real_time()),
1924 int RadosObject::RadosReadOp::iterate(const DoutPrefixProvider
* dpp
, int64_t ofs
, int64_t end
, RGWGetDataCB
* cb
, optional_yield y
)
1926 return parent_op
.iterate(dpp
, ofs
, end
, cb
, y
);
1929 int RadosObject::swift_versioning_restore(RGWObjectCtx
* obj_ctx
,
1931 const DoutPrefixProvider
* dpp
)
1933 return store
->getRados()->swift_versioning_restore(*obj_ctx
,
1934 bucket
->get_owner()->get_id(),
1941 int RadosObject::swift_versioning_copy(RGWObjectCtx
* obj_ctx
,
1942 const DoutPrefixProvider
* dpp
,
1945 return store
->getRados()->swift_versioning_copy(*obj_ctx
,
1946 bucket
->get_info().owner
,
1953 int RadosMultipartUpload::abort(const DoutPrefixProvider
*dpp
, CephContext
*cct
,
1954 RGWObjectCtx
*obj_ctx
)
1956 std::unique_ptr
<rgw::sal::Object
> meta_obj
= get_meta_obj();
1957 meta_obj
->set_in_extra_data(true);
1958 meta_obj
->set_hash_source(mp_obj
.get_key());
1959 cls_rgw_obj_chain chain
;
1960 list
<rgw_obj_index_key
> remove_objs
;
1964 uint64_t parts_accounted_size
= 0;
1967 ret
= list_parts(dpp
, cct
, 1000, marker
, &marker
, &truncated
);
1969 ldpp_dout(dpp
, 20) << __func__
<< ": RadosMultipartUpload::list_parts returned " <<
1971 return (ret
== -ENOENT
) ? -ERR_NO_SUCH_UPLOAD
: ret
;
1974 for (auto part_it
= parts
.begin();
1975 part_it
!= parts
.end();
1977 RadosMultipartPart
* obj_part
= dynamic_cast<RadosMultipartPart
*>(part_it
->second
.get());
1978 if (obj_part
->info
.manifest
.empty()) {
1979 std::unique_ptr
<rgw::sal::Object
> obj
= bucket
->get_object(
1980 rgw_obj_key(obj_part
->oid
, std::string(), RGW_OBJ_NS_MULTIPART
));
1981 obj
->set_hash_source(mp_obj
.get_key());
1982 ret
= obj
->delete_object(dpp
, obj_ctx
, null_yield
);
1983 if (ret
< 0 && ret
!= -ENOENT
)
1986 auto target
= meta_obj
->get_obj();
1987 store
->getRados()->update_gc_chain(dpp
, target
, obj_part
->info
.manifest
, &chain
);
1988 RGWObjManifest::obj_iterator oiter
= obj_part
->info
.manifest
.obj_begin(dpp
);
1989 if (oiter
!= obj_part
->info
.manifest
.obj_end(dpp
)) {
1990 std::unique_ptr
<rgw::sal::Object
> head
= bucket
->get_object(rgw_obj_key());
1991 rgw_raw_obj raw_head
= oiter
.get_location().get_raw_obj(store
);
1992 dynamic_cast<rgw::sal::RadosObject
*>(head
.get())->raw_obj_to_obj(raw_head
);
1994 rgw_obj_index_key key
;
1995 head
->get_key().get_index_key(&key
);
1996 remove_objs
.push_back(key
);
1999 parts_accounted_size
+= obj_part
->info
.accounted_size
;
2001 } while (truncated
);
2003 if (store
->getRados()->get_gc() == nullptr) {
2004 //Delete objects inline if gc hasn't been initialised (in case when bypass gc is specified)
2005 store
->getRados()->delete_objs_inline(dpp
, chain
, mp_obj
.get_upload_id());
2007 /* use upload id as tag and do it synchronously */
2008 ret
= store
->getRados()->send_chain_to_gc(chain
, mp_obj
.get_upload_id());
2010 ldpp_dout(dpp
, 5) << __func__
<< ": gc->send_chain() returned " << ret
<< dendl
;
2011 if (ret
== -ENOENT
) {
2012 return -ERR_NO_SUCH_UPLOAD
;
2014 //Delete objects inline if send chain to gc fails
2015 store
->getRados()->delete_objs_inline(dpp
, chain
, mp_obj
.get_upload_id());
2019 std::unique_ptr
<rgw::sal::Object::DeleteOp
> del_op
= meta_obj
->get_delete_op(obj_ctx
);
2020 del_op
->params
.bucket_owner
= bucket
->get_acl_owner();
2021 del_op
->params
.versioning_status
= 0;
2022 if (!remove_objs
.empty()) {
2023 del_op
->params
.remove_objs
= &remove_objs
;
2026 del_op
->params
.abortmp
= true;
2027 del_op
->params
.parts_accounted_size
= parts_accounted_size
;
2029 // and also remove the metadata obj
2030 ret
= del_op
->delete_obj(dpp
, null_yield
);
2032 ldpp_dout(dpp
, 20) << __func__
<< ": del_op.delete_obj returned " <<
2035 return (ret
== -ENOENT
) ? -ERR_NO_SUCH_UPLOAD
: ret
;
2038 std::unique_ptr
<rgw::sal::Object
> RadosMultipartUpload::get_meta_obj()
2040 return bucket
->get_object(rgw_obj_key(get_meta(), string(), mp_ns
));
2043 int RadosMultipartUpload::init(const DoutPrefixProvider
*dpp
, optional_yield y
, RGWObjectCtx
* obj_ctx
, ACLOwner
& owner
, rgw_placement_rule
& dest_placement
, rgw::sal::Attrs
& attrs
)
2046 std::string oid
= mp_obj
.get_key();
2050 string tmp_obj_name
;
2051 std::unique_ptr
<rgw::sal::Object
> obj
;
2052 gen_rand_alphanumeric(store
->ctx(), buf
, sizeof(buf
) - 1);
2053 std::string upload_id
= MULTIPART_UPLOAD_ID_PREFIX
; /* v2 upload id */
2054 upload_id
.append(buf
);
2056 mp_obj
.init(oid
, upload_id
);
2057 tmp_obj_name
= mp_obj
.get_meta();
2059 obj
= bucket
->get_object(rgw_obj_key(tmp_obj_name
, string(), mp_ns
));
2060 // the meta object will be indexed with 0 size, we c
2061 obj
->set_in_extra_data(true);
2062 obj
->set_hash_source(oid
);
2064 RGWRados::Object
op_target(store
->getRados(),
2065 obj
->get_bucket()->get_info(),
2066 *obj_ctx
, obj
->get_obj());
2067 RGWRados::Object::Write
obj_op(&op_target
);
2069 op_target
.set_versioning_disabled(true); /* no versioning for multipart meta */
2070 obj_op
.meta
.owner
= owner
.get_id();
2071 obj_op
.meta
.category
= RGWObjCategory::MultiMeta
;
2072 obj_op
.meta
.flags
= PUT_OBJ_CREATE_EXCL
;
2073 obj_op
.meta
.mtime
= &mtime
;
2075 multipart_upload_info upload_info
;
2076 upload_info
.dest_placement
= dest_placement
;
2079 encode(upload_info
, bl
);
2080 obj_op
.meta
.data
= &bl
;
2082 ret
= obj_op
.write_meta(dpp
, bl
.length(), 0, attrs
, y
);
2083 } while (ret
== -EEXIST
);
2088 int RadosMultipartUpload::list_parts(const DoutPrefixProvider
*dpp
, CephContext
*cct
,
2089 int num_parts
, int marker
,
2090 int *next_marker
, bool *truncated
,
2091 bool assume_unsorted
)
2093 map
<string
, bufferlist
> parts_map
;
2094 map
<string
, bufferlist
>::iterator iter
;
2096 std::unique_ptr
<rgw::sal::Object
> obj
= bucket
->get_object(
2097 rgw_obj_key(get_meta(), std::string(), RGW_OBJ_NS_MULTIPART
));
2098 obj
->set_in_extra_data(true);
2100 bool sorted_omap
= is_v2_upload_id(get_upload_id()) && !assume_unsorted
;
2110 snprintf(buf
, sizeof(buf
), "%08d", marker
);
2113 ret
= obj
->omap_get_vals(dpp
, p
, num_parts
+ 1, &parts_map
,
2114 nullptr, null_yield
);
2116 ret
= obj
->omap_get_all(dpp
, &parts_map
, null_yield
);
2125 uint32_t expected_next
= marker
+ 1;
2127 for (i
= 0, iter
= parts_map
.begin();
2128 (i
< num_parts
|| !sorted_omap
) && iter
!= parts_map
.end();
2130 bufferlist
& bl
= iter
->second
;
2131 auto bli
= bl
.cbegin();
2132 std::unique_ptr
<RadosMultipartPart
> part
= std::make_unique
<RadosMultipartPart
>();
2134 decode(part
->info
, bli
);
2135 } catch (buffer::error
& err
) {
2136 ldpp_dout(dpp
, 0) << "ERROR: could not part info, caught buffer::error" <<
2141 if (part
->info
.num
!= expected_next
) {
2142 /* ouch, we expected a specific part num here, but we got a
2143 * different one. Either a part is missing, or it could be a
2144 * case of mixed rgw versions working on the same upload,
2145 * where one gateway doesn't support correctly sorted omap
2146 * keys for multipart upload just assume data is unsorted.
2148 return list_parts(dpp
, cct
, num_parts
, marker
, next_marker
, truncated
, true);
2153 (int)part
->info
.num
> marker
) {
2154 last_num
= part
->info
.num
;
2155 parts
[part
->info
.num
] = std::move(part
);
2161 *truncated
= (iter
!= parts_map
.end());
2164 /* rebuild a map with only num_parts entries */
2165 std::map
<uint32_t, std::unique_ptr
<MultipartPart
>> new_parts
;
2166 std::map
<uint32_t, std::unique_ptr
<MultipartPart
>>::iterator piter
;
2167 for (i
= 0, piter
= parts
.begin();
2168 i
< num_parts
&& piter
!= parts
.end();
2170 last_num
= piter
->first
;
2171 new_parts
[piter
->first
] = std::move(piter
->second
);
2175 *truncated
= (piter
!= parts
.end());
2178 parts
.swap(new_parts
);
2182 *next_marker
= last_num
;
2188 int RadosMultipartUpload::complete(const DoutPrefixProvider
*dpp
,
2189 optional_yield y
, CephContext
* cct
,
2190 map
<int, string
>& part_etags
,
2191 list
<rgw_obj_index_key
>& remove_objs
,
2192 uint64_t& accounted_size
, bool& compressed
,
2193 RGWCompressionInfo
& cs_info
, off_t
& ofs
,
2194 std::string
& tag
, ACLOwner
& owner
,
2196 rgw::sal::Object
* target_obj
,
2197 RGWObjectCtx
* obj_ctx
)
2199 char final_etag
[CEPH_CRYPTO_MD5_DIGESTSIZE
];
2200 char final_etag_str
[CEPH_CRYPTO_MD5_DIGESTSIZE
* 2 + 16];
2204 // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
2205 hash
.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW
);
2209 int total_parts
= 0;
2210 int handled_parts
= 0;
2211 int max_parts
= 1000;
2213 uint64_t min_part_size
= cct
->_conf
->rgw_multipart_min_part_size
;
2214 auto etags_iter
= part_etags
.begin();
2215 rgw::sal::Attrs attrs
= target_obj
->get_attrs();
2218 ret
= list_parts(dpp
, cct
, max_parts
, marker
, &marker
, &truncated
);
2219 if (ret
== -ENOENT
) {
2220 ret
= -ERR_NO_SUCH_UPLOAD
;
2225 total_parts
+= parts
.size();
2226 if (!truncated
&& total_parts
!= (int)part_etags
.size()) {
2227 ldpp_dout(dpp
, 0) << "NOTICE: total parts mismatch: have: " << total_parts
2228 << " expected: " << part_etags
.size() << dendl
;
2229 ret
= -ERR_INVALID_PART
;
2233 for (auto obj_iter
= parts
.begin(); etags_iter
!= part_etags
.end() && obj_iter
!= parts
.end(); ++etags_iter
, ++obj_iter
, ++handled_parts
) {
2234 RadosMultipartPart
* part
= dynamic_cast<rgw::sal::RadosMultipartPart
*>(obj_iter
->second
.get());
2235 uint64_t part_size
= part
->get_size();
2236 if (handled_parts
< (int)part_etags
.size() - 1 &&
2237 part_size
< min_part_size
) {
2238 ret
= -ERR_TOO_SMALL
;
2242 char petag
[CEPH_CRYPTO_MD5_DIGESTSIZE
];
2243 if (etags_iter
->first
!= (int)obj_iter
->first
) {
2244 ldpp_dout(dpp
, 0) << "NOTICE: parts num mismatch: next requested: "
2245 << etags_iter
->first
<< " next uploaded: "
2246 << obj_iter
->first
<< dendl
;
2247 ret
= -ERR_INVALID_PART
;
2250 string part_etag
= rgw_string_unquote(etags_iter
->second
);
2251 if (part_etag
.compare(part
->get_etag()) != 0) {
2252 ldpp_dout(dpp
, 0) << "NOTICE: etag mismatch: part: " << etags_iter
->first
2253 << " etag: " << etags_iter
->second
<< dendl
;
2254 ret
= -ERR_INVALID_PART
;
2258 hex_to_buf(part
->get_etag().c_str(), petag
,
2259 CEPH_CRYPTO_MD5_DIGESTSIZE
);
2260 hash
.Update((const unsigned char *)petag
, sizeof(petag
));
2262 RGWUploadPartInfo
& obj_part
= part
->info
;
2264 /* update manifest for part */
2265 string oid
= mp_obj
.get_part(part
->info
.num
);
2267 src_obj
.init_ns(bucket
->get_key(), oid
, mp_ns
);
2269 if (obj_part
.manifest
.empty()) {
2270 ldpp_dout(dpp
, 0) << "ERROR: empty manifest for object part: obj="
2271 << src_obj
<< dendl
;
2272 ret
= -ERR_INVALID_PART
;
2275 manifest
.append(dpp
, obj_part
.manifest
, store
->get_zone());
2278 bool part_compressed
= (obj_part
.cs_info
.compression_type
!= "none");
2279 if ((handled_parts
> 0) &&
2280 ((part_compressed
!= compressed
) ||
2281 (cs_info
.compression_type
!= obj_part
.cs_info
.compression_type
))) {
2282 ldpp_dout(dpp
, 0) << "ERROR: compression type was changed during multipart upload ("
2283 << cs_info
.compression_type
<< ">>" << obj_part
.cs_info
.compression_type
<< ")" << dendl
;
2284 ret
= -ERR_INVALID_PART
;
2288 if (part_compressed
) {
2289 int64_t new_ofs
; // offset in compression data for new part
2290 if (cs_info
.blocks
.size() > 0)
2291 new_ofs
= cs_info
.blocks
.back().new_ofs
+ cs_info
.blocks
.back().len
;
2294 for (const auto& block
: obj_part
.cs_info
.blocks
) {
2295 compression_block cb
;
2296 cb
.old_ofs
= block
.old_ofs
+ cs_info
.orig_size
;
2297 cb
.new_ofs
= new_ofs
;
2299 cs_info
.blocks
.push_back(cb
);
2300 new_ofs
= cb
.new_ofs
+ cb
.len
;
2303 cs_info
.compression_type
= obj_part
.cs_info
.compression_type
;
2304 cs_info
.orig_size
+= obj_part
.cs_info
.orig_size
;
2308 rgw_obj_index_key remove_key
;
2309 src_obj
.key
.get_index_key(&remove_key
);
2311 remove_objs
.push_back(remove_key
);
2313 ofs
+= obj_part
.size
;
2314 accounted_size
+= obj_part
.accounted_size
;
2316 } while (truncated
);
2317 hash
.Final((unsigned char *)final_etag
);
2319 buf_to_hex((unsigned char *)final_etag
, sizeof(final_etag
), final_etag_str
);
2320 snprintf(&final_etag_str
[CEPH_CRYPTO_MD5_DIGESTSIZE
* 2],
2321 sizeof(final_etag_str
) - CEPH_CRYPTO_MD5_DIGESTSIZE
* 2,
2322 "-%lld", (long long)part_etags
.size());
2323 etag
= final_etag_str
;
2324 ldpp_dout(dpp
, 10) << "calculated etag: " << etag
<< dendl
;
2326 etag_bl
.append(etag
);
2328 attrs
[RGW_ATTR_ETAG
] = etag_bl
;
2331 // write compression attribute to full object
2333 encode(cs_info
, tmp
);
2334 attrs
[RGW_ATTR_COMPRESSION
] = tmp
;
2337 target_obj
->set_atomic(obj_ctx
);
2339 RGWRados::Object
op_target(store
->getRados(),
2340 target_obj
->get_bucket()->get_info(),
2341 *obj_ctx
, target_obj
->get_obj());
2342 RGWRados::Object::Write
obj_op(&op_target
);
2344 obj_op
.meta
.manifest
= &manifest
;
2345 obj_op
.meta
.remove_objs
= &remove_objs
;
2347 obj_op
.meta
.ptag
= &tag
; /* use req_id as operation tag */
2348 obj_op
.meta
.owner
= owner
.get_id();
2349 obj_op
.meta
.flags
= PUT_OBJ_CREATE
;
2350 obj_op
.meta
.modify_tail
= true;
2351 obj_op
.meta
.completeMultipart
= true;
2352 obj_op
.meta
.olh_epoch
= olh_epoch
;
2354 ret
= obj_op
.write_meta(dpp
, ofs
, accounted_size
, attrs
, y
);
2361 int RadosMultipartUpload::get_info(const DoutPrefixProvider
*dpp
, optional_yield y
, RGWObjectCtx
* obj_ctx
, rgw_placement_rule
** rule
, rgw::sal::Attrs
* attrs
)
2363 if (!rule
&& !attrs
) {
2368 if (!placement
.empty()) {
2371 /* Don't need attrs, done */
2379 /* We need either attributes or placement, so we need a read */
2380 std::unique_ptr
<rgw::sal::Object
> meta_obj
;
2381 meta_obj
= get_meta_obj();
2382 meta_obj
->set_in_extra_data(true);
2384 multipart_upload_info upload_info
;
2387 /* Read the obj head which contains the multipart_upload_info */
2388 std::unique_ptr
<rgw::sal::Object::ReadOp
> read_op
= meta_obj
->get_read_op(obj_ctx
);
2389 meta_obj
->set_prefetch_data(obj_ctx
);
2391 int ret
= read_op
->prepare(y
, dpp
);
2393 if (ret
== -ENOENT
) {
2394 return -ERR_NO_SUCH_UPLOAD
;
2399 extract_span_context(meta_obj
->get_attrs(), trace_ctx
);
2402 /* Attrs are filled in by prepare */
2403 *attrs
= meta_obj
->get_attrs();
2404 if (!rule
|| *rule
!= nullptr) {
2405 /* placement was cached; don't actually read */
2410 /* Now read the placement from the head */
2411 ret
= read_op
->read(0, store
->ctx()->_conf
->rgw_max_chunk_size
, headbl
, y
, dpp
);
2413 if (ret
== -ENOENT
) {
2414 return -ERR_NO_SUCH_UPLOAD
;
2419 if (headbl
.length() <= 0) {
2420 return -ERR_NO_SUCH_UPLOAD
;
2423 /* Decode multipart_upload_info */
2424 auto hiter
= headbl
.cbegin();
2426 decode(upload_info
, hiter
);
2427 } catch (buffer::error
& err
) {
2428 ldpp_dout(dpp
, 0) << "ERROR: failed to decode multipart upload info" << dendl
;
2431 placement
= upload_info
.dest_placement
;
2437 std::unique_ptr
<Writer
> RadosMultipartUpload::get_writer(
2438 const DoutPrefixProvider
*dpp
,
2440 std::unique_ptr
<rgw::sal::Object
> _head_obj
,
2441 const rgw_user
& owner
, RGWObjectCtx
& obj_ctx
,
2442 const rgw_placement_rule
*ptail_placement_rule
,
2444 const std::string
& part_num_str
)
2446 auto aio
= rgw::make_throttle(store
->ctx()->_conf
->rgw_put_obj_min_window_size
, y
);
2447 return std::make_unique
<RadosMultipartWriter
>(dpp
, y
, this,
2448 std::move(_head_obj
), store
, std::move(aio
), owner
,
2449 obj_ctx
, ptail_placement_rule
, part_num
, part_num_str
);
2452 MPRadosSerializer::MPRadosSerializer(const DoutPrefixProvider
*dpp
, RadosStore
* store
, RadosObject
* obj
, const std::string
& lock_name
) :
2456 rgw_raw_obj raw_obj
;
2458 obj
->get_raw_obj(&raw_obj
);
2460 store
->getRados()->get_obj_data_pool(obj
->get_bucket()->get_placement_rule(),
2461 obj
->get_obj(), &meta_pool
);
2462 store
->getRados()->open_pool_ctx(dpp
, meta_pool
, ioctx
, true);
2465 int MPRadosSerializer::try_lock(const DoutPrefixProvider
*dpp
, utime_t dur
, optional_yield y
)
2468 lock
.set_duration(dur
);
2469 lock
.lock_exclusive(&op
);
2470 int ret
= rgw_rados_operate(dpp
, ioctx
, oid
, &op
, y
);
2477 LCRadosSerializer::LCRadosSerializer(RadosStore
* store
, const std::string
& _oid
, const std::string
& lock_name
, const std::string
& cookie
) :
2478 lock(lock_name
), oid(_oid
)
2480 ioctx
= &store
->getRados()->lc_pool_ctx
;
2481 lock
.set_cookie(cookie
);
2484 int LCRadosSerializer::try_lock(const DoutPrefixProvider
*dpp
, utime_t dur
, optional_yield y
)
2486 lock
.set_duration(dur
);
2487 return lock
.lock_exclusive(ioctx
, oid
);
2490 int RadosLifecycle::get_entry(const std::string
& oid
, const std::string
& marker
,
2493 cls_rgw_lc_entry cls_entry
;
2494 int ret
= cls_rgw_lc_get_entry(*store
->getRados()->get_lc_pool_ctx(), oid
, marker
, cls_entry
);
2496 entry
.bucket
= cls_entry
.bucket
;
2497 entry
.start_time
= cls_entry
.start_time
;
2498 entry
.status
= cls_entry
.status
;
2503 int RadosLifecycle::get_next_entry(const std::string
& oid
, std::string
& marker
,
2506 cls_rgw_lc_entry cls_entry
;
2507 int ret
= cls_rgw_lc_get_next_entry(*store
->getRados()->get_lc_pool_ctx(), oid
, marker
,
2510 entry
.bucket
= cls_entry
.bucket
;
2511 entry
.start_time
= cls_entry
.start_time
;
2512 entry
.status
= cls_entry
.status
;
2517 int RadosLifecycle::set_entry(const std::string
& oid
, const LCEntry
& entry
)
2519 cls_rgw_lc_entry cls_entry
;
2521 cls_entry
.bucket
= entry
.bucket
;
2522 cls_entry
.start_time
= entry
.start_time
;
2523 cls_entry
.status
= entry
.status
;
2525 return cls_rgw_lc_set_entry(*store
->getRados()->get_lc_pool_ctx(), oid
, cls_entry
);
2528 int RadosLifecycle::list_entries(const std::string
& oid
, const std::string
& marker
,
2529 uint32_t max_entries
, vector
<LCEntry
>& entries
)
2533 vector
<cls_rgw_lc_entry
> cls_entries
;
2534 int ret
= cls_rgw_lc_list(*store
->getRados()->get_lc_pool_ctx(), oid
, marker
, max_entries
, cls_entries
);
2539 for (auto& entry
: cls_entries
) {
2540 entries
.push_back(LCEntry(entry
.bucket
, entry
.start_time
, entry
.status
));
2546 int RadosLifecycle::rm_entry(const std::string
& oid
, const LCEntry
& entry
)
2548 cls_rgw_lc_entry cls_entry
;
2550 cls_entry
.bucket
= entry
.bucket
;
2551 cls_entry
.start_time
= entry
.start_time
;
2552 cls_entry
.status
= entry
.status
;
2554 return cls_rgw_lc_rm_entry(*store
->getRados()->get_lc_pool_ctx(), oid
, cls_entry
);
2557 int RadosLifecycle::get_head(const std::string
& oid
, LCHead
& head
)
2559 cls_rgw_lc_obj_head cls_head
;
2560 int ret
= cls_rgw_lc_get_head(*store
->getRados()->get_lc_pool_ctx(), oid
, cls_head
);
2562 head
.marker
= cls_head
.marker
;
2563 head
.start_date
= cls_head
.start_date
;
2568 int RadosLifecycle::put_head(const std::string
& oid
, const LCHead
& head
)
2570 cls_rgw_lc_obj_head cls_head
;
2572 cls_head
.marker
= head
.marker
;
2573 cls_head
.start_date
= head
.start_date
;
2575 return cls_rgw_lc_put_head(*store
->getRados()->get_lc_pool_ctx(), oid
, cls_head
);
2578 LCSerializer
* RadosLifecycle::get_serializer(const std::string
& lock_name
, const std::string
& oid
, const std::string
& cookie
)
2580 return new LCRadosSerializer(store
, oid
, lock_name
, cookie
);
2583 int RadosNotification::publish_reserve(const DoutPrefixProvider
*dpp
, RGWObjTags
* obj_tags
)
2585 return rgw::notify::publish_reserve(dpp
, event_type
, res
, obj_tags
);
2588 int RadosNotification::publish_commit(const DoutPrefixProvider
* dpp
, uint64_t size
,
2589 const ceph::real_time
& mtime
, const std::string
& etag
, const std::string
& version
)
2591 return rgw::notify::publish_commit(obj
, size
, mtime
, etag
, version
, event_type
, res
, dpp
);
2594 int RadosAtomicWriter::prepare(optional_yield y
)
2596 return processor
.prepare(y
);
2599 int RadosAtomicWriter::process(bufferlist
&& data
, uint64_t offset
)
2601 return processor
.process(std::move(data
), offset
);
2604 int RadosAtomicWriter::complete(size_t accounted_size
, const std::string
& etag
,
2605 ceph::real_time
*mtime
, ceph::real_time set_mtime
,
2606 std::map
<std::string
, bufferlist
>& attrs
,
2607 ceph::real_time delete_at
,
2608 const char *if_match
, const char *if_nomatch
,
2609 const std::string
*user_data
,
2610 rgw_zone_set
*zones_trace
, bool *canceled
,
2613 return processor
.complete(accounted_size
, etag
, mtime
, set_mtime
, attrs
, delete_at
,
2614 if_match
, if_nomatch
, user_data
, zones_trace
, canceled
, y
);
2617 int RadosAppendWriter::prepare(optional_yield y
)
2619 return processor
.prepare(y
);
2622 int RadosAppendWriter::process(bufferlist
&& data
, uint64_t offset
)
2624 return processor
.process(std::move(data
), offset
);
2627 int RadosAppendWriter::complete(size_t accounted_size
, const std::string
& etag
,
2628 ceph::real_time
*mtime
, ceph::real_time set_mtime
,
2629 std::map
<std::string
, bufferlist
>& attrs
,
2630 ceph::real_time delete_at
,
2631 const char *if_match
, const char *if_nomatch
,
2632 const std::string
*user_data
,
2633 rgw_zone_set
*zones_trace
, bool *canceled
,
2636 return processor
.complete(accounted_size
, etag
, mtime
, set_mtime
, attrs
, delete_at
,
2637 if_match
, if_nomatch
, user_data
, zones_trace
, canceled
, y
);
2640 int RadosMultipartWriter::prepare(optional_yield y
)
2642 return processor
.prepare(y
);
2645 int RadosMultipartWriter::process(bufferlist
&& data
, uint64_t offset
)
2647 return processor
.process(std::move(data
), offset
);
2650 int RadosMultipartWriter::complete(size_t accounted_size
, const std::string
& etag
,
2651 ceph::real_time
*mtime
, ceph::real_time set_mtime
,
2652 std::map
<std::string
, bufferlist
>& attrs
,
2653 ceph::real_time delete_at
,
2654 const char *if_match
, const char *if_nomatch
,
2655 const std::string
*user_data
,
2656 rgw_zone_set
*zones_trace
, bool *canceled
,
2659 return processor
.complete(accounted_size
, etag
, mtime
, set_mtime
, attrs
, delete_at
,
2660 if_match
, if_nomatch
, user_data
, zones_trace
, canceled
, y
);
2663 const RGWZoneGroup
& RadosZone::get_zonegroup()
2665 return store
->svc()->zone
->get_zonegroup();
2668 int RadosZone::get_zonegroup(const std::string
& id
, RGWZoneGroup
& zonegroup
)
2670 return store
->svc()->zone
->get_zonegroup(id
, zonegroup
);
2673 const RGWZoneParams
& RadosZone::get_params()
2675 return store
->svc()->zone
->get_zone_params();
2678 const rgw_zone_id
& RadosZone::get_id()
2680 return store
->svc()->zone
->zone_id();
2683 const RGWRealm
& RadosZone::get_realm()
2685 return store
->svc()->zone
->get_realm();
2688 const std::string
& RadosZone::get_name() const
2690 return store
->svc()->zone
->zone_name();
2693 bool RadosZone::is_writeable()
2695 return store
->svc()->zone
->zone_is_writeable();
2698 bool RadosZone::get_redirect_endpoint(std::string
* endpoint
)
2700 return store
->svc()->zone
->get_redirect_zone_endpoint(endpoint
);
2703 bool RadosZone::has_zonegroup_api(const std::string
& api
) const
2705 return store
->svc()->zone
->has_zonegroup_api(api
);
2708 const std::string
& RadosZone::get_current_period_id()
2710 return store
->svc()->zone
->get_current_period_id();
2713 int RadosLuaScriptManager::get(const DoutPrefixProvider
* dpp
, optional_yield y
, const std::string
& key
, std::string
& script
)
2715 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2718 int r
= rgw_get_system_obj(obj_ctx
, pool
, key
, bl
, nullptr, nullptr, y
, dpp
);
2723 auto iter
= bl
.cbegin();
2725 ceph::decode(script
, iter
);
2726 } catch (buffer::error
& err
) {
2733 int RadosLuaScriptManager::put(const DoutPrefixProvider
* dpp
, optional_yield y
, const std::string
& key
, const std::string
& script
)
2735 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2737 ceph::encode(script
, bl
);
2739 int r
= rgw_put_system_obj(dpp
, obj_ctx
, pool
, key
, bl
, false, nullptr, real_time(), y
);
2747 int RadosLuaScriptManager::del(const DoutPrefixProvider
* dpp
, optional_yield y
, const std::string
& key
)
2749 int r
= rgw_delete_system_obj(dpp
, store
->svc()->sysobj
, pool
, key
, nullptr, y
);
2750 if (r
< 0 && r
!= -ENOENT
) {
2757 int RadosOIDCProvider::store_url(const DoutPrefixProvider
*dpp
, const std::string
& url
, bool exclusive
, optional_yield y
)
2759 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2760 std::string oid
= tenant
+ get_url_oid_prefix() + url
;
2765 return rgw_put_system_obj(dpp
, obj_ctx
, store
->get_zone()->get_params().oidc_pool
, oid
, bl
, exclusive
, nullptr, real_time(), y
);
2768 int RadosOIDCProvider::read_url(const DoutPrefixProvider
*dpp
, const std::string
& url
, const std::string
& tenant
)
2770 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2771 auto& pool
= store
->get_zone()->get_params().oidc_pool
;
2772 std::string oid
= tenant
+ get_url_oid_prefix() + url
;
2775 int ret
= rgw_get_system_obj(obj_ctx
, pool
, oid
, bl
, nullptr, nullptr, null_yield
, dpp
);
2782 auto iter
= bl
.cbegin();
2783 decode(*this, iter
);
2784 } catch (buffer::error
& err
) {
2785 ldpp_dout(dpp
, 0) << "ERROR: failed to decode oidc provider info from pool: " << pool
.name
<<
2786 ": " << url
<< dendl
;
2793 int RadosOIDCProvider::delete_obj(const DoutPrefixProvider
*dpp
, optional_yield y
)
2795 auto& pool
= store
->get_zone()->get_params().oidc_pool
;
2797 std::string url
, tenant
;
2798 auto ret
= get_tenant_url_from_arn(tenant
, url
);
2800 ldpp_dout(dpp
, 0) << "ERROR: failed to parse arn" << dendl
;
2804 if (this->tenant
!= tenant
) {
2805 ldpp_dout(dpp
, 0) << "ERROR: tenant in arn doesn't match that of user " << this->tenant
<< ", "
2806 << tenant
<< ": " << dendl
;
2811 std::string oid
= tenant
+ get_url_oid_prefix() + url
;
2812 ret
= rgw_delete_system_obj(dpp
, store
->svc()->sysobj
, pool
, oid
, nullptr, y
);
2814 ldpp_dout(dpp
, 0) << "ERROR: deleting oidc url from pool: " << pool
.name
<< ": "
2815 << provider_url
<< ": " << cpp_strerror(-ret
) << dendl
;
2821 int RadosRole::store_info(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
2824 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2825 std::string oid
= get_info_oid_prefix() + id
;
2830 if (!this->tags
.empty()) {
2832 encode(this->tags
, bl_tags
);
2833 map
<string
, bufferlist
> attrs
;
2834 attrs
.emplace("tagging", bl_tags
);
2835 return rgw_put_system_obj(dpp
, obj_ctx
, store
->get_zone()->get_params().roles_pool
, oid
, bl
, exclusive
, nullptr, real_time(), y
, &attrs
);
2838 return rgw_put_system_obj(dpp
, obj_ctx
, store
->get_zone()->get_params().roles_pool
, oid
, bl
, exclusive
, nullptr, real_time(), y
);
2841 int RadosRole::store_name(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
2843 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2844 RGWNameToId nameToId
;
2845 nameToId
.obj_id
= id
;
2847 std::string oid
= tenant
+ get_names_oid_prefix() + name
;
2851 encode(nameToId
, bl
);
2853 return rgw_put_system_obj(dpp
, obj_ctx
, store
->get_zone()->get_params().roles_pool
, oid
, bl
, exclusive
, nullptr, real_time(), y
);
2856 int RadosRole::store_path(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
2858 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2859 std::string oid
= tenant
+ get_path_oid_prefix() + path
+ get_info_oid_prefix() + id
;
2863 return rgw_put_system_obj(dpp
, obj_ctx
, store
->get_zone()->get_params().roles_pool
, oid
, bl
, exclusive
, nullptr, real_time(), y
);
2866 int RadosRole::read_id(const DoutPrefixProvider
*dpp
, const std::string
& role_name
, const std::string
& tenant
, std::string
& role_id
, optional_yield y
)
2868 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2869 std::string oid
= tenant
+ get_names_oid_prefix() + role_name
;
2872 int ret
= rgw_get_system_obj(obj_ctx
, store
->get_zone()->get_params().roles_pool
, oid
, bl
, nullptr, nullptr, null_yield
, dpp
);
2877 RGWNameToId nameToId
;
2879 auto iter
= bl
.cbegin();
2881 decode(nameToId
, iter
);
2882 } catch (buffer::error
& err
) {
2883 ldpp_dout(dpp
, 0) << "ERROR: failed to decode role from Role pool: " << role_name
<< dendl
;
2886 role_id
= nameToId
.obj_id
;
2890 int RadosRole::read_name(const DoutPrefixProvider
*dpp
, optional_yield y
)
2892 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2893 std::string oid
= tenant
+ get_names_oid_prefix() + name
;
2896 int ret
= rgw_get_system_obj(obj_ctx
, store
->get_zone()->get_params().roles_pool
, oid
, bl
, nullptr, nullptr, null_yield
, dpp
);
2898 ldpp_dout(dpp
, 0) << "ERROR: failed reading role name from Role pool: " << name
<<
2899 ": " << cpp_strerror(-ret
) << dendl
;
2903 RGWNameToId nameToId
;
2906 auto iter
= bl
.cbegin();
2907 decode(nameToId
, iter
);
2908 } catch (buffer::error
& err
) {
2909 ldpp_dout(dpp
, 0) << "ERROR: failed to decode role name from Role pool: " << name
<< dendl
;
2912 id
= nameToId
.obj_id
;
2916 int RadosRole::read_info(const DoutPrefixProvider
*dpp
, optional_yield y
)
2918 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
2919 std::string oid
= get_info_oid_prefix() + id
;
2922 map
<string
, bufferlist
> attrs
;
2923 int ret
= rgw_get_system_obj(obj_ctx
, store
->get_zone()->get_params().roles_pool
, oid
, bl
, nullptr, nullptr, null_yield
, dpp
, &attrs
, nullptr, boost::none
, true);
2925 ldpp_dout(dpp
, 0) << "ERROR: failed reading role info from Role pool: " << id
<< ": " << cpp_strerror(-ret
) << dendl
;
2931 auto iter
= bl
.cbegin();
2932 decode(*this, iter
);
2933 } catch (buffer::error
& err
) {
2934 ldpp_dout(dpp
, 0) << "ERROR: failed to decode role info from Role pool: " << id
<< dendl
;
2938 auto it
= attrs
.find("tagging");
2939 if (it
!= attrs
.end()) {
2940 bufferlist bl_tags
= it
->second
;
2943 auto iter
= bl_tags
.cbegin();
2945 } catch (buffer::error
& err
) {
2946 ldpp_dout(dpp
, 0) << "ERROR: failed to decode attrs" << id
<< dendl
;
2954 int RadosRole::create(const DoutPrefixProvider
*dpp
, bool exclusive
, optional_yield y
)
2958 if (! validate_input(dpp
)) {
2962 /* check to see the name is not used */
2963 ret
= read_id(dpp
, name
, tenant
, id
, y
);
2964 if (exclusive
&& ret
== 0) {
2965 ldpp_dout(dpp
, 0) << "ERROR: name " << name
<< " already in use for role id "
2968 } else if ( ret
< 0 && ret
!= -ENOENT
) {
2969 ldpp_dout(dpp
, 0) << "failed reading role id " << id
<< ": "
2970 << cpp_strerror(-ret
) << dendl
;
2974 /* create unique id */
2977 new_uuid
.generate_random();
2978 new_uuid
.print(uuid_str
);
2982 arn
= role_arn_prefix
+ tenant
+ ":role" + path
+ name
;
2985 real_clock::time_point t
= real_clock::now();
2988 real_clock::to_timeval(t
, tv
);
2992 gmtime_r(&tv
.tv_sec
, &result
);
2993 strftime(buf
,30,"%Y-%m-%dT%H:%M:%S", &result
);
2994 sprintf(buf
+ strlen(buf
),".%dZ",(int)tv
.tv_usec
/1000);
2995 creation_date
.assign(buf
, strlen(buf
));
2997 auto& pool
= store
->get_zone()->get_params().roles_pool
;
2998 ret
= store_info(dpp
, exclusive
, y
);
3000 ldpp_dout(dpp
, 0) << "ERROR: storing role info in Role pool: "
3001 << id
<< ": " << cpp_strerror(-ret
) << dendl
;
3005 ret
= store_name(dpp
, exclusive
, y
);
3007 ldpp_dout(dpp
, 0) << "ERROR: storing role name in Role pool: "
3008 << name
<< ": " << cpp_strerror(-ret
) << dendl
;
3010 //Delete the role info that was stored in the previous call
3011 std::string oid
= get_info_oid_prefix() + id
;
3012 int info_ret
= rgw_delete_system_obj(dpp
, store
->svc()->sysobj
, pool
, oid
, nullptr, y
);
3014 ldpp_dout(dpp
, 0) << "ERROR: cleanup of role id from Role pool: "
3015 << id
<< ": " << cpp_strerror(-info_ret
) << dendl
;
3020 ret
= store_path(dpp
, exclusive
, y
);
3022 ldpp_dout(dpp
, 0) << "ERROR: storing role path in Role pool: "
3023 << path
<< ": " << cpp_strerror(-ret
) << dendl
;
3024 //Delete the role info that was stored in the previous call
3025 std::string oid
= get_info_oid_prefix() + id
;
3026 int info_ret
= rgw_delete_system_obj(dpp
, store
->svc()->sysobj
, pool
, oid
, nullptr, y
);
3028 ldpp_dout(dpp
, 0) << "ERROR: cleanup of role id from Role pool: "
3029 << id
<< ": " << cpp_strerror(-info_ret
) << dendl
;
3031 //Delete role name that was stored in previous call
3032 oid
= tenant
+ get_names_oid_prefix() + name
;
3033 int name_ret
= rgw_delete_system_obj(dpp
, store
->svc()->sysobj
, pool
, oid
, nullptr, y
);
3035 ldpp_dout(dpp
, 0) << "ERROR: cleanup of role name from Role pool: "
3036 << name
<< ": " << cpp_strerror(-name_ret
) << dendl
;
3043 int RadosRole::delete_obj(const DoutPrefixProvider
*dpp
, optional_yield y
)
3045 auto& pool
= store
->get_zone()->get_params().roles_pool
;
3047 int ret
= read_name(dpp
, y
);
3052 ret
= read_info(dpp
, y
);
3057 if (! perm_policy_map
.empty()) {
3058 return -ERR_DELETE_CONFLICT
;
3062 std::string oid
= get_info_oid_prefix() + id
;
3063 ret
= rgw_delete_system_obj(dpp
, store
->svc()->sysobj
, pool
, oid
, nullptr, y
);
3065 ldpp_dout(dpp
, 0) << "ERROR: deleting role id from Role pool: "
3066 << id
<< ": " << cpp_strerror(-ret
) << dendl
;
3070 oid
= tenant
+ get_names_oid_prefix() + name
;
3071 ret
= rgw_delete_system_obj(dpp
, store
->svc()->sysobj
, pool
, oid
, nullptr, y
);
3073 ldpp_dout(dpp
, 0) << "ERROR: deleting role name from Role pool: "
3074 << name
<< ": " << cpp_strerror(-ret
) << dendl
;
3078 oid
= tenant
+ get_path_oid_prefix() + path
+ get_info_oid_prefix() + id
;
3079 ret
= rgw_delete_system_obj(dpp
, store
->svc()->sysobj
, pool
, oid
, nullptr, y
);
3081 ldpp_dout(dpp
, 0) << "ERROR: deleting role path from Role pool: "
3082 << path
<< ": " << cpp_strerror(-ret
) << dendl
;
3088 } // namespace rgw::sal
3092 void* newStore(void)
3094 rgw::sal::RadosStore
* store
= new rgw::sal::RadosStore();
3096 RGWRados
* rados
= new RGWRados();
3099 delete store
; store
= nullptr;
3101 store
->setRados(rados
);
3102 rados
->set_store(store
);