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"
32 #include "rgw_rest_conn.h"
33 #include "services/svc_sys_obj.h"
34 #include "services/svc_zone.h"
35 #include "services/svc_tier_rados.h"
36 #include "cls/rgw/cls_rgw_client.h"
38 #include "rgw_pubsub.h"
40 #define dout_subsys ceph_subsys_rgw
44 int RGWRadosUser::list_buckets(const string
& marker
, const string
& end_marker
,
45 uint64_t max
, bool need_stats
, RGWBucketList
&buckets
,
49 bool is_truncated
= false;
53 ret
= store
->ctl()->user
->list_buckets(info
.user_id
, marker
, end_marker
, max
,
54 need_stats
, &ulist
, &is_truncated
, y
);
58 buckets
.set_truncated(is_truncated
);
59 for (const auto& ent
: ulist
.get_buckets()) {
60 buckets
.add(std::unique_ptr
<RGWBucket
>(new RGWRadosBucket(this->store
, ent
.second
, this)));
66 RGWBucket
* RGWRadosUser::create_bucket(rgw_bucket
& bucket
,
67 ceph::real_time creation_time
)
72 int RGWRadosUser::load_by_id(optional_yield y
)
75 return store
->ctl()->user
->get_info_by_uid(info
.user_id
, &info
, y
);
78 std::unique_ptr
<RGWObject
> RGWRadosStore::get_object(const rgw_obj_key
& k
)
80 return std::unique_ptr
<RGWObject
>(new RGWRadosObject(this, k
));
84 RGWObject
*RGWRadosBucket::create_object(const rgw_obj_key
&key
)
89 int RGWRadosBucket::remove_bucket(bool delete_children
, std::string prefix
, std::string delimiter
, bool forward_to_master
, req_info
* req_info
, optional_yield y
)
94 ret
= get_bucket_info(y
);
99 params
.list_versions
= true;
100 params
.allow_unordered
= true;
104 bool is_truncated
= false;
106 results
.objs
.clear();
108 ret
= list(params
, 1000, results
, y
);
112 if (!results
.objs
.empty() && !delete_children
) {
113 lderr(store
->ctx()) << "ERROR: could not remove non-empty bucket " << info
.bucket
.name
<<
118 for (const auto& obj
: results
.objs
) {
119 rgw_obj_key
key(obj
.key
);
121 ret
= rgw_remove_object(store
, info
, info
.bucket
, key
);
122 if (ret
< 0 && ret
!= -ENOENT
) {
126 } while(is_truncated
);
128 /* If there's a prefix, then we are aborting multiparts as well */
129 if (!prefix
.empty()) {
130 ret
= abort_bucket_multiparts(store
, store
->ctx(), info
, prefix
, delimiter
);
136 ret
= store
->ctl()->bucket
->sync_user_stats(info
.owner
, info
, y
);
138 ldout(store
->ctx(), 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret
<< dendl
;
141 RGWObjVersionTracker ot
;
143 // if we deleted children above we will force delete, as any that
144 // remain is detrius from a prior bug
145 ret
= store
->getRados()->delete_bucket(info
, ot
, y
, !delete_children
);
147 lderr(store
->ctx()) << "ERROR: could not remove bucket " <<
148 info
.bucket
.name
<< dendl
;
152 // if bucket has notification definitions associated with it
153 // they should be removed (note that any pending notifications on the bucket are still going to be sent)
154 RGWPubSub
ps(store
, info
.owner
.tenant
);
155 RGWPubSub::Bucket
ps_bucket(&ps
, info
.bucket
);
156 const auto ps_ret
= ps_bucket
.remove_notifications(y
);
157 if (ps_ret
< 0 && ps_ret
!= -ENOENT
) {
158 lderr(store
->ctx()) << "ERROR: unable to remove notifications from bucket. ret=" << ps_ret
<< dendl
;
161 ret
= store
->ctl()->bucket
->unlink_bucket(info
.owner
, info
.bucket
, y
, false);
163 lderr(store
->ctx()) << "ERROR: unable to remove user bucket information" << dendl
;
166 if (forward_to_master
) {
168 ret
= store
->forward_request_to_master(owner
, &ot
.read_version
, in_data
, nullptr, *req_info
, y
);
170 if (ret
== -ENOENT
) {
171 /* adjust error, we want to return with NoSuchBucket and not
173 ret
= -ERR_NO_SUCH_BUCKET
;
182 int RGWRadosBucket::get_bucket_info(optional_yield y
)
184 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
185 RGWSI_MetaBackend_CtxParams bectx_params
= RGWSI_MetaBackend_CtxParams_SObj(&obj_ctx
);
186 RGWObjVersionTracker ep_ot
;
187 int ret
= store
->ctl()->bucket
->read_bucket_info(info
.bucket
, &info
, y
,
188 RGWBucketCtl::BucketInstance::GetParams()
191 .set_bectx_params(bectx_params
),
194 bucket_version
= ep_ot
.read_version
;
195 ent
.placement_rule
= info
.placement_rule
;
200 int RGWRadosBucket::load_by_name(const std::string
& tenant
, const std::string
& bucket_name
, const std::string bucket_instance_id
, RGWSysObjectCtx
*rctx
, optional_yield y
)
202 info
.bucket
.tenant
= tenant
;
203 info
.bucket
.name
= bucket_name
;
204 info
.bucket
.bucket_id
= bucket_instance_id
;
205 ent
.bucket
= info
.bucket
;
207 if (bucket_instance_id
.empty()) {
208 return get_bucket_info(y
);
211 return store
->getRados()->get_bucket_instance_info(*rctx
, info
.bucket
, info
, NULL
, &attrs
, y
);
214 int RGWRadosBucket::get_bucket_stats(RGWBucketInfo
& bucket_info
, int shard_id
,
215 std::string
*bucket_ver
, std::string
*master_ver
,
216 std::map
<RGWObjCategory
, RGWStorageStats
>& stats
,
217 std::string
*max_marker
, bool *syncstopped
)
219 return store
->getRados()->get_bucket_stats(bucket_info
, shard_id
, bucket_ver
, master_ver
, stats
, max_marker
, syncstopped
);
222 int RGWRadosBucket::read_bucket_stats(optional_yield y
)
224 int ret
= store
->ctl()->bucket
->read_bucket_stats(info
.bucket
, &ent
, y
);
225 info
.placement_rule
= ent
.placement_rule
;
229 int RGWRadosBucket::sync_user_stats(optional_yield y
)
231 return store
->ctl()->bucket
->sync_user_stats(owner
->get_id(), info
, y
);
234 int RGWRadosBucket::update_container_stats(void)
237 map
<std::string
, RGWBucketEnt
> m
;
239 m
[info
.bucket
.name
] = ent
;
240 ret
= store
->getRados()->update_containers_stats(m
);
246 map
<string
, RGWBucketEnt
>::iterator iter
= m
.find(info
.bucket
.name
);
250 ent
.count
= iter
->second
.count
;
251 ent
.size
= iter
->second
.size
;
252 ent
.size_rounded
= iter
->second
.size_rounded
;
253 ent
.creation_time
= iter
->second
.creation_time
;
254 ent
.placement_rule
= std::move(iter
->second
.placement_rule
);
256 info
.creation_time
= ent
.creation_time
;
257 info
.placement_rule
= ent
.placement_rule
;
262 int RGWRadosBucket::check_bucket_shards(void)
264 return store
->getRados()->check_bucket_shards(info
, info
.bucket
, get_count());
267 int RGWRadosBucket::link(RGWUser
* new_user
, optional_yield y
)
269 RGWBucketEntryPoint ep
;
270 ep
.bucket
= info
.bucket
;
271 ep
.owner
= new_user
->get_user();
272 ep
.creation_time
= get_creation_time();
275 rgw_ep_info ep_data
{ep
, ep_attrs
};
277 return store
->ctl()->bucket
->link_bucket(new_user
->get_user(), info
.bucket
,
278 ceph::real_time(), y
, true, &ep_data
);
281 int RGWRadosBucket::unlink(RGWUser
* new_user
, optional_yield y
)
286 int RGWRadosBucket::chown(RGWUser
* new_user
, RGWUser
* old_user
, optional_yield y
)
290 return store
->ctl()->bucket
->chown(store
, info
, new_user
->get_user(),
291 old_user
->get_display_name(), obj_marker
, y
);
294 int RGWRadosBucket::put_instance_info(bool exclusive
, ceph::real_time _mtime
)
297 return store
->getRados()->put_bucket_instance_info(info
, exclusive
, mtime
, &attrs
);
300 /* Make sure to call get_bucket_info() if you need it first */
301 bool RGWRadosBucket::is_owner(RGWUser
* user
)
303 return (info
.owner
.compare(user
->get_user()) == 0);
306 int RGWRadosBucket::check_empty(optional_yield y
)
308 return store
->getRados()->check_bucket_empty(info
, y
);
311 int RGWRadosBucket::check_quota(RGWQuotaInfo
& user_quota
, RGWQuotaInfo
& bucket_quota
, uint64_t obj_size
,
312 optional_yield y
, bool check_size_only
)
314 return store
->getRados()->check_quota(owner
->get_user(), get_key(),
315 user_quota
, bucket_quota
, obj_size
, y
, check_size_only
);
318 int RGWRadosBucket::set_instance_attrs(RGWAttrs
& attrs
, optional_yield y
)
320 return store
->ctl()->bucket
->set_bucket_instance_attrs(get_info(),
321 attrs
, &get_info().objv_tracker
, y
);
324 int RGWRadosBucket::try_refresh_info(ceph::real_time
*pmtime
)
326 return store
->getRados()->try_refresh_bucket_info(info
, pmtime
, &attrs
);
329 int RGWRadosBucket::read_usage(uint64_t start_epoch
, uint64_t end_epoch
,
330 uint32_t max_entries
, bool *is_truncated
,
331 RGWUsageIter
& usage_iter
,
332 map
<rgw_user_bucket
, rgw_usage_log_entry
>& usage
)
334 return store
->getRados()->read_usage(owner
->get_id(), get_name(), start_epoch
,
335 end_epoch
, max_entries
, is_truncated
,
339 int RGWRadosBucket::set_acl(RGWAccessControlPolicy
&acl
, optional_yield y
)
346 return store
->ctl()->bucket
->set_acl(acl
.get_owner(), info
.bucket
, info
, aclbl
, y
);
349 std::unique_ptr
<RGWObject
> RGWRadosBucket::get_object(const rgw_obj_key
& k
)
351 return std::unique_ptr
<RGWObject
>(new RGWRadosObject(this->store
, k
, this));
354 int RGWRadosBucket::list(ListParams
& params
, int max
, ListResults
& results
, optional_yield y
)
356 RGWRados::Bucket
target(store
->getRados(), get_info());
357 if (params
.shard_id
>= 0) {
358 target
.set_shard_id(params
.shard_id
);
360 RGWRados::Bucket::List
list_op(&target
);
362 list_op
.params
.prefix
= params
.prefix
;
363 list_op
.params
.delim
= params
.delim
;
364 list_op
.params
.marker
= params
.marker
;
365 list_op
.params
.ns
= params
.ns
;
366 list_op
.params
.end_marker
= params
.end_marker
;
367 list_op
.params
.list_versions
= params
.list_versions
;
368 list_op
.params
.allow_unordered
= params
.allow_unordered
;
370 int ret
= list_op
.list_objects(max
, &results
.objs
, &results
.common_prefixes
, &results
.is_truncated
, y
);
372 results
.next_marker
= list_op
.get_next_marker();
378 std::unique_ptr
<RGWUser
> RGWRadosStore::get_user(const rgw_user
&u
)
380 return std::unique_ptr
<RGWUser
>(new RGWRadosUser(this, u
));
383 //RGWBucket *RGWRadosStore::create_bucket(RGWUser &u, const rgw_bucket &b)
386 //bucket = new RGWRadosBucket(this, u, b);
392 void RGWRadosStore::finalize(void)
398 int RGWObject::range_to_ofs(uint64_t obj_size
, int64_t &ofs
, int64_t &end
)
405 } else if (end
< 0) {
410 if (ofs
>= (off_t
)obj_size
) {
413 if (end
>= (off_t
)obj_size
) {
420 int RGWRadosObject::get_obj_state(RGWObjectCtx
*rctx
, RGWBucket
& bucket
, RGWObjState
**state
, optional_yield y
, bool follow_olh
)
422 rgw_obj
obj(bucket
.get_key(), key
.name
);
424 return store
->getRados()->get_obj_state(rctx
, bucket
.get_info(), obj
, state
, follow_olh
, y
);
427 int RGWRadosObject::read_attrs(RGWRados::Object::Read
&read_op
, optional_yield y
, rgw_obj
*target_obj
)
429 read_op
.params
.attrs
= &attrs
;
430 read_op
.params
.target_obj
= target_obj
;
431 read_op
.params
.obj_size
= &obj_size
;
432 read_op
.params
.lastmod
= &mtime
;
434 return read_op
.prepare(y
);
437 int RGWRadosObject::set_obj_attrs(RGWObjectCtx
* rctx
, RGWAttrs
* setattrs
, RGWAttrs
* delattrs
, optional_yield y
, rgw_obj
* target_obj
)
440 rgw_obj target
= get_obj();
443 target_obj
= &target
;
445 return store
->getRados()->set_attrs(rctx
,
448 setattrs
? *setattrs
: empty
,
449 delattrs
? delattrs
: nullptr,
453 int RGWRadosObject::get_obj_attrs(RGWObjectCtx
*rctx
, optional_yield y
, rgw_obj
* target_obj
)
455 RGWRados::Object
op_target(store
->getRados(), bucket
->get_info(), *rctx
, get_obj());
456 RGWRados::Object::Read
read_op(&op_target
);
458 return read_attrs(read_op
, y
, target_obj
);
461 int RGWRadosObject::modify_obj_attrs(RGWObjectCtx
*rctx
, const char *attr_name
, bufferlist
& attr_val
, optional_yield y
)
463 rgw_obj target
= get_obj();
464 int r
= get_obj_attrs(rctx
, y
, &target
);
469 attrs
[attr_name
] = attr_val
;
470 return set_obj_attrs(rctx
, &attrs
, nullptr, y
, &target
);
473 int RGWRadosObject::delete_obj_attrs(RGWObjectCtx
*rctx
, const char *attr_name
, optional_yield y
)
479 rmattr
[attr_name
] = bl
;
480 return set_obj_attrs(rctx
, nullptr, &rmattr
, y
);
483 int RGWRadosObject::copy_obj_data(RGWObjectCtx
& rctx
, RGWBucket
* dest_bucket
,
487 const DoutPrefixProvider
*dpp
,
491 RGWRados::Object
op_target(store
->getRados(), dest_bucket
->get_info(), rctx
, get_obj());
492 RGWRados::Object::Read
read_op(&op_target
);
494 int ret
= read_attrs(read_op
, y
);
500 attrset
.erase(RGW_ATTR_ID_TAG
);
501 attrset
.erase(RGW_ATTR_TAIL_TAG
);
503 return store
->getRados()->copy_obj_data(rctx
, dest_bucket
,
504 dest_bucket
->get_info().placement_rule
, read_op
,
505 obj_size
- 1, dest_obj
, NULL
, mtime
, attrset
, 0,
506 real_time(), NULL
, dpp
, y
);
509 void RGWRadosObject::set_atomic(RGWObjectCtx
*rctx
) const
511 rgw_obj obj
= get_obj();
512 store
->getRados()->set_atomic(rctx
, obj
);
515 void RGWRadosObject::set_prefetch_data(RGWObjectCtx
*rctx
)
517 rgw_obj obj
= get_obj();
518 store
->getRados()->set_prefetch_data(rctx
, obj
);
521 bool RGWRadosObject::is_expired() {
522 auto iter
= attrs
.find(RGW_ATTR_DELETE_AT
);
523 if (iter
!= attrs
.end()) {
526 auto bufit
= iter
->second
.cbegin();
527 decode(delete_at
, bufit
);
528 } catch (buffer::error
& err
) {
529 ldout(store
->ctx(), 0) << "ERROR: " << __func__
<< ": failed to decode " RGW_ATTR_DELETE_AT
" attr" << dendl
;
533 if (delete_at
<= ceph_clock_now() && !delete_at
.is_zero()) {
541 void RGWRadosObject::gen_rand_obj_instance_name()
543 store
->getRados()->gen_rand_obj_instance_name(&key
);
546 void RGWRadosObject::raw_obj_to_obj(const rgw_raw_obj
& raw_obj
)
548 rgw_obj tobj
= get_obj();
549 RGWSI_Tier_RADOS::raw_obj_to_obj(get_bucket()->get_key(), raw_obj
, &tobj
);
553 void RGWRadosObject::get_raw_obj(rgw_raw_obj
* raw_obj
)
555 store
->getRados()->obj_to_raw((bucket
->get_info()).placement_rule
, get_obj(), raw_obj
);
558 int RGWRadosObject::omap_get_vals_by_keys(const std::string
& oid
,
559 const std::set
<std::string
>& keys
,
563 rgw_raw_obj head_obj
;
564 librados::IoCtx cur_ioctx
;
565 rgw_obj obj
= get_obj();
567 store
->getRados()->obj_to_raw(bucket
->get_placement_rule(), obj
, &head_obj
);
568 ret
= store
->get_obj_head_ioctx(bucket
->get_info(), obj
, &cur_ioctx
);
573 return cur_ioctx
.omap_get_vals_by_keys(oid
, keys
, vals
);
576 int RGWRadosObject::omap_set_val_by_key(const std::string
& key
, bufferlist
& val
,
577 bool must_exist
, optional_yield y
)
579 rgw_raw_obj raw_meta_obj
;
580 rgw_obj obj
= get_obj();
582 store
->getRados()->obj_to_raw(bucket
->get_placement_rule(), obj
, &raw_meta_obj
);
584 auto obj_ctx
= store
->svc()->sysobj
->init_obj_ctx();
585 auto sysobj
= obj_ctx
.get_obj(raw_meta_obj
);
587 return sysobj
.omap().set_must_exist(must_exist
).set(key
, val
, y
);
590 MPSerializer
* RGWRadosObject::get_serializer(const std::string
& lock_name
)
592 return new MPRadosSerializer(store
, this, lock_name
);
595 int RGWRadosObject::transition(RGWObjectCtx
& rctx
,
597 const rgw_placement_rule
& placement_rule
,
598 const real_time
& mtime
,
600 const DoutPrefixProvider
*dpp
,
603 return store
->getRados()->transition_obj(rctx
, bucket
, *this, placement_rule
, mtime
, olh_epoch
, dpp
, y
);
606 int RGWRadosObject::get_max_chunk_size(rgw_placement_rule placement_rule
, uint64_t *max_chunk_size
, uint64_t *alignment
)
608 return store
->getRados()->get_max_chunk_size(placement_rule
, get_obj(), max_chunk_size
, alignment
);
611 void RGWRadosObject::get_max_aligned_size(uint64_t size
, uint64_t alignment
,
614 store
->getRados()->get_max_aligned_size(size
, alignment
, max_size
);
617 bool RGWRadosObject::placement_rules_match(rgw_placement_rule
& r1
, rgw_placement_rule
& r2
)
627 if (!store
->getRados()->get_obj_data_pool(r1
, obj
, &p1
)) {
630 if (!store
->getRados()->get_obj_data_pool(r2
, obj
, &p2
)) {
637 std::unique_ptr
<RGWObject::ReadOp
> RGWRadosObject::get_read_op(RGWObjectCtx
*ctx
)
639 return std::unique_ptr
<RGWObject::ReadOp
>(new RGWRadosObject::RadosReadOp(this, ctx
));
642 RGWRadosObject::RadosReadOp::RadosReadOp(RGWRadosObject
*_source
, RGWObjectCtx
*_rctx
) :
645 op_target(_source
->store
->getRados(),
646 _source
->get_bucket()->get_info(),
647 *static_cast<RGWObjectCtx
*>(rctx
),
649 parent_op(&op_target
)
652 int RGWRadosObject::RadosReadOp::prepare(optional_yield y
)
656 parent_op
.conds
.mod_ptr
= params
.mod_ptr
;
657 parent_op
.conds
.unmod_ptr
= params
.unmod_ptr
;
658 parent_op
.conds
.high_precision_time
= params
.high_precision_time
;
659 parent_op
.conds
.mod_zone_id
= params
.mod_zone_id
;
660 parent_op
.conds
.mod_pg_ver
= params
.mod_pg_ver
;
661 parent_op
.conds
.if_match
= params
.if_match
;
662 parent_op
.conds
.if_nomatch
= params
.if_nomatch
;
663 parent_op
.params
.lastmod
= params
.lastmod
;
664 parent_op
.params
.target_obj
= params
.target_obj
;
665 parent_op
.params
.obj_size
= &obj_size
;
666 parent_op
.params
.attrs
= &source
->get_attrs();
668 int ret
= parent_op
.prepare(y
);
672 source
->set_key(parent_op
.state
.obj
.key
);
673 source
->set_obj_size(obj_size
);
674 result
.head_obj
= parent_op
.state
.head_obj
;
679 int RGWRadosObject::RadosReadOp::read(int64_t ofs
, int64_t end
, bufferlist
& bl
, optional_yield y
)
681 return parent_op
.read(ofs
, end
, bl
, y
);
684 int RGWRadosObject::RadosReadOp::get_manifest(RGWObjManifest
**pmanifest
,
687 return op_target
.get_manifest(pmanifest
, y
);
690 int RGWRadosObject::RadosReadOp::get_attr(const char *name
, bufferlist
& dest
, optional_yield y
)
692 return parent_op
.get_attr(name
, dest
, y
);
695 int RGWRadosObject::delete_object(RGWObjectCtx
* obj_ctx
, ACLOwner obj_owner
, ACLOwner bucket_owner
, ceph::real_time unmod_since
, bool high_precision_time
, uint64_t epoch
, string
& version_id
, optional_yield y
)
698 RGWRados::Object
del_target(store
->getRados(), bucket
->get_info(), *obj_ctx
, get_obj());
699 RGWRados::Object::Delete
del_op(&del_target
);
701 del_op
.params
.olh_epoch
= epoch
;
702 del_op
.params
.marker_version_id
= version_id
;
703 del_op
.params
.bucket_owner
= bucket_owner
.get_id();
704 del_op
.params
.versioning_status
= bucket
->get_info().versioning_status();
705 del_op
.params
.obj_owner
= obj_owner
;
706 del_op
.params
.unmod_since
= unmod_since
;
707 del_op
.params
.high_precision_time
= high_precision_time
;
709 ret
= del_op
.delete_obj(y
);
711 delete_marker
= del_op
.result
.delete_marker
;
712 version_id
= del_op
.result
.version_id
;
718 int RGWRadosObject::copy_object(RGWObjectCtx
& obj_ctx
,
721 const rgw_zone_id
& source_zone
,
722 rgw::sal::RGWObject
* dest_object
,
723 rgw::sal::RGWBucket
* dest_bucket
,
724 rgw::sal::RGWBucket
* src_bucket
,
725 const rgw_placement_rule
& dest_placement
,
726 ceph::real_time
*src_mtime
,
727 ceph::real_time
*mtime
,
728 const ceph::real_time
*mod_ptr
,
729 const ceph::real_time
*unmod_ptr
,
730 bool high_precision_time
,
731 const char *if_match
,
732 const char *if_nomatch
,
736 RGWObjCategory category
,
738 boost::optional
<ceph::real_time
> delete_at
,
742 void (*progress_cb
)(off_t
, void *),
744 const DoutPrefixProvider
*dpp
,
747 return store
->getRados()->copy_obj(obj_ctx
,
763 static_cast<RGWRados::AttrsMod
>(attrs_mod
),
768 (delete_at
? *delete_at
: real_time()),
778 int RGWRadosObject::RadosReadOp::iterate(int64_t ofs
, int64_t end
, RGWGetDataCB
*cb
, optional_yield y
)
780 return parent_op
.iterate(ofs
, end
, cb
, y
);
783 std::unique_ptr
<RGWObject::WriteOp
> RGWRadosObject::get_write_op(RGWObjectCtx
* ctx
)
785 return std::unique_ptr
<RGWObject::WriteOp
>(new RGWRadosObject::RadosWriteOp(this, ctx
));
788 RGWRadosObject::RadosWriteOp::RadosWriteOp(RGWRadosObject
* _source
, RGWObjectCtx
* _rctx
) :
791 op_target(_source
->store
->getRados(),
792 _source
->get_bucket()->get_info(),
793 *static_cast<RGWObjectCtx
*>(rctx
),
795 parent_op(&op_target
)
798 int RGWRadosObject::RadosWriteOp::prepare(optional_yield y
)
800 op_target
.set_versioning_disabled(params
.versioning_disabled
);
801 parent_op
.meta
.mtime
= params
.mtime
;
802 parent_op
.meta
.rmattrs
= params
.rmattrs
;
803 parent_op
.meta
.data
= params
.data
;
804 parent_op
.meta
.manifest
= params
.manifest
;
805 parent_op
.meta
.ptag
= params
.ptag
;
806 parent_op
.meta
.remove_objs
= params
.remove_objs
;
807 parent_op
.meta
.set_mtime
= params
.set_mtime
;
808 parent_op
.meta
.owner
= params
.owner
.get_id();
809 parent_op
.meta
.category
= params
.category
;
810 parent_op
.meta
.flags
= params
.flags
;
811 parent_op
.meta
.if_match
= params
.if_match
;
812 parent_op
.meta
.if_nomatch
= params
.if_nomatch
;
813 parent_op
.meta
.olh_epoch
= params
.olh_epoch
;
814 parent_op
.meta
.delete_at
= params
.delete_at
;
815 parent_op
.meta
.canceled
= params
.canceled
;
816 parent_op
.meta
.user_data
= params
.user_data
;
817 parent_op
.meta
.zones_trace
= params
.zones_trace
;
818 parent_op
.meta
.modify_tail
= params
.modify_tail
;
819 parent_op
.meta
.completeMultipart
= params
.completeMultipart
;
820 parent_op
.meta
.appendable
= params
.appendable
;
825 int RGWRadosObject::RadosWriteOp::write_meta(uint64_t size
, uint64_t accounted_size
, optional_yield y
)
827 int ret
= parent_op
.write_meta(size
, accounted_size
, *params
.attrs
, y
);
828 params
.canceled
= parent_op
.meta
.canceled
;
833 int RGWRadosObject::swift_versioning_restore(RGWObjectCtx
* obj_ctx
,
835 const DoutPrefixProvider
*dpp
)
837 return store
->getRados()->swift_versioning_restore(*obj_ctx
,
838 bucket
->get_owner()->get_id(),
845 int RGWRadosObject::swift_versioning_copy(RGWObjectCtx
* obj_ctx
,
846 const DoutPrefixProvider
*dpp
,
849 return store
->getRados()->swift_versioning_copy(*obj_ctx
,
850 bucket
->get_info().owner
,
857 int RGWRadosStore::get_bucket(RGWUser
* u
, const rgw_bucket
& b
, std::unique_ptr
<RGWBucket
>* bucket
, optional_yield y
)
862 bp
= new RGWRadosBucket(this, b
, u
);
863 ret
= bp
->get_bucket_info(y
);
873 int RGWRadosStore::get_bucket(RGWUser
* u
, const RGWBucketInfo
& i
, std::unique_ptr
<RGWBucket
>* bucket
)
877 bp
= new RGWRadosBucket(this, i
, u
);
878 /* Don't need to fetch the bucket info, use the provided one */
884 int RGWRadosStore::get_bucket(RGWUser
* u
, const std::string
& tenant
, const std::string
&name
, std::unique_ptr
<RGWBucket
>* bucket
, optional_yield y
)
891 return get_bucket(u
, b
, bucket
, y
);
894 static int decode_policy(CephContext
*cct
,
896 RGWAccessControlPolicy
*policy
)
898 auto iter
= bl
.cbegin();
900 policy
->decode(iter
);
901 } catch (buffer::error
& err
) {
902 ldout(cct
, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl
;
905 if (cct
->_conf
->subsys
.should_gather
<ceph_subsys_rgw
, 15>()) {
906 ldout(cct
, 15) << __func__
<< " Read AccessControlPolicy";
907 RGWAccessControlPolicy_S3
*s3policy
= static_cast<RGWAccessControlPolicy_S3
*>(policy
);
908 s3policy
->to_xml(*_dout
);
914 static int rgw_op_get_bucket_policy_from_attr(RGWRadosStore
*store
,
916 RGWAttrs
& bucket_attrs
,
917 RGWAccessControlPolicy
*policy
,
920 auto aiter
= bucket_attrs
.find(RGW_ATTR_ACL
);
922 if (aiter
!= bucket_attrs
.end()) {
923 int ret
= decode_policy(store
->ctx(), aiter
->second
, policy
);
927 ldout(store
->ctx(), 0) << "WARNING: couldn't find acl header for bucket, generating default" << dendl
;
928 /* object exists, but policy is broken */
929 int r
= user
.load_by_id(y
);
933 policy
->create_default(user
.get_user(), user
.get_display_name());
938 bool RGWRadosStore::is_meta_master()
940 return svc()->zone
->is_meta_master();
943 int RGWRadosStore::forward_request_to_master(RGWUser
* user
, obj_version
*objv
,
945 JSONParser
*jp
, req_info
& info
,
948 if (is_meta_master()) {
949 /* We're master, don't forward */
953 if (!svc()->zone
->get_master_conn()) {
954 ldout(ctx(), 0) << "rest connection is invalid" << dendl
;
957 ldout(ctx(), 0) << "sending request to master zonegroup" << dendl
;
959 string uid_str
= user
->get_id().to_str();
960 #define MAX_REST_RESPONSE (128 * 1024) // we expect a very small response
961 int ret
= svc()->zone
->get_master_conn()->forward(rgw_user(uid_str
), info
,
962 objv
, MAX_REST_RESPONSE
,
963 &in_data
, &response
, y
);
967 ldout(ctx(), 20) << "response: " << response
.c_str() << dendl
;
968 if (jp
&& !jp
->parse(response
.c_str(), response
.length())) {
969 ldout(ctx(), 0) << "failed parsing response from master zonegroup" << dendl
;
976 int RGWRadosStore::defer_gc(RGWObjectCtx
*rctx
, RGWBucket
* bucket
, RGWObject
* obj
, optional_yield y
)
978 return rados
->defer_gc(rctx
, bucket
->get_info(), obj
->get_obj(), y
);
981 const RGWZoneGroup
& RGWRadosStore::get_zonegroup()
983 return rados
->svc
.zone
->get_zonegroup();
986 int RGWRadosStore::get_zonegroup(const string
& id
, RGWZoneGroup
& zonegroup
)
988 return rados
->svc
.zone
->get_zonegroup(id
, zonegroup
);
991 int RGWRadosStore::cluster_stat(RGWClusterStat
& stats
)
993 rados_cluster_stat_t rados_stats
;
996 ret
= rados
->get_rados_handle()->cluster_stat(rados_stats
);
1000 stats
.kb
= rados_stats
.kb
;
1001 stats
.kb_used
= rados_stats
.kb_used
;
1002 stats
.kb_avail
= rados_stats
.kb_avail
;
1003 stats
.num_objects
= rados_stats
.num_objects
;
1008 int RGWRadosStore::create_bucket(RGWUser
& u
, const rgw_bucket
& b
,
1009 const string
& zonegroup_id
,
1010 rgw_placement_rule
& placement_rule
,
1011 string
& swift_ver_location
,
1012 const RGWQuotaInfo
* pquota_info
,
1013 const RGWAccessControlPolicy
& policy
,
1015 RGWBucketInfo
& info
,
1016 obj_version
& ep_objv
,
1018 bool obj_lock_enabled
,
1021 std::unique_ptr
<RGWBucket
>* bucket_out
,
1026 RGWBucketInfo master_info
;
1027 rgw_bucket
*pmaster_bucket
;
1028 uint32_t *pmaster_num_shards
;
1029 real_time creation_time
;
1030 std::unique_ptr
<RGWBucket
> bucket
;
1031 obj_version objv
, *pobjv
= NULL
;
1033 /* If it exists, look it up; otherwise create it */
1034 ret
= get_bucket(&u
, b
, &bucket
, y
);
1035 if (ret
< 0 && ret
!= -ENOENT
)
1038 if (ret
!= -ENOENT
) {
1039 RGWAccessControlPolicy
old_policy(ctx());
1041 if (swift_ver_location
.empty()) {
1042 swift_ver_location
= bucket
->get_info().swift_ver_location
;
1044 placement_rule
.inherit_from(bucket
->get_info().placement_rule
);
1046 // don't allow changes to the acl policy
1047 int r
= rgw_op_get_bucket_policy_from_attr(this, u
, bucket
->get_attrs(),
1049 if (r
>= 0 && old_policy
!= policy
) {
1050 bucket_out
->swap(bucket
);
1054 bucket
= std::unique_ptr
<RGWBucket
>(new RGWRadosBucket(this, b
, &u
));
1056 bucket
->set_attrs(attrs
);
1059 if (!svc()->zone
->is_meta_master()) {
1061 ret
= forward_request_to_master(&u
, NULL
, in_data
, &jp
, req_info
, y
);
1066 JSONDecoder::decode_json("entry_point_object_ver", ep_objv
, &jp
);
1067 JSONDecoder::decode_json("object_ver", objv
, &jp
);
1068 JSONDecoder::decode_json("bucket_info", master_info
, &jp
);
1069 ldpp_dout(this, 20) << "parsed: objv.tag=" << objv
.tag
<< " objv.ver=" << objv
.ver
<< dendl
;
1070 std::time_t ctime
= ceph::real_clock::to_time_t(master_info
.creation_time
);
1071 ldpp_dout(this, 20) << "got creation time: << " << std::put_time(std::localtime(&ctime
), "%F %T") << dendl
;
1072 pmaster_bucket
= &master_info
.bucket
;
1073 creation_time
= master_info
.creation_time
;
1074 pmaster_num_shards
= &master_info
.layout
.current_index
.layout
.normal
.num_shards
;
1076 if (master_info
.obj_lock_enabled()) {
1077 info
.flags
= BUCKET_VERSIONED
| BUCKET_OBJ_LOCK_ENABLED
;
1080 pmaster_bucket
= NULL
;
1081 pmaster_num_shards
= NULL
;
1082 if (obj_lock_enabled
)
1083 info
.flags
= BUCKET_VERSIONED
| BUCKET_OBJ_LOCK_ENABLED
;
1086 std::string zid
= zonegroup_id
;
1088 zid
= svc()->zone
->get_zonegroup().get_id();
1092 rgw_placement_rule selected_placement_rule
;
1093 ret
= svc()->zone
->select_bucket_placement(u
.get_info(),
1094 zid
, placement_rule
,
1095 &selected_placement_rule
, nullptr, y
);
1096 if (selected_placement_rule
!= info
.placement_rule
) {
1098 bucket_out
->swap(bucket
);
1103 ret
= getRados()->create_bucket(u
.get_info(), bucket
->get_key(),
1104 zid
, placement_rule
, swift_ver_location
,
1106 info
, pobjv
, &ep_objv
, creation_time
,
1107 pmaster_bucket
, pmaster_num_shards
, y
, exclusive
);
1108 if (ret
== -EEXIST
) {
1111 } else if (ret
!= 0) {
1116 bucket
->set_version(ep_objv
);
1117 bucket
->get_info() = info
;
1119 bucket_out
->swap(bucket
);
1124 std::unique_ptr
<Lifecycle
> RGWRadosStore::get_lifecycle(void)
1126 return std::unique_ptr
<Lifecycle
>(new RadosLifecycle(this));
1129 int RGWRadosStore::delete_raw_obj(const rgw_raw_obj
& obj
)
1131 return rados
->delete_raw_obj(obj
);
1134 void RGWRadosStore::get_raw_obj(const rgw_placement_rule
& placement_rule
, const rgw_obj
& obj
, rgw_raw_obj
* raw_obj
)
1136 rados
->obj_to_raw(placement_rule
, obj
, raw_obj
);
1139 int RGWRadosStore::get_raw_chunk_size(const rgw_raw_obj
& obj
, uint64_t* chunk_size
)
1141 return rados
->get_max_chunk_size(obj
.pool
, chunk_size
);
1144 MPRadosSerializer::MPRadosSerializer(RGWRadosStore
* store
, RGWRadosObject
* obj
, const std::string
& lock_name
) :
1148 rgw_raw_obj raw_obj
;
1150 obj
->get_raw_obj(&raw_obj
);
1152 store
->getRados()->get_obj_data_pool(obj
->get_bucket()->get_placement_rule(),
1153 obj
->get_obj(), &meta_pool
);
1154 store
->getRados()->open_pool_ctx(meta_pool
, ioctx
, true);
1157 int MPRadosSerializer::try_lock(utime_t dur
, optional_yield y
)
1160 lock
.set_duration(dur
);
1161 lock
.lock_exclusive(&op
);
1162 int ret
= rgw_rados_operate(ioctx
, oid
, &op
, y
);
1169 LCRadosSerializer::LCRadosSerializer(RGWRadosStore
* store
, const std::string
& _oid
, const std::string
& lock_name
, const std::string
& cookie
) :
1170 lock(lock_name
), oid(_oid
)
1172 ioctx
= &store
->getRados()->lc_pool_ctx
;
1173 lock
.set_cookie(cookie
);
1176 int LCRadosSerializer::try_lock(utime_t dur
, optional_yield y
)
1178 lock
.set_duration(dur
);
1179 return lock
.lock_exclusive(ioctx
, oid
);
1182 int RadosLifecycle::get_entry(const string
& oid
, const std::string
& marker
,
1185 cls_rgw_lc_entry cls_entry
;
1186 int ret
= cls_rgw_lc_get_entry(*store
->getRados()->get_lc_pool_ctx(), oid
, marker
, cls_entry
);
1188 entry
.bucket
= cls_entry
.bucket
;
1189 entry
.start_time
= cls_entry
.start_time
;
1190 entry
.status
= cls_entry
.status
;
1195 int RadosLifecycle::get_next_entry(const string
& oid
, std::string
& marker
,
1198 cls_rgw_lc_entry cls_entry
;
1199 int ret
= cls_rgw_lc_get_next_entry(*store
->getRados()->get_lc_pool_ctx(), oid
, marker
,
1202 entry
.bucket
= cls_entry
.bucket
;
1203 entry
.start_time
= cls_entry
.start_time
;
1204 entry
.status
= cls_entry
.status
;
1209 int RadosLifecycle::set_entry(const string
& oid
, const LCEntry
& entry
)
1211 cls_rgw_lc_entry cls_entry
;
1213 cls_entry
.bucket
= entry
.bucket
;
1214 cls_entry
.start_time
= entry
.start_time
;
1215 cls_entry
.status
= entry
.status
;
1217 return cls_rgw_lc_set_entry(*store
->getRados()->get_lc_pool_ctx(), oid
, cls_entry
);
1220 int RadosLifecycle::list_entries(const string
& oid
, const string
& marker
,
1221 uint32_t max_entries
, vector
<LCEntry
>& entries
)
1225 vector
<cls_rgw_lc_entry
> cls_entries
;
1226 int ret
= cls_rgw_lc_list(*store
->getRados()->get_lc_pool_ctx(), oid
, marker
, max_entries
, cls_entries
);
1231 for (auto& entry
: cls_entries
) {
1232 entries
.push_back(LCEntry(entry
.bucket
, entry
.start_time
, entry
.status
));
1238 int RadosLifecycle::rm_entry(const string
& oid
, const LCEntry
& entry
)
1240 cls_rgw_lc_entry cls_entry
;
1242 cls_entry
.bucket
= entry
.bucket
;
1243 cls_entry
.start_time
= entry
.start_time
;
1244 cls_entry
.status
= entry
.status
;
1246 return cls_rgw_lc_rm_entry(*store
->getRados()->get_lc_pool_ctx(), oid
, cls_entry
);
1249 int RadosLifecycle::get_head(const string
& oid
, LCHead
& head
)
1251 cls_rgw_lc_obj_head cls_head
;
1252 int ret
= cls_rgw_lc_get_head(*store
->getRados()->get_lc_pool_ctx(), oid
, cls_head
);
1254 head
.marker
= cls_head
.marker
;
1255 head
.start_date
= cls_head
.start_date
;
1260 int RadosLifecycle::put_head(const string
& oid
, const LCHead
& head
)
1262 cls_rgw_lc_obj_head cls_head
;
1264 cls_head
.marker
= head
.marker
;
1265 cls_head
.start_date
= head
.start_date
;
1267 return cls_rgw_lc_put_head(*store
->getRados()->get_lc_pool_ctx(), oid
, cls_head
);
1270 LCSerializer
* RadosLifecycle::get_serializer(const std::string
& lock_name
, const std::string
& oid
, const std::string
& cookie
)
1272 return new LCRadosSerializer(store
, oid
, lock_name
, cookie
);
1275 } // namespace rgw::sal
1277 rgw::sal::RGWRadosStore
*RGWStoreManager::init_storage_provider(CephContext
*cct
, bool use_gc_thread
, bool use_lc_thread
, bool quota_threads
, bool run_sync_thread
, bool run_reshard_thread
, bool use_cache
)
1279 RGWRados
*rados
= new RGWRados
;
1280 rgw::sal::RGWRadosStore
*store
= new rgw::sal::RGWRadosStore();
1282 store
->setRados(rados
);
1283 rados
->set_store(store
);
1285 if ((*rados
).set_use_cache(use_cache
)
1286 .set_run_gc_thread(use_gc_thread
)
1287 .set_run_lc_thread(use_lc_thread
)
1288 .set_run_quota_threads(quota_threads
)
1289 .set_run_sync_thread(run_sync_thread
)
1290 .set_run_reshard_thread(run_reshard_thread
)
1291 .initialize(cct
) < 0) {
1299 rgw::sal::RGWRadosStore
*RGWStoreManager::init_raw_storage_provider(CephContext
*cct
)
1301 RGWRados
*rados
= new RGWRados
;
1302 rgw::sal::RGWRadosStore
*store
= new rgw::sal::RGWRadosStore();
1304 store
->setRados(rados
);
1305 rados
->set_store(store
);
1307 rados
->set_context(cct
);
1309 int ret
= rados
->init_svc(true);
1311 ldout(cct
, 0) << "ERROR: failed to init services (ret=" << cpp_strerror(-ret
) << ")" << dendl
;
1316 if (rados
->init_rados() < 0) {
1324 int rgw::sal::RGWRadosStore::get_obj_head_ioctx(const RGWBucketInfo
& bucket_info
, const rgw_obj
& obj
, librados::IoCtx
*ioctx
)
1326 return rados
->get_obj_head_ioctx(bucket_info
, obj
, ioctx
);
1329 void RGWStoreManager::close_storage(rgw::sal::RGWRadosStore
*store
)