]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_sal_rados.cc
8c9f9ef031b7da6dc24178d7f3b3e4a215593efa
[ceph.git] / ceph / src / rgw / rgw_sal_rados.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 /*
5 * Ceph - scalable distributed file system
6 *
7 * Copyright (C) 2020 Red Hat, Inc.
8 *
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.
13 *
14 */
15
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <system_error>
19 #include <unistd.h>
20 #include <sstream>
21
22 #include "common/Clock.h"
23 #include "common/errno.h"
24
25 #include "rgw_sal.h"
26 #include "rgw_sal_rados.h"
27 #include "rgw_bucket.h"
28 #include "rgw_multi.h"
29 #include "rgw_acl_s3.h"
30 #include "rgw_aio.h"
31 #include "rgw_aio_throttle.h"
32 #include "rgw_tracer.h"
33
34 #include "rgw_zone.h"
35 #include "rgw_rest_conn.h"
36 #include "rgw_service.h"
37 #include "rgw_lc.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"
45
46 #include "rgw_pubsub.h"
47
48 #define dout_subsys ceph_subsys_rgw
49
50 using namespace std;
51
52 static string mp_ns = RGW_OBJ_NS_MULTIPART;
53
54 namespace rgw::sal {
55
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;
59
60 static int decode_policy(CephContext* cct,
61 bufferlist& bl,
62 RGWAccessControlPolicy* policy)
63 {
64 auto iter = bl.cbegin();
65 try {
66 policy->decode(iter);
67 } catch (buffer::error& err) {
68 ldout(cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
69 return -EIO;
70 }
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);
75 *_dout << dendl;
76 }
77 return 0;
78 }
79
80 static int rgw_op_get_bucket_policy_from_attr(const DoutPrefixProvider* dpp,
81 RadosStore* store,
82 User* user,
83 Attrs& bucket_attrs,
84 RGWAccessControlPolicy* policy,
85 optional_yield y)
86 {
87 auto aiter = bucket_attrs.find(RGW_ATTR_ACL);
88
89 if (aiter != bucket_attrs.end()) {
90 int ret = decode_policy(store->ctx(), aiter->second, policy);
91 if (ret < 0)
92 return ret;
93 } else {
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);
97 if (r < 0)
98 return r;
99
100 policy->create_default(user->get_id(), user->get_display_name());
101 }
102 return 0;
103 }
104
105 int RadosCompletions::drain()
106 {
107 int ret = 0;
108 while (!handles.empty()) {
109 librados::AioCompletion* handle = handles.front();
110 handles.pop_front();
111 handle->wait_for_complete();
112 int r = handle->get_return_value();
113 handle->release();
114 if (r < 0) {
115 ret = r;
116 }
117 }
118 return ret;
119 }
120
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)
124 {
125 RGWUserBuckets ulist;
126 bool is_truncated = false;
127 int ret;
128
129 buckets.clear();
130 ret = store->ctl()->user->list_buckets(dpp, info.user_id, marker, end_marker, max,
131 need_stats, &ulist, &is_truncated, y);
132 if (ret < 0)
133 return ret;
134
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)));
138 }
139
140 return 0;
141 }
142
143 int RadosUser::create_bucket(const DoutPrefixProvider* dpp,
144 const rgw_bucket& b,
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,
150 Attrs& attrs,
151 RGWBucketInfo& info,
152 obj_version& ep_objv,
153 bool exclusive,
154 bool obj_lock_enabled,
155 bool* existed,
156 req_info& req_info,
157 std::unique_ptr<Bucket>* bucket_out,
158 optional_yield y)
159 {
160 int ret;
161 bufferlist in_data;
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;
168
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)
172 return ret;
173
174 if (ret != -ENOENT) {
175 RGWAccessControlPolicy old_policy(store->ctx());
176 *existed = true;
177 if (swift_ver_location.empty()) {
178 swift_ver_location = bucket->get_info().swift_ver_location;
179 }
180 placement_rule.inherit_from(bucket->get_info().placement_rule);
181
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(),
184 &old_policy, y);
185 if (r >= 0 && old_policy != policy) {
186 bucket_out->swap(bucket);
187 return -EEXIST;
188 }
189 } else {
190 bucket = std::unique_ptr<Bucket>(new RadosBucket(store, b, this));
191 *existed = false;
192 bucket->set_attrs(attrs);
193 }
194
195 if (!store->svc()->zone->is_meta_master()) {
196 JSONParser jp;
197 ret = store->forward_request_to_master(dpp, this, NULL, in_data, &jp, req_info, y);
198 if (ret < 0) {
199 return ret;
200 }
201
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;
211 pobjv = &objv;
212 if (master_info.obj_lock_enabled()) {
213 info.flags = BUCKET_VERSIONED | BUCKET_OBJ_LOCK_ENABLED;
214 }
215 } else {
216 pmaster_bucket = NULL;
217 pmaster_num_shards = NULL;
218 if (obj_lock_enabled)
219 info.flags = BUCKET_VERSIONED | BUCKET_OBJ_LOCK_ENABLED;
220 }
221
222 std::string zid = zonegroup_id;
223 if (zid.empty()) {
224 zid = store->svc()->zone->get_zonegroup().get_id();
225 }
226
227 if (*existed) {
228 rgw_placement_rule selected_placement_rule;
229 ret = store->svc()->zone->select_bucket_placement(dpp, this->get_info(),
230 zid, placement_rule,
231 &selected_placement_rule, nullptr, y);
232 if (selected_placement_rule != info.placement_rule) {
233 ret = -EEXIST;
234 bucket_out->swap(bucket);
235 return ret;
236 }
237 } else {
238
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,
243 exclusive);
244 if (ret == -EEXIST) {
245 *existed = true;
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.
251 */
252 if (info.owner.compare(this->get_id()) != 0) {
253 return -EEXIST;
254 }
255 ret = 0;
256 } else if (ret != 0) {
257 return ret;
258 }
259 }
260
261 bucket->set_version(ep_objv);
262 bucket->get_info() = info;
263
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);
269 if (ret < 0) {
270 ldpp_dout(dpp, 0) << "WARNING: failed to unlink bucket: ret=" << ret
271 << dendl;
272 }
273 } else if (ret == -EEXIST || (ret == 0 && *existed)) {
274 ret = -ERR_BUCKET_EXISTS;
275 }
276
277 bucket_out->swap(bucket);
278
279 return ret;
280 }
281
282 int RadosUser::read_attrs(const DoutPrefixProvider* dpp, optional_yield y)
283 {
284 return store->ctl()->user->get_attrs_by_uid(dpp, get_id(), &attrs, y, &objv_tracker);
285 }
286
287 int RadosUser::merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y)
288 {
289 for(auto& it : new_attrs) {
290 attrs[it.first] = it.second;
291 }
292 return store_user(dpp, y, false);
293 }
294
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)
299 {
300 return store->ctl()->user->read_stats(dpp, get_id(), stats, y, last_stats_sync, last_stats_update);
301 }
302
303 int RadosUser::read_stats_async(const DoutPrefixProvider *dpp, RGWGetUserStats_CB* cb)
304 {
305 return store->ctl()->user->read_stats_async(dpp, get_id(), cb);
306 }
307
308 int RadosUser::complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y)
309 {
310 return store->ctl()->user->complete_flush_stats(dpp, get_id(), y);
311 }
312
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)
317 {
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,
321 usage_iter, usage);
322 }
323
324 int RadosUser::trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch)
325 {
326 std::string bucket_name;
327
328 return store->getRados()->trim_usage(dpp, get_id(), bucket_name, start_epoch, end_epoch);
329 }
330
331 int RadosUser::load_user(const DoutPrefixProvider* dpp, optional_yield y)
332 {
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));
334 }
335
336 int RadosUser::store_user(const DoutPrefixProvider* dpp, optional_yield y, bool exclusive, RGWUserInfo* old_info)
337 {
338 return store->ctl()->user->store_info(dpp, info, y,
339 RGWUserCtl::PutParams().set_objv_tracker(&objv_tracker)
340 .set_exclusive(exclusive)
341 .set_attrs(&attrs)
342 .set_old_info(old_info));
343 }
344
345 int RadosUser::remove_user(const DoutPrefixProvider* dpp, optional_yield y)
346 {
347 return store->ctl()->user->remove_info(dpp, info, y,
348 RGWUserCtl::RemoveParams().set_objv_tracker(&objv_tracker));
349 }
350
351 RadosBucket::~RadosBucket() {}
352
353 int RadosBucket::remove_bucket(const DoutPrefixProvider* dpp,
354 bool delete_children,
355 bool forward_to_master,
356 req_info* req_info,
357 optional_yield y)
358 {
359 int ret;
360
361 // Refresh info
362 ret = load_bucket(dpp, y);
363 if (ret < 0) {
364 return ret;
365 }
366
367 ListParams params;
368 params.list_versions = true;
369 params.allow_unordered = true;
370
371 ListResults results;
372
373 do {
374 results.objs.clear();
375
376 ret = list(dpp, params, 1000, results, y);
377 if (ret < 0) {
378 return ret;
379 }
380
381 if (!results.objs.empty() && !delete_children) {
382 ldpp_dout(dpp, -1) << "ERROR: could not remove non-empty bucket " << info.bucket.name <<
383 dendl;
384 return -ENOTEMPTY;
385 }
386
387 for (const auto& obj : results.objs) {
388 rgw_obj_key key(obj.key);
389 /* xxx dang */
390 ret = rgw_remove_object(dpp, store, this, key);
391 if (ret < 0 && ret != -ENOENT) {
392 return ret;
393 }
394 }
395 } while(results.is_truncated);
396
397 ret = abort_multiparts(dpp, store->ctx());
398 if (ret < 0) {
399 return ret;
400 }
401
402 // remove lifecycle config, if any (XXX note could be made generic)
403 (void) store->getRados()->get_lc()->remove_bucket_config(
404 this, get_attrs());
405
406 ret = store->ctl()->bucket->sync_user_stats(dpp, info.owner, info, y, nullptr);
407 if (ret < 0) {
408 ldout(store->ctx(), 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret << dendl;
409 }
410
411 RGWObjVersionTracker ot;
412
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);
416 if (ret < 0) {
417 ldpp_dout(dpp, -1) << "ERROR: could not remove bucket " <<
418 info.bucket.name << dendl;
419 return ret;
420 }
421
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;
429 }
430
431 ret = store->ctl()->bucket->unlink_bucket(info.owner, info.bucket, y, dpp, false);
432 if (ret < 0) {
433 ldpp_dout(dpp, -1) << "ERROR: unable to remove user bucket information" << dendl;
434 }
435
436 if (forward_to_master) {
437 bufferlist in_data;
438 ret = store->forward_request_to_master(dpp, owner, &ot.read_version, in_data, nullptr, *req_info, y);
439 if (ret < 0) {
440 if (ret == -ENOENT) {
441 /* adjust error, we want to return with NoSuchBucket and not
442 * NoSuchKey */
443 ret = -ERR_NO_SUCH_BUCKET;
444 }
445 return ret;
446 }
447 }
448
449 return ret;
450 }
451
452 int RadosBucket::remove_bucket_bypass_gc(int concurrent_max, bool
453 keep_index_consistent,
454 optional_yield y, const
455 DoutPrefixProvider *dpp)
456 {
457 int ret;
458 map<RGWObjCategory, RGWStorageStats> stats;
459 map<string, bool> common_prefixes;
460 RGWObjectCtx obj_ctx(store);
461 CephContext *cct = store->ctx();
462
463 string bucket_ver, master_ver;
464
465 ret = load_bucket(dpp, null_yield);
466 if (ret < 0)
467 return ret;
468
469 ret = read_stats(dpp, RGW_NO_SHARD, &bucket_ver, &master_ver, stats, NULL);
470 if (ret < 0)
471 return ret;
472
473 ret = abort_multiparts(dpp, cct);
474 if (ret < 0) {
475 return ret;
476 }
477
478 rgw::sal::Bucket::ListParams params;
479 rgw::sal::Bucket::ListResults results;
480
481 params.list_versions = true;
482 params.allow_unordered = true;
483
484 std::unique_ptr<rgw::sal::Completions> handles = store->get_completions();
485
486 int max_aio = concurrent_max;
487 results.is_truncated = true;
488
489 while (results.is_truncated) {
490 ret = list(dpp, params, listing_max_entries, results, null_yield);
491 if (ret < 0)
492 return ret;
493
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);
498
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;
502 continue;
503 }
504 if (ret < 0) {
505 ldpp_dout(dpp, -1) << "ERROR: get obj state returned with error " << ret << dendl;
506 return ret;
507 }
508
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);
515
516 for (; miter != manifest.obj_end(dpp) && max_aio--; ++miter) {
517 if (!max_aio) {
518 ret = handles->drain();
519 if (ret < 0) {
520 ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
521 return ret;
522 }
523 max_aio = concurrent_max;
524 }
525
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
529 continue;
530 }
531
532 ret = store->delete_raw_obj_aio(dpp, last_obj, handles.get());
533 if (ret < 0) {
534 ldpp_dout(dpp, -1) << "ERROR: delete obj aio failed with " << ret << dendl;
535 return ret;
536 }
537 } // for all shadow objs
538
539 ret = head_obj->delete_obj_aio(dpp, astate, handles.get(), keep_index_consistent, null_yield);
540 if (ret < 0) {
541 ldpp_dout(dpp, -1) << "ERROR: delete obj aio failed with " << ret << dendl;
542 return ret;
543 }
544 }
545
546 if (!max_aio) {
547 ret = handles->drain();
548 if (ret < 0) {
549 ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
550 return ret;
551 }
552 max_aio = concurrent_max;
553 }
554 obj_ctx.invalidate(obj->get_obj());
555 } // for all RGW objects in results
556 } // while is_truncated
557
558 ret = handles->drain();
559 if (ret < 0) {
560 ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
561 return ret;
562 }
563
564 sync_user_stats(dpp, y);
565 if (ret < 0) {
566 ldpp_dout(dpp, 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret << dendl;
567 }
568
569 RGWObjVersionTracker objv_tracker;
570
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);
575 if (ret < 0) {
576 ldpp_dout(dpp, -1) << "ERROR: could not remove bucket " << this << dendl;
577 return ret;
578 }
579
580 return ret;
581 }
582
583 int RadosBucket::load_bucket(const DoutPrefixProvider* dpp, optional_yield y, bool get_stats)
584 {
585 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
586 int ret;
587
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()
593 .set_mtime(&mtime)
594 .set_attrs(&attrs)
595 .set_bectx_params(bectx_params),
596 &ep_ot);
597 } else {
598 ret = store->ctl()->bucket->read_bucket_instance_info(info.bucket, &info, y, dpp,
599 RGWBucketCtl::BucketInstance::GetParams()
600 .set_mtime(&mtime)
601 .set_attrs(&attrs)
602 .set_bectx_params(bectx_params));
603 }
604 if (ret != 0) {
605 return ret;
606 }
607
608 bucket_version = ep_ot.read_version;
609
610 if (get_stats) {
611 ret = store->ctl()->bucket->read_bucket_stats(info.bucket, &ent, y, dpp);
612 }
613
614 return ret;
615 }
616
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)
621 {
622 return store->getRados()->get_bucket_stats(dpp, info, shard_id, bucket_ver, master_ver, stats, max_marker, syncstopped);
623 }
624
625 int RadosBucket::read_stats_async(const DoutPrefixProvider *dpp, int shard_id, RGWGetBucketStats_CB* ctx)
626 {
627 return store->getRados()->get_bucket_stats_async(dpp, get_info(), shard_id, ctx);
628 }
629
630 int RadosBucket::sync_user_stats(const DoutPrefixProvider *dpp, optional_yield y)
631 {
632 return store->ctl()->bucket->sync_user_stats(dpp, owner->get_id(), info, y, &ent);
633 }
634
635 int RadosBucket::update_container_stats(const DoutPrefixProvider* dpp)
636 {
637 int ret;
638 map<std::string, RGWBucketEnt> m;
639
640 m[info.bucket.name] = ent;
641 ret = store->getRados()->update_containers_stats(m, dpp);
642 if (!ret)
643 return -EEXIST;
644 if (ret < 0)
645 return ret;
646
647 map<std::string, RGWBucketEnt>::iterator iter = m.find(info.bucket.name);
648 if (iter == m.end())
649 return -EINVAL;
650
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);
656
657 info.creation_time = ent.creation_time;
658 info.placement_rule = ent.placement_rule;
659
660 return 0;
661 }
662
663 int RadosBucket::check_bucket_shards(const DoutPrefixProvider* dpp)
664 {
665 return store->getRados()->check_bucket_shards(info, info.bucket, get_count(), dpp);
666 }
667
668 int RadosBucket::link(const DoutPrefixProvider* dpp, User* new_user, optional_yield y, bool update_entrypoint, RGWObjVersionTracker* objv)
669 {
670 RGWBucketEntryPoint ep;
671 ep.bucket = info.bucket;
672 ep.owner = new_user->get_id();
673 ep.creation_time = get_creation_time();
674 ep.linked = true;
675 Attrs ep_attrs;
676 rgw_ep_info ep_data{ep, ep_attrs};
677
678 int r = store->ctl()->bucket->link_bucket(new_user->get_id(), info.bucket,
679 get_creation_time(), y, dpp, update_entrypoint,
680 &ep_data);
681 if (r < 0)
682 return r;
683
684 if (objv)
685 *objv = ep_data.ep_objv;
686
687 return r;
688 }
689
690 int RadosBucket::unlink(const DoutPrefixProvider* dpp, User* new_user, optional_yield y, bool update_entrypoint)
691 {
692 return store->ctl()->bucket->unlink_bucket(new_user->get_id(), info.bucket, y, dpp, update_entrypoint);
693 }
694
695 int RadosBucket::chown(const DoutPrefixProvider* dpp, User* new_user, User* old_user, optional_yield y, const std::string* marker)
696 {
697 std::string obj_marker;
698
699 if (marker == nullptr)
700 marker = &obj_marker;
701
702 int r = this->link(dpp, new_user, y);
703 if (r < 0) {
704 return r;
705 }
706 if (!old_user) {
707 return r;
708 }
709
710 return store->ctl()->bucket->chown(store, this, new_user->get_id(),
711 old_user->get_display_name(), *marker, y, dpp);
712 }
713
714 int RadosBucket::put_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time _mtime)
715 {
716 mtime = _mtime;
717 return store->getRados()->put_bucket_instance_info(info, exclusive, mtime, &attrs, dpp);
718 }
719
720 /* Make sure to call get_bucket_info() if you need it first */
721 bool RadosBucket::is_owner(User* user)
722 {
723 return (info.owner.compare(user->get_id()) == 0);
724 }
725
726 int RadosBucket::check_empty(const DoutPrefixProvider* dpp, optional_yield y)
727 {
728 return store->getRados()->check_bucket_empty(dpp, info, y);
729 }
730
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)
733 {
734 return store->getRados()->check_quota(dpp, owner->get_id(), get_key(),
735 user_quota, bucket_quota, obj_size, y, check_size_only);
736 }
737
738 int RadosBucket::merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y)
739 {
740 for(auto& it : new_attrs) {
741 attrs[it.first] = it.second;
742 }
743 return store->ctl()->bucket->set_bucket_instance_attrs(get_info(),
744 new_attrs, &get_info().objv_tracker, y, dpp);
745 }
746
747 int RadosBucket::try_refresh_info(const DoutPrefixProvider* dpp, ceph::real_time* pmtime)
748 {
749 return store->getRados()->try_refresh_bucket_info(info, pmtime, dpp, &attrs);
750 }
751
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)
756 {
757 return store->getRados()->read_usage(dpp, owner->get_id(), get_name(), start_epoch,
758 end_epoch, max_entries, is_truncated,
759 usage_iter, usage);
760 }
761
762 int RadosBucket::trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch)
763 {
764 return store->getRados()->trim_usage(dpp, owner->get_id(), get_name(), start_epoch, end_epoch);
765 }
766
767 int RadosBucket::remove_objs_from_index(const DoutPrefixProvider *dpp, std::list<rgw_obj_index_key>& objs_to_unlink)
768 {
769 return store->getRados()->remove_objs_from_index(dpp, info, objs_to_unlink);
770 }
771
772 int RadosBucket::check_index(const DoutPrefixProvider *dpp, std::map<RGWObjCategory, RGWStorageStats>& existing_stats, std::map<RGWObjCategory, RGWStorageStats>& calculated_stats)
773 {
774 return store->getRados()->bucket_check_index(dpp, info, &existing_stats, &calculated_stats);
775 }
776
777 int RadosBucket::rebuild_index(const DoutPrefixProvider *dpp)
778 {
779 return store->getRados()->bucket_rebuild_index(dpp, info);
780 }
781
782 int RadosBucket::set_tag_timeout(const DoutPrefixProvider *dpp, uint64_t timeout)
783 {
784 return store->getRados()->cls_obj_set_bucket_tag_timeout(dpp, info, timeout);
785 }
786
787 int RadosBucket::purge_instance(const DoutPrefixProvider* dpp)
788 {
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);
794 if (ret < 0) {
795 cerr << "ERROR: bs.init(bucket=" << info.bucket << ", shard=" << shard_id
796 << "): " << cpp_strerror(-ret) << std::endl;
797 return ret;
798 }
799 ret = store->getRados()->bi_remove(dpp, bs);
800 if (ret < 0) {
801 cerr << "ERROR: failed to remove bucket index object: "
802 << cpp_strerror(-ret) << std::endl;
803 return ret;
804 }
805 }
806 return 0;
807 }
808
809 int RadosBucket::set_acl(const DoutPrefixProvider* dpp, RGWAccessControlPolicy &acl, optional_yield y)
810 {
811 bufferlist aclbl;
812
813 acls = acl;
814 acl.encode(aclbl);
815 map<string, bufferlist>& attrs = get_attrs();
816
817 attrs[RGW_ATTR_ACL] = aclbl;
818 info.owner = acl.get_owner().get_id();
819
820 int r = store->ctl()->bucket->store_bucket_instance_info(info.bucket,
821 info, y, dpp,
822 RGWBucketCtl::BucketInstance::PutParams().set_attrs(&attrs));
823 if (r < 0) {
824 cerr << "ERROR: failed to set bucket owner: " << cpp_strerror(-r) << std::endl;
825 return r;
826 }
827
828 return 0;
829 }
830
831 std::unique_ptr<Object> RadosBucket::get_object(const rgw_obj_key& k)
832 {
833 return std::make_unique<RadosObject>(this->store, k, this);
834 }
835
836 int RadosBucket::list(const DoutPrefixProvider* dpp, ListParams& params, int max, ListResults& results, optional_yield y)
837 {
838 RGWRados::Bucket target(store->getRados(), get_info());
839 if (params.shard_id >= 0) {
840 target.set_shard_id(params.shard_id);
841 }
842 RGWRados::Bucket::List list_op(&target);
843
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;
855
856 int ret = list_op.list_objects(dpp, max, &results.objs, &results.common_prefixes, &results.is_truncated, y);
857 if (ret >= 0) {
858 results.next_marker = list_op.get_next_marker();
859 params.marker = results.next_marker;
860 }
861
862 return ret;
863 }
864
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)
869 {
870 return std::make_unique<RadosMultipartUpload>(this->store, this, oid, upload_id,
871 std::move(owner), mtime);
872 }
873
874 int RadosBucket::list_multiparts(const DoutPrefixProvider *dpp,
875 const string& prefix,
876 string& marker,
877 const string& delim,
878 const int& max_uploads,
879 vector<std::unique_ptr<MultipartUpload>>& uploads,
880 map<string, bool> *common_prefixes,
881 bool *is_truncated)
882 {
883 rgw::sal::Bucket::ListParams params;
884 rgw::sal::Bucket::ListResults results;
885 MultipartMetaFilter mp_filter;
886
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;
892
893 int ret = list(dpp, params, max_uploads, results, null_yield);
894
895 if (ret < 0)
896 return ret;
897
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)));
905 }
906 }
907 if (common_prefixes) {
908 *common_prefixes = std::move(results.common_prefixes);
909 }
910 *is_truncated = results.is_truncated;
911 marker = params.marker.name;
912
913 return 0;
914 }
915
916 int RadosBucket::abort_multiparts(const DoutPrefixProvider* dpp,
917 CephContext* cct)
918 {
919 constexpr int max = 1000;
920 int ret, num_deleted = 0;
921 vector<std::unique_ptr<MultipartUpload>> uploads;
922 RGWObjectCtx obj_ctx(store);
923 string marker;
924 bool is_truncated;
925
926 const std::string empty_delim;
927 const std::string empty_prefix;
928
929 do {
930 ret = list_multiparts(dpp, empty_prefix, marker, empty_delim,
931 max, uploads, nullptr, &is_truncated);
932 if (ret < 0) {
933 ldpp_dout(dpp, 0) << __func__ <<
934 " ERROR : calling list_bucket_multiparts; ret=" << ret <<
935 "; bucket=\"" << this << "\"" << dendl;
936 return ret;
937 }
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;
942
943 if (!uploads.empty()) {
944 for (const auto& upload : uploads) {
945 ret = upload->abort(dpp, cct, &obj_ctx);
946 if (ret < 0) {
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;
953 return ret;
954 } else {
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;
959 }
960 }
961 num_deleted++;
962 }
963 if (num_deleted) {
964 ldpp_dout(dpp, 0) << __func__ <<
965 " WARNING : aborted " << num_deleted <<
966 " incomplete multipart uploads" << dendl;
967 }
968 }
969 } while (is_truncated);
970
971 return 0;
972 }
973
974 std::unique_ptr<User> RadosStore::get_user(const rgw_user &u)
975 {
976 return std::make_unique<RadosUser>(this, u);
977 }
978
979 std::string RadosStore::get_cluster_id(const DoutPrefixProvider* dpp, optional_yield y)
980 {
981 return getRados()->get_cluster_fsid(dpp, y);
982 }
983
984 int RadosStore::get_user_by_access_key(const DoutPrefixProvider* dpp, const std::string& key, optional_yield y, std::unique_ptr<User>* user)
985 {
986 RGWUserInfo uinfo;
987 User* u;
988 RGWObjVersionTracker objv_tracker;
989
990 int r = ctl()->user->get_info_by_access_key(dpp, key, &uinfo, y, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker));
991 if (r < 0)
992 return r;
993
994 u = new RadosUser(this, uinfo);
995 if (!u)
996 return -ENOMEM;
997
998 u->get_version_tracker() = objv_tracker;
999
1000 user->reset(u);
1001 return 0;
1002 }
1003
1004 int RadosStore::get_user_by_email(const DoutPrefixProvider* dpp, const std::string& email, optional_yield y, std::unique_ptr<User>* user)
1005 {
1006 RGWUserInfo uinfo;
1007 User* u;
1008 RGWObjVersionTracker objv_tracker;
1009
1010 int r = ctl()->user->get_info_by_email(dpp, email, &uinfo, y, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker));
1011 if (r < 0)
1012 return r;
1013
1014 u = new RadosUser(this, uinfo);
1015 if (!u)
1016 return -ENOMEM;
1017
1018 u->get_version_tracker() = objv_tracker;
1019
1020 user->reset(u);
1021 return 0;
1022 }
1023
1024 int RadosStore::get_user_by_swift(const DoutPrefixProvider* dpp, const std::string& user_str, optional_yield y, std::unique_ptr<User>* user)
1025 {
1026 RGWUserInfo uinfo;
1027 User* u;
1028 RGWObjVersionTracker objv_tracker;
1029
1030 int r = ctl()->user->get_info_by_swift(dpp, user_str, &uinfo, y, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker));
1031 if (r < 0)
1032 return r;
1033
1034 u = new RadosUser(this, uinfo);
1035 if (!u)
1036 return -ENOMEM;
1037
1038 u->get_version_tracker() = objv_tracker;
1039
1040 user->reset(u);
1041 return 0;
1042 }
1043
1044 std::unique_ptr<Object> RadosStore::get_object(const rgw_obj_key& k)
1045 {
1046 return std::make_unique<RadosObject>(this, k);
1047 }
1048
1049 int RadosStore::get_bucket(const DoutPrefixProvider* dpp, User* u, const rgw_bucket& b, std::unique_ptr<Bucket>* bucket, optional_yield y)
1050 {
1051 int ret;
1052 Bucket* bp;
1053
1054 bp = new RadosBucket(this, b, u);
1055 ret = bp->load_bucket(dpp, y);
1056 if (ret < 0) {
1057 delete bp;
1058 return ret;
1059 }
1060
1061 bucket->reset(bp);
1062 return 0;
1063 }
1064
1065 int RadosStore::get_bucket(User* u, const RGWBucketInfo& i, std::unique_ptr<Bucket>* bucket)
1066 {
1067 Bucket* bp;
1068
1069 bp = new RadosBucket(this, i, u);
1070 /* Don't need to fetch the bucket info, use the provided one */
1071
1072 bucket->reset(bp);
1073 return 0;
1074 }
1075
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)
1077 {
1078 rgw_bucket b;
1079
1080 b.tenant = tenant;
1081 b.name = name;
1082
1083 return get_bucket(dpp, u, b, bucket, y);
1084 }
1085
1086 bool RadosStore::is_meta_master()
1087 {
1088 return svc()->zone->is_meta_master();
1089 }
1090
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,
1094 optional_yield y)
1095 {
1096 if (is_meta_master()) {
1097 /* We're master, don't forward */
1098 return 0;
1099 }
1100
1101 if (!svc()->zone->get_master_conn()) {
1102 ldpp_dout(dpp, 0) << "rest connection is invalid" << dendl;
1103 return -EINVAL;
1104 }
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);
1112 if (ret < 0)
1113 return ret;
1114
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;
1118 return -EINVAL;
1119 }
1120
1121 return 0;
1122 }
1123
1124 std::string RadosStore::zone_unique_id(uint64_t unique_num)
1125 {
1126 return svc()->zone_utils->unique_id(unique_num);
1127 }
1128
1129 std::string RadosStore::zone_unique_trans_id(const uint64_t unique_num)
1130 {
1131 return svc()->zone_utils->unique_trans_id(unique_num);
1132 }
1133
1134 int RadosStore::cluster_stat(RGWClusterStat& stats)
1135 {
1136 rados_cluster_stat_t rados_stats;
1137 int ret;
1138
1139 ret = rados->get_rados_handle()->cluster_stat(rados_stats);
1140 if (ret < 0)
1141 return ret;
1142
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;
1147
1148 return ret;
1149 }
1150
1151 std::unique_ptr<Lifecycle> RadosStore::get_lifecycle(void)
1152 {
1153 return std::make_unique<RadosLifecycle>(this);
1154 }
1155
1156 std::unique_ptr<Completions> RadosStore::get_completions(void)
1157 {
1158 return std::make_unique<RadosCompletions>();
1159 }
1160
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)
1163 {
1164 return std::make_unique<RadosNotification>(s, this, obj, src_obj, s, event_type, object_name);
1165 }
1166
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)
1168 {
1169 return std::make_unique<RadosNotification>(dpp, this, obj, src_obj, rctx, event_type, _bucket, _user_id, _user_tenant, _req_id, y);
1170 }
1171
1172 int RadosStore::delete_raw_obj(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj)
1173 {
1174 return rados->delete_raw_obj(dpp, obj);
1175 }
1176
1177 int RadosStore::delete_raw_obj_aio(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj, Completions* aio)
1178 {
1179 RadosCompletions* raio = static_cast<RadosCompletions*>(aio);
1180
1181 return rados->delete_raw_obj_aio(dpp, obj, raio->handles);
1182 }
1183
1184 void RadosStore::get_raw_obj(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_raw_obj* raw_obj)
1185 {
1186 rados->obj_to_raw(placement_rule, obj, raw_obj);
1187 }
1188
1189 int RadosStore::get_raw_chunk_size(const DoutPrefixProvider* dpp, const rgw_raw_obj& obj, uint64_t* chunk_size)
1190 {
1191 return rados->get_max_chunk_size(obj.pool, chunk_size, dpp);
1192 }
1193
1194 int RadosStore::log_usage(const DoutPrefixProvider *dpp, map<rgw_user_bucket, RGWUsageBatch>& usage_info)
1195 {
1196 return rados->log_usage(dpp, usage_info);
1197 }
1198
1199 int RadosStore::log_op(const DoutPrefixProvider *dpp, std::string& oid, bufferlist& bl)
1200 {
1201 rgw_raw_obj obj(svc()->zone->get_zone_params().log_pool, oid);
1202
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);
1206 if (ret < 0)
1207 return ret;
1208 // retry
1209 ret = rados->append_async(dpp, obj, bl.length(), bl);
1210 }
1211
1212 return ret;
1213 }
1214
1215 int RadosStore::register_to_service_map(const DoutPrefixProvider *dpp, const std::string& daemon_type,
1216 const map<std::string, std::string>& meta)
1217 {
1218 return rados->register_to_service_map(dpp, daemon_type, meta);
1219 }
1220
1221 void RadosStore::get_quota(RGWQuotaInfo& bucket_quota, RGWQuotaInfo& user_quota)
1222 {
1223 bucket_quota = svc()->quota->get_bucket_quota();
1224 user_quota = svc()->quota->get_user_quota();
1225 }
1226
1227 void RadosStore::get_ratelimit(RGWRateLimitInfo& bucket_ratelimit, RGWRateLimitInfo& user_ratelimit, RGWRateLimitInfo& anon_ratelimit)
1228 {
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;
1232 }
1233
1234 int RadosStore::set_buckets_enabled(const DoutPrefixProvider* dpp, vector<rgw_bucket>& buckets, bool enabled)
1235 {
1236 return rados->set_buckets_enabled(buckets, enabled, dpp);
1237 }
1238
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,
1243 optional_yield y)
1244 {
1245 return ctl()->bucket->get_sync_policy_handler(zone, bucket, phandler, y, dpp);
1246 }
1247
1248 RGWDataSyncStatusManager* RadosStore::get_data_sync_manager(const rgw_zone_id& source_zone)
1249 {
1250 return rados->get_data_sync_manager(source_zone);
1251 }
1252
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)
1257 {
1258 rgw_user uid;
1259 std::string bucket_name;
1260
1261 return rados->read_usage(dpp, uid, bucket_name, start_epoch, end_epoch, max_entries,
1262 is_truncated, usage_iter, usage);
1263 }
1264
1265 int RadosStore::trim_all_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch)
1266 {
1267 rgw_user uid;
1268 std::string bucket_name;
1269
1270 return rados->trim_usage(dpp, uid, bucket_name, start_epoch, end_epoch);
1271 }
1272
1273 int RadosStore::get_config_key_val(std::string name, bufferlist* bl)
1274 {
1275 return svc()->config_key->get(name, true, bl);
1276 }
1277
1278 int RadosStore::meta_list_keys_init(const DoutPrefixProvider *dpp, const std::string& section, const std::string& marker, void** phandle)
1279 {
1280 return ctl()->meta.mgr->list_keys_init(dpp, section, marker, phandle);
1281 }
1282
1283 int RadosStore::meta_list_keys_next(const DoutPrefixProvider *dpp, void* handle, int max, list<std::string>& keys, bool* truncated)
1284 {
1285 return ctl()->meta.mgr->list_keys_next(dpp, handle, max, keys, truncated);
1286 }
1287
1288 void RadosStore::meta_list_keys_complete(void* handle)
1289 {
1290 ctl()->meta.mgr->list_keys_complete(handle);
1291 }
1292
1293 std::string RadosStore::meta_get_marker(void* handle)
1294 {
1295 return ctl()->meta.mgr->get_marker(handle);
1296 }
1297
1298 int RadosStore::meta_remove(const DoutPrefixProvider* dpp, std::string& metadata_key, optional_yield y)
1299 {
1300 return ctl()->meta.mgr->remove(metadata_key, y, dpp);
1301 }
1302
1303 void RadosStore::finalize(void)
1304 {
1305 if (rados)
1306 rados->finalize();
1307 }
1308
1309 std::unique_ptr<LuaScriptManager> RadosStore::get_lua_script_manager()
1310 {
1311 return std::make_unique<RadosLuaScriptManager>(this);
1312 }
1313
1314 std::unique_ptr<RGWRole> RadosStore::get_role(std::string name,
1315 std::string tenant,
1316 std::string path,
1317 std::string trust_policy,
1318 std::string max_session_duration_str,
1319 std::multimap<std::string,std::string> tags)
1320 {
1321 return std::make_unique<RadosRole>(this, name, tenant, path, trust_policy, max_session_duration_str, tags);
1322 }
1323
1324 std::unique_ptr<RGWRole> RadosStore::get_role(std::string id)
1325 {
1326 return std::make_unique<RadosRole>(this, id);
1327 }
1328
1329 int RadosStore::get_roles(const DoutPrefixProvider *dpp,
1330 optional_yield y,
1331 const std::string& path_prefix,
1332 const std::string& tenant,
1333 vector<std::unique_ptr<RGWRole>>& roles)
1334 {
1335 auto pool = get_zone()->get_params().roles_pool;
1336 std::string prefix;
1337
1338 // List all roles if path prefix is empty
1339 if (! path_prefix.empty()) {
1340 prefix = tenant + RGWRole::role_path_oid_prefix + path_prefix;
1341 } else {
1342 prefix = tenant + RGWRole::role_path_oid_prefix;
1343 }
1344
1345 //Get the filtered objects
1346 list<std::string> result;
1347 bool is_truncated;
1348 RGWListRawObjsCtx ctx;
1349 do {
1350 list<std::string> oids;
1351 int r = rados->list_raw_objects(dpp, pool, prefix, 1000, ctx, oids, &is_truncated);
1352 if (r < 0) {
1353 ldpp_dout(dpp, 0) << "ERROR: listing filtered objects failed: "
1354 << prefix << ": " << cpp_strerror(-r) << dendl;
1355 return r;
1356 }
1357 for (const auto& iter : oids) {
1358 result.push_back(iter.substr(RGWRole::role_path_oid_prefix.size()));
1359 }
1360 } while (is_truncated);
1361
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) {
1366 continue;
1367 }
1368 // Split the result into path and info_oid + id
1369 std::string path = it.substr(0, pos);
1370
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());
1376
1377 std::unique_ptr<rgw::sal::RGWRole> role = get_role(id);
1378 int ret = role->read_info(dpp, y);
1379 if (ret < 0) {
1380 return ret;
1381 }
1382 roles.push_back(std::move(role));
1383 }
1384 }
1385
1386 return 0;
1387 }
1388
1389 std::unique_ptr<RGWOIDCProvider> RadosStore::get_oidc_provider()
1390 {
1391 return std::make_unique<RadosOIDCProvider>(this);
1392 }
1393
1394 int RadosStore::get_oidc_providers(const DoutPrefixProvider *dpp,
1395 const std::string& tenant,
1396 vector<std::unique_ptr<RGWOIDCProvider>>& providers)
1397 {
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();
1401
1402 //Get the filtered objects
1403 list<std::string> result;
1404 bool is_truncated;
1405 RGWListRawObjsCtx ctx;
1406 do {
1407 list<std::string> oids;
1408 int r = rados->list_raw_objects(dpp, pool, prefix, 1000, ctx, oids, &is_truncated);
1409 if (r < 0) {
1410 ldpp_dout(dpp, 0) << "ERROR: listing filtered objects failed: OIDC pool: "
1411 << pool.name << ": " << prefix << ": " << cpp_strerror(-r) << dendl;
1412 return r;
1413 }
1414 for (const auto& iter : oids) {
1415 std::unique_ptr<rgw::sal::RGWOIDCProvider> provider = get_oidc_provider();
1416 bufferlist bl;
1417
1418 r = rgw_get_system_obj(obj_ctx, pool, iter, bl, nullptr, nullptr, null_yield, dpp);
1419 if (r < 0) {
1420 return r;
1421 }
1422
1423 try {
1424 using ceph::decode;
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;
1430 return -EIO;
1431 }
1432
1433 providers.push_back(std::move(provider));
1434 }
1435 } while (is_truncated);
1436
1437 return 0;
1438 }
1439
1440 std::unique_ptr<Writer> RadosStore::get_append_writer(const DoutPrefixProvider *dpp,
1441 optional_yield y,
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,
1446 uint64_t position,
1447 uint64_t *cur_accounted_size)
1448 {
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);
1456 }
1457
1458 std::unique_ptr<Writer> RadosStore::get_atomic_writer(const DoutPrefixProvider *dpp,
1459 optional_yield y,
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,
1463 uint64_t olh_epoch,
1464 const std::string& unique_tag)
1465 {
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);
1472 }
1473
1474 int RadosStore::get_obj_head_ioctx(const DoutPrefixProvider *dpp, const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::IoCtx* ioctx)
1475 {
1476 return rados->get_obj_head_ioctx(dpp, bucket_info, obj, ioctx);
1477 }
1478
1479 RadosObject::~RadosObject() {}
1480
1481 int RadosObject::get_obj_state(const DoutPrefixProvider* dpp, RGWObjectCtx* rctx, RGWObjState **state, optional_yield y, bool follow_olh)
1482 {
1483 return store->getRados()->get_obj_state(dpp, rctx, bucket->get_info(), get_obj(), state, follow_olh, y);
1484 }
1485
1486 int RadosObject::read_attrs(const DoutPrefixProvider* dpp, RGWRados::Object::Read &read_op, optional_yield y, rgw_obj* target_obj)
1487 {
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;
1492
1493 return read_op.prepare(y, dpp);
1494 }
1495
1496 int RadosObject::set_obj_attrs(const DoutPrefixProvider* dpp, RGWObjectCtx* rctx, Attrs* setattrs, Attrs* delattrs, optional_yield y, rgw_obj* target_obj)
1497 {
1498 Attrs empty;
1499 rgw_obj target = get_obj();
1500
1501 if (!target_obj)
1502 target_obj = &target;
1503
1504 return store->getRados()->set_attrs(dpp, rctx,
1505 bucket->get_info(),
1506 *target_obj,
1507 setattrs ? *setattrs : empty,
1508 delattrs ? delattrs : nullptr,
1509 y);
1510 }
1511
1512 int RadosObject::get_obj_attrs(RGWObjectCtx* rctx, optional_yield y, const DoutPrefixProvider* dpp, rgw_obj* target_obj)
1513 {
1514 RGWRados::Object op_target(store->getRados(), bucket->get_info(), *rctx, get_obj());
1515 RGWRados::Object::Read read_op(&op_target);
1516
1517 return read_attrs(dpp, read_op, y, target_obj);
1518 }
1519
1520 int RadosObject::modify_obj_attrs(RGWObjectCtx* rctx, const char* attr_name, bufferlist& attr_val, optional_yield y, const DoutPrefixProvider* dpp)
1521 {
1522 rgw_obj target = get_obj();
1523 int r = get_obj_attrs(rctx, y, dpp, &target);
1524 if (r < 0) {
1525 return r;
1526 }
1527 set_atomic(rctx);
1528 attrs[attr_name] = attr_val;
1529 return set_obj_attrs(dpp, rctx, &attrs, nullptr, y, &target);
1530 }
1531
1532 int RadosObject::delete_obj_attrs(const DoutPrefixProvider* dpp, RGWObjectCtx* rctx, const char* attr_name, optional_yield y)
1533 {
1534 Attrs rmattr;
1535 bufferlist bl;
1536
1537 set_atomic(rctx);
1538 rmattr[attr_name] = bl;
1539 return set_obj_attrs(dpp, rctx, nullptr, &rmattr, y);
1540 }
1541
1542 void RadosObject::set_compressed(RGWObjectCtx* rctx) {
1543 rgw_obj obj = get_obj();
1544 store->getRados()->set_compressed(rctx, obj);
1545 }
1546
1547 void RadosObject::set_atomic(RGWObjectCtx* rctx) const
1548 {
1549 rgw_obj obj = get_obj();
1550 store->getRados()->set_atomic(rctx, obj);
1551 }
1552
1553 void RadosObject::set_prefetch_data(RGWObjectCtx* rctx)
1554 {
1555 rgw_obj obj = get_obj();
1556 store->getRados()->set_prefetch_data(rctx, obj);
1557 }
1558
1559 bool RadosObject::is_expired() {
1560 auto iter = attrs.find(RGW_ATTR_DELETE_AT);
1561 if (iter != attrs.end()) {
1562 utime_t delete_at;
1563 try {
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;
1568 return false;
1569 }
1570
1571 if (delete_at <= ceph_clock_now() && !delete_at.is_zero()) {
1572 return true;
1573 }
1574 }
1575
1576 return false;
1577 }
1578
1579 void RadosObject::gen_rand_obj_instance_name()
1580 {
1581 store->getRados()->gen_rand_obj_instance_name(&key);
1582 }
1583
1584 void RadosObject::raw_obj_to_obj(const rgw_raw_obj& raw_obj)
1585 {
1586 rgw_obj tobj = get_obj();
1587 RGWSI_Tier_RADOS::raw_obj_to_obj(get_bucket()->get_key(), raw_obj, &tobj);
1588 set_key(tobj.key);
1589 }
1590
1591 void RadosObject::get_raw_obj(rgw_raw_obj* raw_obj)
1592 {
1593 store->getRados()->obj_to_raw((bucket->get_info()).placement_rule, get_obj(), raw_obj);
1594 }
1595
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)
1599 {
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);
1604
1605 return sysobj.omap().get_vals(dpp, marker, count, m, pmore, y);
1606 }
1607
1608 int RadosObject::omap_get_all(const DoutPrefixProvider *dpp, std::map<std::string, bufferlist> *m,
1609 optional_yield y)
1610 {
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);
1615
1616 return sysobj.omap().get_all(dpp, m, y);
1617 }
1618
1619 int RadosObject::omap_get_vals_by_keys(const DoutPrefixProvider *dpp, const std::string& oid,
1620 const std::set<std::string>& keys,
1621 Attrs* vals)
1622 {
1623 int ret;
1624 rgw_raw_obj head_obj;
1625 librados::IoCtx cur_ioctx;
1626 rgw_obj obj = get_obj();
1627
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);
1630 if (ret < 0) {
1631 return ret;
1632 }
1633
1634 return cur_ioctx.omap_get_vals_by_keys(oid, keys, vals);
1635 }
1636
1637 int RadosObject::omap_set_val_by_key(const DoutPrefixProvider *dpp, const std::string& key, bufferlist& val,
1638 bool must_exist, optional_yield y)
1639 {
1640 rgw_raw_obj raw_meta_obj;
1641 rgw_obj obj = get_obj();
1642
1643 store->getRados()->obj_to_raw(bucket->get_placement_rule(), obj, &raw_meta_obj);
1644
1645 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
1646 auto sysobj = obj_ctx.get_obj(raw_meta_obj);
1647
1648 return sysobj.omap().set_must_exist(must_exist).set(dpp, key, val, y);
1649 }
1650
1651 MPSerializer* RadosObject::get_serializer(const DoutPrefixProvider *dpp, const std::string& lock_name)
1652 {
1653 return new MPRadosSerializer(dpp, store, this, lock_name);
1654 }
1655
1656 int RadosObject::transition(RGWObjectCtx& rctx,
1657 Bucket* bucket,
1658 const rgw_placement_rule& placement_rule,
1659 const real_time& mtime,
1660 uint64_t olh_epoch,
1661 const DoutPrefixProvider* dpp,
1662 optional_yield y)
1663 {
1664 return store->getRados()->transition_obj(rctx, bucket, *this, placement_rule, mtime, olh_epoch, dpp, y);
1665 }
1666
1667 int RadosObject::get_max_chunk_size(const DoutPrefixProvider* dpp, rgw_placement_rule placement_rule, uint64_t* max_chunk_size, uint64_t* alignment)
1668 {
1669 return store->getRados()->get_max_chunk_size(placement_rule, get_obj(), max_chunk_size, dpp, alignment);
1670 }
1671
1672 void RadosObject::get_max_aligned_size(uint64_t size, uint64_t alignment,
1673 uint64_t* max_size)
1674 {
1675 store->getRados()->get_max_aligned_size(size, alignment, max_size);
1676 }
1677
1678 bool RadosObject::placement_rules_match(rgw_placement_rule& r1, rgw_placement_rule& r2)
1679 {
1680 rgw_obj obj;
1681 rgw_pool p1, p2;
1682
1683 obj = get_obj();
1684
1685 if (r1 == r2)
1686 return true;
1687
1688 if (!store->getRados()->get_obj_data_pool(r1, obj, &p1)) {
1689 return false;
1690 }
1691 if (!store->getRados()->get_obj_data_pool(r2, obj, &p2)) {
1692 return false;
1693 }
1694
1695 return p1 == p2;
1696 }
1697
1698 int RadosObject::dump_obj_layout(const DoutPrefixProvider *dpp, optional_yield y, Formatter* f, RGWObjectCtx* obj_ctx)
1699 {
1700 int ret;
1701 RGWObjManifest *manifest{nullptr};
1702 rgw_raw_obj head_obj;
1703
1704 RGWRados::Object op_target(store->getRados(), get_bucket()->get_info(),
1705 *obj_ctx, get_obj());
1706 RGWRados::Object::Read parent_op(&op_target);
1707 uint64_t obj_size;
1708
1709 parent_op.params.obj_size = &obj_size;
1710 parent_op.params.attrs = &get_attrs();
1711
1712 ret = parent_op.prepare(y, dpp);
1713 if (ret < 0) {
1714 return ret;
1715 }
1716
1717 head_obj = parent_op.state.head_obj;
1718
1719 ret = op_target.get_manifest(dpp, &manifest, y);
1720 if (ret < 0) {
1721 return ret;
1722 }
1723
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) {
1737 loc_size = left;
1738 }
1739 ::encode_json("loc_size", loc_size, f);
1740 f->close_section();
1741 }
1742 f->close_section();
1743
1744 return 0;
1745 }
1746
1747 std::unique_ptr<Object::ReadOp> RadosObject::get_read_op(RGWObjectCtx* ctx)
1748 {
1749 return std::make_unique<RadosObject::RadosReadOp>(this, ctx);
1750 }
1751
1752 RadosObject::RadosReadOp::RadosReadOp(RadosObject *_source, RGWObjectCtx *_rctx) :
1753 source(_source),
1754 rctx(_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)
1760 { }
1761
1762 int RadosObject::RadosReadOp::prepare(optional_yield y, const DoutPrefixProvider* dpp)
1763 {
1764 uint64_t obj_size;
1765
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();
1777
1778 int ret = parent_op.prepare(y, dpp);
1779 if (ret < 0)
1780 return ret;
1781
1782 source->set_key(parent_op.state.obj.key);
1783 source->set_obj_size(obj_size);
1784
1785 return ret;
1786 }
1787
1788 int RadosObject::RadosReadOp::read(int64_t ofs, int64_t end, bufferlist& bl, optional_yield y, const DoutPrefixProvider* dpp)
1789 {
1790 return parent_op.read(ofs, end, bl, y, dpp);
1791 }
1792
1793 int RadosObject::RadosReadOp::get_attr(const DoutPrefixProvider* dpp, const char* name, bufferlist& dest, optional_yield y)
1794 {
1795 return parent_op.get_attr(dpp, name, dest, y);
1796 }
1797
1798 std::unique_ptr<Object::DeleteOp> RadosObject::get_delete_op(RGWObjectCtx* ctx)
1799 {
1800 return std::make_unique<RadosObject::RadosDeleteOp>(this, ctx);
1801 }
1802
1803 RadosObject::RadosDeleteOp::RadosDeleteOp(RadosObject *_source, RGWObjectCtx *_rctx) :
1804 source(_source),
1805 rctx(_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)
1811 { }
1812
1813 int RadosObject::RadosDeleteOp::delete_obj(const DoutPrefixProvider* dpp, optional_yield y)
1814 {
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;
1829
1830 int ret = parent_op.delete_obj(y, dpp);
1831 if (ret < 0)
1832 return ret;
1833
1834 result.delete_marker = parent_op.result.delete_marker;
1835 result.version_id = parent_op.result.version_id;
1836
1837 return ret;
1838 }
1839
1840 int RadosObject::delete_object(const DoutPrefixProvider* dpp,
1841 RGWObjectCtx* obj_ctx,
1842 optional_yield y,
1843 bool prevent_versioning)
1844 {
1845 RGWRados::Object del_target(store->getRados(), bucket->get_info(), *obj_ctx, get_obj());
1846 RGWRados::Object::Delete del_op(&del_target);
1847
1848 del_op.params.bucket_owner = bucket->get_info().owner;
1849 del_op.params.versioning_status = prevent_versioning ? 0 : bucket->get_info().versioning_status();
1850
1851 return del_op.delete_obj(y, dpp);
1852 }
1853
1854 int RadosObject::delete_obj_aio(const DoutPrefixProvider* dpp, RGWObjState* astate,
1855 Completions* aio, bool keep_index_consistent,
1856 optional_yield y)
1857 {
1858 RadosCompletions* raio = static_cast<RadosCompletions*>(aio);
1859
1860 return store->getRados()->delete_obj_aio(dpp, get_obj(), bucket->get_info(), astate,
1861 raio->handles, keep_index_consistent, y);
1862 }
1863
1864 int RadosObject::copy_object(RGWObjectCtx& obj_ctx,
1865 User* user,
1866 req_info* info,
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,
1879 AttrsMod attrs_mod,
1880 bool copy_if_newer,
1881 Attrs& attrs,
1882 RGWObjCategory category,
1883 uint64_t olh_epoch,
1884 boost::optional<ceph::real_time> delete_at,
1885 std::string* version_id,
1886 std::string* tag,
1887 std::string* etag,
1888 void (*progress_cb)(off_t, void *),
1889 void* progress_data,
1890 const DoutPrefixProvider* dpp,
1891 optional_yield y)
1892 {
1893 return store->getRados()->copy_obj(obj_ctx,
1894 user->get_id(),
1895 info,
1896 source_zone,
1897 dest_object,
1898 this,
1899 dest_bucket,
1900 src_bucket,
1901 dest_placement,
1902 src_mtime,
1903 mtime,
1904 mod_ptr,
1905 unmod_ptr,
1906 high_precision_time,
1907 if_match,
1908 if_nomatch,
1909 static_cast<RGWRados::AttrsMod>(attrs_mod),
1910 copy_if_newer,
1911 attrs,
1912 category,
1913 olh_epoch,
1914 (delete_at ? *delete_at : real_time()),
1915 version_id,
1916 tag,
1917 etag,
1918 progress_cb,
1919 progress_data,
1920 dpp,
1921 y);
1922 }
1923
1924 int RadosObject::RadosReadOp::iterate(const DoutPrefixProvider* dpp, int64_t ofs, int64_t end, RGWGetDataCB* cb, optional_yield y)
1925 {
1926 return parent_op.iterate(dpp, ofs, end, cb, y);
1927 }
1928
1929 int RadosObject::swift_versioning_restore(RGWObjectCtx* obj_ctx,
1930 bool& restored,
1931 const DoutPrefixProvider* dpp)
1932 {
1933 return store->getRados()->swift_versioning_restore(*obj_ctx,
1934 bucket->get_owner()->get_id(),
1935 bucket,
1936 this,
1937 restored,
1938 dpp);
1939 }
1940
1941 int RadosObject::swift_versioning_copy(RGWObjectCtx* obj_ctx,
1942 const DoutPrefixProvider* dpp,
1943 optional_yield y)
1944 {
1945 return store->getRados()->swift_versioning_copy(*obj_ctx,
1946 bucket->get_info().owner,
1947 bucket,
1948 this,
1949 dpp,
1950 y);
1951 }
1952
1953 int RadosMultipartUpload::abort(const DoutPrefixProvider *dpp, CephContext *cct,
1954 RGWObjectCtx *obj_ctx)
1955 {
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;
1961 bool truncated;
1962 int marker = 0;
1963 int ret;
1964 uint64_t parts_accounted_size = 0;
1965
1966 do {
1967 ret = list_parts(dpp, cct, 1000, marker, &marker, &truncated);
1968 if (ret < 0) {
1969 ldpp_dout(dpp, 20) << __func__ << ": RadosMultipartUpload::list_parts returned " <<
1970 ret << dendl;
1971 return (ret == -ENOENT) ? -ERR_NO_SUCH_UPLOAD : ret;
1972 }
1973
1974 for (auto part_it = parts.begin();
1975 part_it != parts.end();
1976 ++part_it) {
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)
1984 return ret;
1985 } else {
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);
1993
1994 rgw_obj_index_key key;
1995 head->get_key().get_index_key(&key);
1996 remove_objs.push_back(key);
1997 }
1998 }
1999 parts_accounted_size += obj_part->info.accounted_size;
2000 }
2001 } while (truncated);
2002
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());
2006 } else {
2007 /* use upload id as tag and do it synchronously */
2008 ret = store->getRados()->send_chain_to_gc(chain, mp_obj.get_upload_id());
2009 if (ret < 0) {
2010 ldpp_dout(dpp, 5) << __func__ << ": gc->send_chain() returned " << ret << dendl;
2011 if (ret == -ENOENT) {
2012 return -ERR_NO_SUCH_UPLOAD;
2013 }
2014 //Delete objects inline if send chain to gc fails
2015 store->getRados()->delete_objs_inline(dpp, chain, mp_obj.get_upload_id());
2016 }
2017 }
2018
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;
2024 }
2025
2026 del_op->params.abortmp = true;
2027 del_op->params.parts_accounted_size = parts_accounted_size;
2028
2029 // and also remove the metadata obj
2030 ret = del_op->delete_obj(dpp, null_yield);
2031 if (ret < 0) {
2032 ldpp_dout(dpp, 20) << __func__ << ": del_op.delete_obj returned " <<
2033 ret << dendl;
2034 }
2035 return (ret == -ENOENT) ? -ERR_NO_SUCH_UPLOAD : ret;
2036 }
2037
2038 std::unique_ptr<rgw::sal::Object> RadosMultipartUpload::get_meta_obj()
2039 {
2040 return bucket->get_object(rgw_obj_key(get_meta(), string(), mp_ns));
2041 }
2042
2043 int RadosMultipartUpload::init(const DoutPrefixProvider *dpp, optional_yield y, RGWObjectCtx* obj_ctx, ACLOwner& owner, rgw_placement_rule& dest_placement, rgw::sal::Attrs& attrs)
2044 {
2045 int ret;
2046 std::string oid = mp_obj.get_key();
2047
2048 do {
2049 char buf[33];
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);
2055
2056 mp_obj.init(oid, upload_id);
2057 tmp_obj_name = mp_obj.get_meta();
2058
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);
2063
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);
2068
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;
2074
2075 multipart_upload_info upload_info;
2076 upload_info.dest_placement = dest_placement;
2077
2078 bufferlist bl;
2079 encode(upload_info, bl);
2080 obj_op.meta.data = &bl;
2081
2082 ret = obj_op.write_meta(dpp, bl.length(), 0, attrs, y);
2083 } while (ret == -EEXIST);
2084
2085 return ret;
2086 }
2087
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)
2092 {
2093 map<string, bufferlist> parts_map;
2094 map<string, bufferlist>::iterator iter;
2095
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);
2099
2100 bool sorted_omap = is_v2_upload_id(get_upload_id()) && !assume_unsorted;
2101
2102 parts.clear();
2103
2104 int ret;
2105 if (sorted_omap) {
2106 string p;
2107 p = "part.";
2108 char buf[32];
2109
2110 snprintf(buf, sizeof(buf), "%08d", marker);
2111 p.append(buf);
2112
2113 ret = obj->omap_get_vals(dpp, p, num_parts + 1, &parts_map,
2114 nullptr, null_yield);
2115 } else {
2116 ret = obj->omap_get_all(dpp, &parts_map, null_yield);
2117 }
2118 if (ret < 0) {
2119 return ret;
2120 }
2121
2122 int i;
2123 int last_num = 0;
2124
2125 uint32_t expected_next = marker + 1;
2126
2127 for (i = 0, iter = parts_map.begin();
2128 (i < num_parts || !sorted_omap) && iter != parts_map.end();
2129 ++iter, ++i) {
2130 bufferlist& bl = iter->second;
2131 auto bli = bl.cbegin();
2132 std::unique_ptr<RadosMultipartPart> part = std::make_unique<RadosMultipartPart>();
2133 try {
2134 decode(part->info, bli);
2135 } catch (buffer::error& err) {
2136 ldpp_dout(dpp, 0) << "ERROR: could not part info, caught buffer::error" <<
2137 dendl;
2138 return -EIO;
2139 }
2140 if (sorted_omap) {
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.
2147 */
2148 return list_parts(dpp, cct, num_parts, marker, next_marker, truncated, true);
2149 }
2150 expected_next++;
2151 }
2152 if (sorted_omap ||
2153 (int)part->info.num > marker) {
2154 last_num = part->info.num;
2155 parts[part->info.num] = std::move(part);
2156 }
2157 }
2158
2159 if (sorted_omap) {
2160 if (truncated) {
2161 *truncated = (iter != parts_map.end());
2162 }
2163 } else {
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();
2169 ++i, ++piter) {
2170 last_num = piter->first;
2171 new_parts[piter->first] = std::move(piter->second);
2172 }
2173
2174 if (truncated) {
2175 *truncated = (piter != parts.end());
2176 }
2177
2178 parts.swap(new_parts);
2179 }
2180
2181 if (next_marker) {
2182 *next_marker = last_num;
2183 }
2184
2185 return 0;
2186 }
2187
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,
2195 uint64_t olh_epoch,
2196 rgw::sal::Object* target_obj,
2197 RGWObjectCtx* obj_ctx)
2198 {
2199 char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE];
2200 char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16];
2201 std::string etag;
2202 bufferlist etag_bl;
2203 MD5 hash;
2204 // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
2205 hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
2206 bool truncated;
2207 int ret;
2208
2209 int total_parts = 0;
2210 int handled_parts = 0;
2211 int max_parts = 1000;
2212 int marker = 0;
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();
2216
2217 do {
2218 ret = list_parts(dpp, cct, max_parts, marker, &marker, &truncated);
2219 if (ret == -ENOENT) {
2220 ret = -ERR_NO_SUCH_UPLOAD;
2221 }
2222 if (ret < 0)
2223 return ret;
2224
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;
2230 return ret;
2231 }
2232
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;
2239 return ret;
2240 }
2241
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;
2248 return ret;
2249 }
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;
2255 return ret;
2256 }
2257
2258 hex_to_buf(part->get_etag().c_str(), petag,
2259 CEPH_CRYPTO_MD5_DIGESTSIZE);
2260 hash.Update((const unsigned char *)petag, sizeof(petag));
2261
2262 RGWUploadPartInfo& obj_part = part->info;
2263
2264 /* update manifest for part */
2265 string oid = mp_obj.get_part(part->info.num);
2266 rgw_obj src_obj;
2267 src_obj.init_ns(bucket->get_key(), oid, mp_ns);
2268
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;
2273 return ret;
2274 } else {
2275 manifest.append(dpp, obj_part.manifest, store->get_zone());
2276 }
2277
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;
2285 return ret;
2286 }
2287
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;
2292 else
2293 new_ofs = 0;
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;
2298 cb.len = block.len;
2299 cs_info.blocks.push_back(cb);
2300 new_ofs = cb.new_ofs + cb.len;
2301 }
2302 if (!compressed)
2303 cs_info.compression_type = obj_part.cs_info.compression_type;
2304 cs_info.orig_size += obj_part.cs_info.orig_size;
2305 compressed = true;
2306 }
2307
2308 rgw_obj_index_key remove_key;
2309 src_obj.key.get_index_key(&remove_key);
2310
2311 remove_objs.push_back(remove_key);
2312
2313 ofs += obj_part.size;
2314 accounted_size += obj_part.accounted_size;
2315 }
2316 } while (truncated);
2317 hash.Final((unsigned char *)final_etag);
2318
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;
2325
2326 etag_bl.append(etag);
2327
2328 attrs[RGW_ATTR_ETAG] = etag_bl;
2329
2330 if (compressed) {
2331 // write compression attribute to full object
2332 bufferlist tmp;
2333 encode(cs_info, tmp);
2334 attrs[RGW_ATTR_COMPRESSION] = tmp;
2335 }
2336
2337 target_obj->set_atomic(obj_ctx);
2338
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);
2343
2344 obj_op.meta.manifest = &manifest;
2345 obj_op.meta.remove_objs = &remove_objs;
2346
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;
2353
2354 ret = obj_op.write_meta(dpp, ofs, accounted_size, attrs, y);
2355 if (ret < 0)
2356 return ret;
2357
2358 return ret;
2359 }
2360
2361 int RadosMultipartUpload::get_info(const DoutPrefixProvider *dpp, optional_yield y, RGWObjectCtx* obj_ctx, rgw_placement_rule** rule, rgw::sal::Attrs* attrs)
2362 {
2363 if (!rule && !attrs) {
2364 return 0;
2365 }
2366
2367 if (rule) {
2368 if (!placement.empty()) {
2369 *rule = &placement;
2370 if (!attrs) {
2371 /* Don't need attrs, done */
2372 return 0;
2373 }
2374 } else {
2375 *rule = nullptr;
2376 }
2377 }
2378
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);
2383
2384 multipart_upload_info upload_info;
2385 bufferlist headbl;
2386
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);
2390
2391 int ret = read_op->prepare(y, dpp);
2392 if (ret < 0) {
2393 if (ret == -ENOENT) {
2394 return -ERR_NO_SUCH_UPLOAD;
2395 }
2396 return ret;
2397 }
2398
2399 extract_span_context(meta_obj->get_attrs(), trace_ctx);
2400
2401 if (attrs) {
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 */
2406 return 0;
2407 }
2408 }
2409
2410 /* Now read the placement from the head */
2411 ret = read_op->read(0, store->ctx()->_conf->rgw_max_chunk_size, headbl, y, dpp);
2412 if (ret < 0) {
2413 if (ret == -ENOENT) {
2414 return -ERR_NO_SUCH_UPLOAD;
2415 }
2416 return ret;
2417 }
2418
2419 if (headbl.length() <= 0) {
2420 return -ERR_NO_SUCH_UPLOAD;
2421 }
2422
2423 /* Decode multipart_upload_info */
2424 auto hiter = headbl.cbegin();
2425 try {
2426 decode(upload_info, hiter);
2427 } catch (buffer::error& err) {
2428 ldpp_dout(dpp, 0) << "ERROR: failed to decode multipart upload info" << dendl;
2429 return -EIO;
2430 }
2431 placement = upload_info.dest_placement;
2432 *rule = &placement;
2433
2434 return 0;
2435 }
2436
2437 std::unique_ptr<Writer> RadosMultipartUpload::get_writer(
2438 const DoutPrefixProvider *dpp,
2439 optional_yield y,
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,
2443 uint64_t part_num,
2444 const std::string& part_num_str)
2445 {
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);
2450 }
2451
2452 MPRadosSerializer::MPRadosSerializer(const DoutPrefixProvider *dpp, RadosStore* store, RadosObject* obj, const std::string& lock_name) :
2453 lock(lock_name)
2454 {
2455 rgw_pool meta_pool;
2456 rgw_raw_obj raw_obj;
2457
2458 obj->get_raw_obj(&raw_obj);
2459 oid = raw_obj.oid;
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);
2463 }
2464
2465 int MPRadosSerializer::try_lock(const DoutPrefixProvider *dpp, utime_t dur, optional_yield y)
2466 {
2467 op.assert_exists();
2468 lock.set_duration(dur);
2469 lock.lock_exclusive(&op);
2470 int ret = rgw_rados_operate(dpp, ioctx, oid, &op, y);
2471 if (! ret) {
2472 locked = true;
2473 }
2474 return ret;
2475 }
2476
2477 LCRadosSerializer::LCRadosSerializer(RadosStore* store, const std::string& _oid, const std::string& lock_name, const std::string& cookie) :
2478 lock(lock_name), oid(_oid)
2479 {
2480 ioctx = &store->getRados()->lc_pool_ctx;
2481 lock.set_cookie(cookie);
2482 }
2483
2484 int LCRadosSerializer::try_lock(const DoutPrefixProvider *dpp, utime_t dur, optional_yield y)
2485 {
2486 lock.set_duration(dur);
2487 return lock.lock_exclusive(ioctx, oid);
2488 }
2489
2490 int RadosLifecycle::get_entry(const std::string& oid, const std::string& marker,
2491 LCEntry& entry)
2492 {
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);
2495
2496 entry.bucket = cls_entry.bucket;
2497 entry.start_time = cls_entry.start_time;
2498 entry.status = cls_entry.status;
2499
2500 return ret;
2501 }
2502
2503 int RadosLifecycle::get_next_entry(const std::string& oid, std::string& marker,
2504 LCEntry& entry)
2505 {
2506 cls_rgw_lc_entry cls_entry;
2507 int ret = cls_rgw_lc_get_next_entry(*store->getRados()->get_lc_pool_ctx(), oid, marker,
2508 cls_entry);
2509
2510 entry.bucket = cls_entry.bucket;
2511 entry.start_time = cls_entry.start_time;
2512 entry.status = cls_entry.status;
2513
2514 return ret;
2515 }
2516
2517 int RadosLifecycle::set_entry(const std::string& oid, const LCEntry& entry)
2518 {
2519 cls_rgw_lc_entry cls_entry;
2520
2521 cls_entry.bucket = entry.bucket;
2522 cls_entry.start_time = entry.start_time;
2523 cls_entry.status = entry.status;
2524
2525 return cls_rgw_lc_set_entry(*store->getRados()->get_lc_pool_ctx(), oid, cls_entry);
2526 }
2527
2528 int RadosLifecycle::list_entries(const std::string& oid, const std::string& marker,
2529 uint32_t max_entries, vector<LCEntry>& entries)
2530 {
2531 entries.clear();
2532
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);
2535
2536 if (ret < 0)
2537 return ret;
2538
2539 for (auto& entry : cls_entries) {
2540 entries.push_back(LCEntry(entry.bucket, entry.start_time, entry.status));
2541 }
2542
2543 return ret;
2544 }
2545
2546 int RadosLifecycle::rm_entry(const std::string& oid, const LCEntry& entry)
2547 {
2548 cls_rgw_lc_entry cls_entry;
2549
2550 cls_entry.bucket = entry.bucket;
2551 cls_entry.start_time = entry.start_time;
2552 cls_entry.status = entry.status;
2553
2554 return cls_rgw_lc_rm_entry(*store->getRados()->get_lc_pool_ctx(), oid, cls_entry);
2555 }
2556
2557 int RadosLifecycle::get_head(const std::string& oid, LCHead& head)
2558 {
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);
2561
2562 head.marker = cls_head.marker;
2563 head.start_date = cls_head.start_date;
2564
2565 return ret;
2566 }
2567
2568 int RadosLifecycle::put_head(const std::string& oid, const LCHead& head)
2569 {
2570 cls_rgw_lc_obj_head cls_head;
2571
2572 cls_head.marker = head.marker;
2573 cls_head.start_date = head.start_date;
2574
2575 return cls_rgw_lc_put_head(*store->getRados()->get_lc_pool_ctx(), oid, cls_head);
2576 }
2577
2578 LCSerializer* RadosLifecycle::get_serializer(const std::string& lock_name, const std::string& oid, const std::string& cookie)
2579 {
2580 return new LCRadosSerializer(store, oid, lock_name, cookie);
2581 }
2582
2583 int RadosNotification::publish_reserve(const DoutPrefixProvider *dpp, RGWObjTags* obj_tags)
2584 {
2585 return rgw::notify::publish_reserve(dpp, event_type, res, obj_tags);
2586 }
2587
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)
2590 {
2591 return rgw::notify::publish_commit(obj, size, mtime, etag, version, event_type, res, dpp);
2592 }
2593
2594 int RadosAtomicWriter::prepare(optional_yield y)
2595 {
2596 return processor.prepare(y);
2597 }
2598
2599 int RadosAtomicWriter::process(bufferlist&& data, uint64_t offset)
2600 {
2601 return processor.process(std::move(data), offset);
2602 }
2603
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,
2611 optional_yield y)
2612 {
2613 return processor.complete(accounted_size, etag, mtime, set_mtime, attrs, delete_at,
2614 if_match, if_nomatch, user_data, zones_trace, canceled, y);
2615 }
2616
2617 int RadosAppendWriter::prepare(optional_yield y)
2618 {
2619 return processor.prepare(y);
2620 }
2621
2622 int RadosAppendWriter::process(bufferlist&& data, uint64_t offset)
2623 {
2624 return processor.process(std::move(data), offset);
2625 }
2626
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,
2634 optional_yield y)
2635 {
2636 return processor.complete(accounted_size, etag, mtime, set_mtime, attrs, delete_at,
2637 if_match, if_nomatch, user_data, zones_trace, canceled, y);
2638 }
2639
2640 int RadosMultipartWriter::prepare(optional_yield y)
2641 {
2642 return processor.prepare(y);
2643 }
2644
2645 int RadosMultipartWriter::process(bufferlist&& data, uint64_t offset)
2646 {
2647 return processor.process(std::move(data), offset);
2648 }
2649
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,
2657 optional_yield y)
2658 {
2659 return processor.complete(accounted_size, etag, mtime, set_mtime, attrs, delete_at,
2660 if_match, if_nomatch, user_data, zones_trace, canceled, y);
2661 }
2662
2663 const RGWZoneGroup& RadosZone::get_zonegroup()
2664 {
2665 return store->svc()->zone->get_zonegroup();
2666 }
2667
2668 int RadosZone::get_zonegroup(const std::string& id, RGWZoneGroup& zonegroup)
2669 {
2670 return store->svc()->zone->get_zonegroup(id, zonegroup);
2671 }
2672
2673 const RGWZoneParams& RadosZone::get_params()
2674 {
2675 return store->svc()->zone->get_zone_params();
2676 }
2677
2678 const rgw_zone_id& RadosZone::get_id()
2679 {
2680 return store->svc()->zone->zone_id();
2681 }
2682
2683 const RGWRealm& RadosZone::get_realm()
2684 {
2685 return store->svc()->zone->get_realm();
2686 }
2687
2688 const std::string& RadosZone::get_name() const
2689 {
2690 return store->svc()->zone->zone_name();
2691 }
2692
2693 bool RadosZone::is_writeable()
2694 {
2695 return store->svc()->zone->zone_is_writeable();
2696 }
2697
2698 bool RadosZone::get_redirect_endpoint(std::string* endpoint)
2699 {
2700 return store->svc()->zone->get_redirect_zone_endpoint(endpoint);
2701 }
2702
2703 bool RadosZone::has_zonegroup_api(const std::string& api) const
2704 {
2705 return store->svc()->zone->has_zonegroup_api(api);
2706 }
2707
2708 const std::string& RadosZone::get_current_period_id()
2709 {
2710 return store->svc()->zone->get_current_period_id();
2711 }
2712
2713 int RadosLuaScriptManager::get(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, std::string& script)
2714 {
2715 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2716 bufferlist bl;
2717
2718 int r = rgw_get_system_obj(obj_ctx, pool, key, bl, nullptr, nullptr, y, dpp);
2719 if (r < 0) {
2720 return r;
2721 }
2722
2723 auto iter = bl.cbegin();
2724 try {
2725 ceph::decode(script, iter);
2726 } catch (buffer::error& err) {
2727 return -EIO;
2728 }
2729
2730 return 0;
2731 }
2732
2733 int RadosLuaScriptManager::put(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, const std::string& script)
2734 {
2735 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2736 bufferlist bl;
2737 ceph::encode(script, bl);
2738
2739 int r = rgw_put_system_obj(dpp, obj_ctx, pool, key, bl, false, nullptr, real_time(), y);
2740 if (r < 0) {
2741 return r;
2742 }
2743
2744 return 0;
2745 }
2746
2747 int RadosLuaScriptManager::del(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key)
2748 {
2749 int r = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, key, nullptr, y);
2750 if (r < 0 && r != -ENOENT) {
2751 return r;
2752 }
2753
2754 return 0;
2755 }
2756
2757 int RadosOIDCProvider::store_url(const DoutPrefixProvider *dpp, const std::string& url, bool exclusive, optional_yield y)
2758 {
2759 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2760 std::string oid = tenant + get_url_oid_prefix() + url;
2761
2762 bufferlist bl;
2763 using ceph::encode;
2764 encode(*this, bl);
2765 return rgw_put_system_obj(dpp, obj_ctx, store->get_zone()->get_params().oidc_pool, oid, bl, exclusive, nullptr, real_time(), y);
2766 }
2767
2768 int RadosOIDCProvider::read_url(const DoutPrefixProvider *dpp, const std::string& url, const std::string& tenant)
2769 {
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;
2773 bufferlist bl;
2774
2775 int ret = rgw_get_system_obj(obj_ctx, pool, oid, bl, nullptr, nullptr, null_yield, dpp);
2776 if (ret < 0) {
2777 return ret;
2778 }
2779
2780 try {
2781 using ceph::decode;
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;
2787 return -EIO;
2788 }
2789
2790 return 0;
2791 }
2792
2793 int RadosOIDCProvider::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
2794 {
2795 auto& pool = store->get_zone()->get_params().oidc_pool;
2796
2797 std::string url, tenant;
2798 auto ret = get_tenant_url_from_arn(tenant, url);
2799 if (ret < 0) {
2800 ldpp_dout(dpp, 0) << "ERROR: failed to parse arn" << dendl;
2801 return -EINVAL;
2802 }
2803
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;
2807 return -EINVAL;
2808 }
2809
2810 // Delete url
2811 std::string oid = tenant + get_url_oid_prefix() + url;
2812 ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
2813 if (ret < 0) {
2814 ldpp_dout(dpp, 0) << "ERROR: deleting oidc url from pool: " << pool.name << ": "
2815 << provider_url << ": " << cpp_strerror(-ret) << dendl;
2816 }
2817
2818 return ret;
2819 }
2820
2821 int RadosRole::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
2822 {
2823 using ceph::encode;
2824 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2825 std::string oid = get_info_oid_prefix() + id;
2826
2827 bufferlist bl;
2828 encode(*this, bl);
2829
2830 if (!this->tags.empty()) {
2831 bufferlist bl_tags;
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);
2836 }
2837
2838 return rgw_put_system_obj(dpp, obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, nullptr, real_time(), y);
2839 }
2840
2841 int RadosRole::store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
2842 {
2843 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2844 RGWNameToId nameToId;
2845 nameToId.obj_id = id;
2846
2847 std::string oid = tenant + get_names_oid_prefix() + name;
2848
2849 bufferlist bl;
2850 using ceph::encode;
2851 encode(nameToId, bl);
2852
2853 return rgw_put_system_obj(dpp, obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, nullptr, real_time(), y);
2854 }
2855
2856 int RadosRole::store_path(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
2857 {
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;
2860
2861 bufferlist bl;
2862
2863 return rgw_put_system_obj(dpp, obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, nullptr, real_time(), y);
2864 }
2865
2866 int RadosRole::read_id(const DoutPrefixProvider *dpp, const std::string& role_name, const std::string& tenant, std::string& role_id, optional_yield y)
2867 {
2868 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2869 std::string oid = tenant + get_names_oid_prefix() + role_name;
2870 bufferlist bl;
2871
2872 int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, dpp);
2873 if (ret < 0) {
2874 return ret;
2875 }
2876
2877 RGWNameToId nameToId;
2878 try {
2879 auto iter = bl.cbegin();
2880 using ceph::decode;
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;
2884 return -EIO;
2885 }
2886 role_id = nameToId.obj_id;
2887 return 0;
2888 }
2889
2890 int RadosRole::read_name(const DoutPrefixProvider *dpp, optional_yield y)
2891 {
2892 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2893 std::string oid = tenant + get_names_oid_prefix() + name;
2894 bufferlist bl;
2895
2896 int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, dpp);
2897 if (ret < 0) {
2898 ldpp_dout(dpp, 0) << "ERROR: failed reading role name from Role pool: " << name <<
2899 ": " << cpp_strerror(-ret) << dendl;
2900 return ret;
2901 }
2902
2903 RGWNameToId nameToId;
2904 try {
2905 using ceph::decode;
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;
2910 return -EIO;
2911 }
2912 id = nameToId.obj_id;
2913 return 0;
2914 }
2915
2916 int RadosRole::read_info(const DoutPrefixProvider *dpp, optional_yield y)
2917 {
2918 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2919 std::string oid = get_info_oid_prefix() + id;
2920 bufferlist bl;
2921
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);
2924 if (ret < 0) {
2925 ldpp_dout(dpp, 0) << "ERROR: failed reading role info from Role pool: " << id << ": " << cpp_strerror(-ret) << dendl;
2926 return ret;
2927 }
2928
2929 try {
2930 using ceph::decode;
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;
2935 return -EIO;
2936 }
2937
2938 auto it = attrs.find("tagging");
2939 if (it != attrs.end()) {
2940 bufferlist bl_tags = it->second;
2941 try {
2942 using ceph::decode;
2943 auto iter = bl_tags.cbegin();
2944 decode(tags, iter);
2945 } catch (buffer::error& err) {
2946 ldpp_dout(dpp, 0) << "ERROR: failed to decode attrs" << id << dendl;
2947 return -EIO;
2948 }
2949 }
2950
2951 return 0;
2952 }
2953
2954 int RadosRole::create(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
2955 {
2956 int ret;
2957
2958 if (! validate_input(dpp)) {
2959 return -EINVAL;
2960 }
2961
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 "
2966 << id << dendl;
2967 return -EEXIST;
2968 } else if ( ret < 0 && ret != -ENOENT) {
2969 ldpp_dout(dpp, 0) << "failed reading role id " << id << ": "
2970 << cpp_strerror(-ret) << dendl;
2971 return ret;
2972 }
2973
2974 /* create unique id */
2975 uuid_d new_uuid;
2976 char uuid_str[37];
2977 new_uuid.generate_random();
2978 new_uuid.print(uuid_str);
2979 id = uuid_str;
2980
2981 //arn
2982 arn = role_arn_prefix + tenant + ":role" + path + name;
2983
2984 // Creation time
2985 real_clock::time_point t = real_clock::now();
2986
2987 struct timeval tv;
2988 real_clock::to_timeval(t, tv);
2989
2990 char buf[30];
2991 struct tm result;
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));
2996
2997 auto& pool = store->get_zone()->get_params().roles_pool;
2998 ret = store_info(dpp, exclusive, y);
2999 if (ret < 0) {
3000 ldpp_dout(dpp, 0) << "ERROR: storing role info in Role pool: "
3001 << id << ": " << cpp_strerror(-ret) << dendl;
3002 return ret;
3003 }
3004
3005 ret = store_name(dpp, exclusive, y);
3006 if (ret < 0) {
3007 ldpp_dout(dpp, 0) << "ERROR: storing role name in Role pool: "
3008 << name << ": " << cpp_strerror(-ret) << dendl;
3009
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);
3013 if (info_ret < 0) {
3014 ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from Role pool: "
3015 << id << ": " << cpp_strerror(-info_ret) << dendl;
3016 }
3017 return ret;
3018 }
3019
3020 ret = store_path(dpp, exclusive, y);
3021 if (ret < 0) {
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);
3027 if (info_ret < 0) {
3028 ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from Role pool: "
3029 << id << ": " << cpp_strerror(-info_ret) << dendl;
3030 }
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);
3034 if (name_ret < 0) {
3035 ldpp_dout(dpp, 0) << "ERROR: cleanup of role name from Role pool: "
3036 << name << ": " << cpp_strerror(-name_ret) << dendl;
3037 }
3038 return ret;
3039 }
3040 return 0;
3041 }
3042
3043 int RadosRole::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
3044 {
3045 auto& pool = store->get_zone()->get_params().roles_pool;
3046
3047 int ret = read_name(dpp, y);
3048 if (ret < 0) {
3049 return ret;
3050 }
3051
3052 ret = read_info(dpp, y);
3053 if (ret < 0) {
3054 return ret;
3055 }
3056
3057 if (! perm_policy_map.empty()) {
3058 return -ERR_DELETE_CONFLICT;
3059 }
3060
3061 // Delete id
3062 std::string oid = get_info_oid_prefix() + id;
3063 ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
3064 if (ret < 0) {
3065 ldpp_dout(dpp, 0) << "ERROR: deleting role id from Role pool: "
3066 << id << ": " << cpp_strerror(-ret) << dendl;
3067 }
3068
3069 // Delete name
3070 oid = tenant + get_names_oid_prefix() + name;
3071 ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
3072 if (ret < 0) {
3073 ldpp_dout(dpp, 0) << "ERROR: deleting role name from Role pool: "
3074 << name << ": " << cpp_strerror(-ret) << dendl;
3075 }
3076
3077 // Delete path
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);
3080 if (ret < 0) {
3081 ldpp_dout(dpp, 0) << "ERROR: deleting role path from Role pool: "
3082 << path << ": " << cpp_strerror(-ret) << dendl;
3083 }
3084 return ret;
3085 }
3086
3087
3088 } // namespace rgw::sal
3089
3090 extern "C" {
3091
3092 void* newStore(void)
3093 {
3094 rgw::sal::RadosStore* store = new rgw::sal::RadosStore();
3095 if (store) {
3096 RGWRados* rados = new RGWRados();
3097
3098 if (!rados) {
3099 delete store; store = nullptr;
3100 } else {
3101 store->setRados(rados);
3102 rados->set_store(store);
3103 }
3104 }
3105
3106 return store;
3107 }
3108
3109 }