]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_sal_rados.cc
import ceph quincy 17.2.6
[ceph.git] / ceph / src / rgw / rgw_sal_rados.cc
CommitLineData
f67539c2
TL
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>
39ae355f 21#include <boost/algorithm/string.hpp>
f67539c2
TL
22
23#include "common/Clock.h"
24#include "common/errno.h"
25
26#include "rgw_sal.h"
27#include "rgw_sal_rados.h"
28#include "rgw_bucket.h"
29#include "rgw_multi.h"
39ae355f 30#include "rgw_acl.h"
f67539c2 31#include "rgw_acl_s3.h"
20effc67
TL
32#include "rgw_aio.h"
33#include "rgw_aio_throttle.h"
34#include "rgw_tracer.h"
f67539c2
TL
35
36#include "rgw_zone.h"
37#include "rgw_rest_conn.h"
20effc67
TL
38#include "rgw_service.h"
39#include "rgw_lc.h"
f67539c2 40#include "services/svc_sys_obj.h"
39ae355f
TL
41#include "services/svc_meta.h"
42#include "services/svc_meta_be_sobj.h"
f67539c2
TL
43#include "services/svc_zone.h"
44#include "services/svc_tier_rados.h"
20effc67
TL
45#include "services/svc_quota.h"
46#include "services/svc_config_key.h"
47#include "services/svc_zone_utils.h"
39ae355f 48#include "services/svc_role_rados.h"
f67539c2
TL
49#include "cls/rgw/cls_rgw_client.h"
50
51#include "rgw_pubsub.h"
52
53#define dout_subsys ceph_subsys_rgw
54
20effc67
TL
55using namespace std;
56
57static string mp_ns = RGW_OBJ_NS_MULTIPART;
58
f67539c2
TL
59namespace rgw::sal {
60
20effc67
TL
61// default number of entries to list with each bucket listing call
62// (use marker to bridge between calls)
63static constexpr size_t listing_max_entries = 1000;
64
65static int decode_policy(CephContext* cct,
66 bufferlist& bl,
67 RGWAccessControlPolicy* policy)
68{
69 auto iter = bl.cbegin();
70 try {
71 policy->decode(iter);
72 } catch (buffer::error& err) {
73 ldout(cct, 0) << "ERROR: could not decode policy, caught buffer::error" << dendl;
74 return -EIO;
75 }
76 if (cct->_conf->subsys.should_gather<ceph_subsys_rgw, 15>()) {
77 ldout(cct, 15) << __func__ << " Read AccessControlPolicy";
78 RGWAccessControlPolicy_S3* s3policy = static_cast<RGWAccessControlPolicy_S3 *>(policy);
79 s3policy->to_xml(*_dout);
80 *_dout << dendl;
81 }
82 return 0;
83}
84
85static int rgw_op_get_bucket_policy_from_attr(const DoutPrefixProvider* dpp,
86 RadosStore* store,
87 User* user,
88 Attrs& bucket_attrs,
89 RGWAccessControlPolicy* policy,
90 optional_yield y)
91{
92 auto aiter = bucket_attrs.find(RGW_ATTR_ACL);
93
94 if (aiter != bucket_attrs.end()) {
95 int ret = decode_policy(store->ctx(), aiter->second, policy);
96 if (ret < 0)
97 return ret;
98 } else {
99 ldout(store->ctx(), 0) << "WARNING: couldn't find acl header for bucket, generating default" << dendl;
100 /* object exists, but policy is broken */
101 int r = user->load_user(dpp, y);
102 if (r < 0)
103 return r;
104
105 policy->create_default(user->get_id(), user->get_display_name());
106 }
107 return 0;
108}
109
110int RadosCompletions::drain()
111{
112 int ret = 0;
113 while (!handles.empty()) {
114 librados::AioCompletion* handle = handles.front();
115 handles.pop_front();
116 handle->wait_for_complete();
117 int r = handle->get_return_value();
118 handle->release();
119 if (r < 0) {
120 ret = r;
121 }
122 }
123 return ret;
124}
125
126int RadosUser::list_buckets(const DoutPrefixProvider* dpp, const std::string& marker,
127 const std::string& end_marker, uint64_t max, bool need_stats,
128 BucketList &buckets, optional_yield y)
f67539c2
TL
129{
130 RGWUserBuckets ulist;
131 bool is_truncated = false;
132 int ret;
133
134 buckets.clear();
b3b6e05e 135 ret = store->ctl()->user->list_buckets(dpp, info.user_id, marker, end_marker, max,
f67539c2
TL
136 need_stats, &ulist, &is_truncated, y);
137 if (ret < 0)
138 return ret;
139
140 buckets.set_truncated(is_truncated);
141 for (const auto& ent : ulist.get_buckets()) {
20effc67 142 buckets.add(std::unique_ptr<Bucket>(new RadosBucket(this->store, ent.second, this)));
f67539c2
TL
143 }
144
145 return 0;
146}
147
20effc67
TL
148int RadosUser::create_bucket(const DoutPrefixProvider* dpp,
149 const rgw_bucket& b,
150 const std::string& zonegroup_id,
151 rgw_placement_rule& placement_rule,
152 std::string& swift_ver_location,
153 const RGWQuotaInfo * pquota_info,
154 const RGWAccessControlPolicy& policy,
155 Attrs& attrs,
156 RGWBucketInfo& info,
157 obj_version& ep_objv,
158 bool exclusive,
159 bool obj_lock_enabled,
160 bool* existed,
161 req_info& req_info,
162 std::unique_ptr<Bucket>* bucket_out,
163 optional_yield y)
164{
165 int ret;
166 bufferlist in_data;
167 RGWBucketInfo master_info;
168 rgw_bucket* pmaster_bucket;
169 uint32_t* pmaster_num_shards;
170 real_time creation_time;
171 std::unique_ptr<Bucket> bucket;
172 obj_version objv,* pobjv = NULL;
173
174 /* If it exists, look it up; otherwise create it */
175 ret = store->get_bucket(dpp, this, b, &bucket, y);
176 if (ret < 0 && ret != -ENOENT)
177 return ret;
178
179 if (ret != -ENOENT) {
180 RGWAccessControlPolicy old_policy(store->ctx());
181 *existed = true;
182 if (swift_ver_location.empty()) {
183 swift_ver_location = bucket->get_info().swift_ver_location;
184 }
185 placement_rule.inherit_from(bucket->get_info().placement_rule);
186
187 // don't allow changes to the acl policy
188 int r = rgw_op_get_bucket_policy_from_attr(dpp, store, this, bucket->get_attrs(),
189 &old_policy, y);
190 if (r >= 0 && old_policy != policy) {
191 bucket_out->swap(bucket);
192 return -EEXIST;
193 }
194 } else {
195 bucket = std::unique_ptr<Bucket>(new RadosBucket(store, b, this));
196 *existed = false;
197 bucket->set_attrs(attrs);
198 }
199
200 if (!store->svc()->zone->is_meta_master()) {
201 JSONParser jp;
202 ret = store->forward_request_to_master(dpp, this, NULL, in_data, &jp, req_info, y);
203 if (ret < 0) {
204 return ret;
205 }
206
207 JSONDecoder::decode_json("entry_point_object_ver", ep_objv, &jp);
208 JSONDecoder::decode_json("object_ver", objv, &jp);
209 JSONDecoder::decode_json("bucket_info", master_info, &jp);
210 ldpp_dout(dpp, 20) << "parsed: objv.tag=" << objv.tag << " objv.ver=" << objv.ver << dendl;
211 std::time_t ctime = ceph::real_clock::to_time_t(master_info.creation_time);
212 ldpp_dout(dpp, 20) << "got creation time: << " << std::put_time(std::localtime(&ctime), "%F %T") << dendl;
213 pmaster_bucket= &master_info.bucket;
214 creation_time = master_info.creation_time;
215 pmaster_num_shards = &master_info.layout.current_index.layout.normal.num_shards;
216 pobjv = &objv;
217 if (master_info.obj_lock_enabled()) {
218 info.flags = BUCKET_VERSIONED | BUCKET_OBJ_LOCK_ENABLED;
219 }
220 } else {
221 pmaster_bucket = NULL;
222 pmaster_num_shards = NULL;
223 if (obj_lock_enabled)
224 info.flags = BUCKET_VERSIONED | BUCKET_OBJ_LOCK_ENABLED;
225 }
226
227 std::string zid = zonegroup_id;
228 if (zid.empty()) {
229 zid = store->svc()->zone->get_zonegroup().get_id();
230 }
231
232 if (*existed) {
233 rgw_placement_rule selected_placement_rule;
234 ret = store->svc()->zone->select_bucket_placement(dpp, this->get_info(),
235 zid, placement_rule,
236 &selected_placement_rule, nullptr, y);
237 if (selected_placement_rule != info.placement_rule) {
238 ret = -EEXIST;
239 bucket_out->swap(bucket);
240 return ret;
241 }
242 } else {
243
244 ret = store->getRados()->create_bucket(this->get_info(), bucket->get_key(),
245 zid, placement_rule, swift_ver_location, pquota_info,
246 attrs, info, pobjv, &ep_objv, creation_time,
247 pmaster_bucket, pmaster_num_shards, y, dpp,
248 exclusive);
249 if (ret == -EEXIST) {
250 *existed = true;
251 /* bucket already existed, might have raced with another bucket creation,
252 * or might be partial bucket creation that never completed. Read existing
253 * bucket info, verify that the reported bucket owner is the current user.
254 * If all is ok then update the user's list of buckets. Otherwise inform
255 * client about a name conflict.
256 */
257 if (info.owner.compare(this->get_id()) != 0) {
258 return -EEXIST;
259 }
260 ret = 0;
261 } else if (ret != 0) {
262 return ret;
263 }
264 }
265
266 bucket->set_version(ep_objv);
267 bucket->get_info() = info;
268
269 RadosBucket* rbucket = static_cast<RadosBucket*>(bucket.get());
270 ret = rbucket->link(dpp, this, y, false);
271 if (ret && !*existed && ret != -EEXIST) {
272 /* if it exists (or previously existed), don't remove it! */
273 ret = rbucket->unlink(dpp, this, y);
274 if (ret < 0) {
275 ldpp_dout(dpp, 0) << "WARNING: failed to unlink bucket: ret=" << ret
276 << dendl;
277 }
278 } else if (ret == -EEXIST || (ret == 0 && *existed)) {
279 ret = -ERR_BUCKET_EXISTS;
280 }
281
282 bucket_out->swap(bucket);
283
284 return ret;
285}
286
287int RadosUser::read_attrs(const DoutPrefixProvider* dpp, optional_yield y)
288{
289 return store->ctl()->user->get_attrs_by_uid(dpp, get_id(), &attrs, y, &objv_tracker);
290}
291
292int RadosUser::merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y)
f67539c2 293{
20effc67
TL
294 for(auto& it : new_attrs) {
295 attrs[it.first] = it.second;
296 }
297 return store_user(dpp, y, false);
298}
299
300int RadosUser::read_stats(const DoutPrefixProvider *dpp,
301 optional_yield y, RGWStorageStats* stats,
302 ceph::real_time* last_stats_sync,
303 ceph::real_time* last_stats_update)
304{
305 return store->ctl()->user->read_stats(dpp, get_id(), stats, y, last_stats_sync, last_stats_update);
306}
307
308int RadosUser::read_stats_async(const DoutPrefixProvider *dpp, RGWGetUserStats_CB* cb)
309{
310 return store->ctl()->user->read_stats_async(dpp, get_id(), cb);
311}
312
313int RadosUser::complete_flush_stats(const DoutPrefixProvider *dpp, optional_yield y)
314{
315 return store->ctl()->user->complete_flush_stats(dpp, get_id(), y);
316}
317
318int RadosUser::read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch,
319 uint32_t max_entries, bool* is_truncated,
320 RGWUsageIter& usage_iter,
321 map<rgw_user_bucket, rgw_usage_log_entry>& usage)
322{
323 std::string bucket_name;
324 return store->getRados()->read_usage(dpp, get_id(), bucket_name, start_epoch,
325 end_epoch, max_entries, is_truncated,
326 usage_iter, usage);
f67539c2
TL
327}
328
20effc67
TL
329int RadosUser::trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch)
330{
331 std::string bucket_name;
332
333 return store->getRados()->trim_usage(dpp, get_id(), bucket_name, start_epoch, end_epoch);
334}
f67539c2 335
20effc67 336int RadosUser::load_user(const DoutPrefixProvider* dpp, optional_yield y)
f67539c2 337{
20effc67 338 return store->ctl()->user->get_info_by_uid(dpp, info.user_id, &info, y, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker).set_attrs(&attrs));
f67539c2
TL
339}
340
20effc67 341int RadosUser::store_user(const DoutPrefixProvider* dpp, optional_yield y, bool exclusive, RGWUserInfo* old_info)
f67539c2 342{
20effc67
TL
343 return store->ctl()->user->store_info(dpp, info, y,
344 RGWUserCtl::PutParams().set_objv_tracker(&objv_tracker)
345 .set_exclusive(exclusive)
346 .set_attrs(&attrs)
347 .set_old_info(old_info));
f67539c2
TL
348}
349
20effc67 350int RadosUser::remove_user(const DoutPrefixProvider* dpp, optional_yield y)
f67539c2 351{
20effc67
TL
352 return store->ctl()->user->remove_info(dpp, info, y,
353 RGWUserCtl::RemoveParams().set_objv_tracker(&objv_tracker));
f67539c2
TL
354}
355
20effc67
TL
356RadosBucket::~RadosBucket() {}
357
358int RadosBucket::remove_bucket(const DoutPrefixProvider* dpp,
b3b6e05e 359 bool delete_children,
b3b6e05e 360 bool forward_to_master,
20effc67
TL
361 req_info* req_info,
362 optional_yield y)
f67539c2
TL
363{
364 int ret;
365
366 // Refresh info
20effc67
TL
367 ret = load_bucket(dpp, y);
368 if (ret < 0) {
f67539c2 369 return ret;
20effc67 370 }
f67539c2
TL
371
372 ListParams params;
373 params.list_versions = true;
374 params.allow_unordered = true;
375
376 ListResults results;
377
f67539c2
TL
378 do {
379 results.objs.clear();
380
b3b6e05e 381 ret = list(dpp, params, 1000, results, y);
20effc67 382 if (ret < 0) {
b3b6e05e 383 return ret;
20effc67 384 }
f67539c2
TL
385
386 if (!results.objs.empty() && !delete_children) {
b3b6e05e 387 ldpp_dout(dpp, -1) << "ERROR: could not remove non-empty bucket " << info.bucket.name <<
f67539c2
TL
388 dendl;
389 return -ENOTEMPTY;
390 }
391
392 for (const auto& obj : results.objs) {
393 rgw_obj_key key(obj.key);
394 /* xxx dang */
20effc67 395 ret = rgw_remove_object(dpp, store, this, key);
f67539c2
TL
396 if (ret < 0 && ret != -ENOENT) {
397 return ret;
398 }
399 }
b3b6e05e 400 } while(results.is_truncated);
f67539c2 401
20effc67 402 ret = abort_multiparts(dpp, store->ctx());
a4b75251
TL
403 if (ret < 0) {
404 return ret;
f67539c2
TL
405 }
406
20effc67
TL
407 // remove lifecycle config, if any (XXX note could be made generic)
408 (void) store->getRados()->get_lc()->remove_bucket_config(
409 this, get_attrs());
410
411 ret = store->ctl()->bucket->sync_user_stats(dpp, info.owner, info, y, nullptr);
f67539c2
TL
412 if (ret < 0) {
413 ldout(store->ctx(), 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret << dendl;
414 }
415
416 RGWObjVersionTracker ot;
417
418 // if we deleted children above we will force delete, as any that
419 // remain is detrius from a prior bug
b3b6e05e 420 ret = store->getRados()->delete_bucket(info, ot, y, dpp, !delete_children);
f67539c2 421 if (ret < 0) {
b3b6e05e 422 ldpp_dout(dpp, -1) << "ERROR: could not remove bucket " <<
f67539c2
TL
423 info.bucket.name << dendl;
424 return ret;
425 }
426
427 // if bucket has notification definitions associated with it
428 // they should be removed (note that any pending notifications on the bucket are still going to be sent)
429 RGWPubSub ps(store, info.owner.tenant);
430 RGWPubSub::Bucket ps_bucket(&ps, info.bucket);
b3b6e05e 431 const auto ps_ret = ps_bucket.remove_notifications(dpp, y);
f67539c2 432 if (ps_ret < 0 && ps_ret != -ENOENT) {
20effc67 433 ldpp_dout(dpp, -1) << "ERROR: unable to remove notifications from bucket. ret=" << ps_ret << dendl;
f67539c2
TL
434 }
435
b3b6e05e 436 ret = store->ctl()->bucket->unlink_bucket(info.owner, info.bucket, y, dpp, false);
f67539c2 437 if (ret < 0) {
b3b6e05e 438 ldpp_dout(dpp, -1) << "ERROR: unable to remove user bucket information" << dendl;
f67539c2
TL
439 }
440
441 if (forward_to_master) {
442 bufferlist in_data;
b3b6e05e 443 ret = store->forward_request_to_master(dpp, owner, &ot.read_version, in_data, nullptr, *req_info, y);
f67539c2
TL
444 if (ret < 0) {
445 if (ret == -ENOENT) {
446 /* adjust error, we want to return with NoSuchBucket and not
447 * NoSuchKey */
448 ret = -ERR_NO_SUCH_BUCKET;
449 }
450 return ret;
451 }
452 }
453
454 return ret;
455}
456
20effc67
TL
457int RadosBucket::remove_bucket_bypass_gc(int concurrent_max, bool
458 keep_index_consistent,
459 optional_yield y, const
460 DoutPrefixProvider *dpp)
461{
462 int ret;
463 map<RGWObjCategory, RGWStorageStats> stats;
464 map<string, bool> common_prefixes;
465 RGWObjectCtx obj_ctx(store);
466 CephContext *cct = store->ctx();
467
468 string bucket_ver, master_ver;
469
470 ret = load_bucket(dpp, null_yield);
471 if (ret < 0)
472 return ret;
473
474 ret = read_stats(dpp, RGW_NO_SHARD, &bucket_ver, &master_ver, stats, NULL);
475 if (ret < 0)
476 return ret;
477
478 ret = abort_multiparts(dpp, cct);
479 if (ret < 0) {
480 return ret;
481 }
482
483 rgw::sal::Bucket::ListParams params;
484 rgw::sal::Bucket::ListResults results;
485
486 params.list_versions = true;
487 params.allow_unordered = true;
488
489 std::unique_ptr<rgw::sal::Completions> handles = store->get_completions();
490
491 int max_aio = concurrent_max;
492 results.is_truncated = true;
493
494 while (results.is_truncated) {
495 ret = list(dpp, params, listing_max_entries, results, null_yield);
496 if (ret < 0)
497 return ret;
498
499 std::vector<rgw_bucket_dir_entry>::iterator it = results.objs.begin();
500 for (; it != results.objs.end(); ++it) {
501 RGWObjState *astate = NULL;
502 std::unique_ptr<rgw::sal::Object> obj = get_object((*it).key);
503
504 ret = obj->get_obj_state(dpp, &obj_ctx, &astate, y, false);
505 if (ret == -ENOENT) {
506 ldpp_dout(dpp, 1) << "WARNING: cannot find obj state for obj " << obj << dendl;
507 continue;
508 }
509 if (ret < 0) {
510 ldpp_dout(dpp, -1) << "ERROR: get obj state returned with error " << ret << dendl;
511 return ret;
512 }
513
514 if (astate->manifest) {
515 RGWObjManifest& manifest = *astate->manifest;
516 RGWObjManifest::obj_iterator miter = manifest.obj_begin(dpp);
517 std::unique_ptr<rgw::sal::Object> head_obj = get_object(manifest.get_obj().key);
518 rgw_raw_obj raw_head_obj;
519 dynamic_cast<RadosObject*>(head_obj.get())->get_raw_obj(&raw_head_obj);
520
521 for (; miter != manifest.obj_end(dpp) && max_aio--; ++miter) {
522 if (!max_aio) {
523 ret = handles->drain();
524 if (ret < 0) {
525 ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
526 return ret;
527 }
528 max_aio = concurrent_max;
529 }
530
531 rgw_raw_obj last_obj = miter.get_location().get_raw_obj(store);
532 if (last_obj == raw_head_obj) {
533 // have the head obj deleted at the end
534 continue;
535 }
536
537 ret = store->delete_raw_obj_aio(dpp, last_obj, handles.get());
538 if (ret < 0) {
539 ldpp_dout(dpp, -1) << "ERROR: delete obj aio failed with " << ret << dendl;
540 return ret;
541 }
542 } // for all shadow objs
543
544 ret = head_obj->delete_obj_aio(dpp, astate, handles.get(), keep_index_consistent, null_yield);
545 if (ret < 0) {
546 ldpp_dout(dpp, -1) << "ERROR: delete obj aio failed with " << ret << dendl;
547 return ret;
548 }
549 }
550
551 if (!max_aio) {
552 ret = handles->drain();
553 if (ret < 0) {
554 ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
555 return ret;
556 }
557 max_aio = concurrent_max;
558 }
559 obj_ctx.invalidate(obj->get_obj());
560 } // for all RGW objects in results
561 } // while is_truncated
562
563 ret = handles->drain();
564 if (ret < 0) {
565 ldpp_dout(dpp, -1) << "ERROR: could not drain handles as aio completion returned with " << ret << dendl;
566 return ret;
567 }
568
569 sync_user_stats(dpp, y);
570 if (ret < 0) {
571 ldpp_dout(dpp, 1) << "WARNING: failed sync user stats before bucket delete. ret=" << ret << dendl;
572 }
573
574 RGWObjVersionTracker objv_tracker;
575
576 // this function can only be run if caller wanted children to be
577 // deleted, so we can ignore the check for children as any that
578 // remain are detritus from a prior bug
579 ret = remove_bucket(dpp, true, false, nullptr, y);
580 if (ret < 0) {
581 ldpp_dout(dpp, -1) << "ERROR: could not remove bucket " << this << dendl;
582 return ret;
583 }
584
585 return ret;
586}
587
588int RadosBucket::load_bucket(const DoutPrefixProvider* dpp, optional_yield y, bool get_stats)
f67539c2
TL
589{
590 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
20effc67
TL
591 int ret;
592
f67539c2
TL
593 RGWSI_MetaBackend_CtxParams bectx_params = RGWSI_MetaBackend_CtxParams_SObj(&obj_ctx);
594 RGWObjVersionTracker ep_ot;
20effc67
TL
595 if (info.bucket.bucket_id.empty()) {
596 ret = store->ctl()->bucket->read_bucket_info(info.bucket, &info, y, dpp,
f67539c2
TL
597 RGWBucketCtl::BucketInstance::GetParams()
598 .set_mtime(&mtime)
599 .set_attrs(&attrs)
600 .set_bectx_params(bectx_params),
601 &ep_ot);
20effc67
TL
602 } else {
603 ret = store->ctl()->bucket->read_bucket_instance_info(info.bucket, &info, y, dpp,
604 RGWBucketCtl::BucketInstance::GetParams()
605 .set_mtime(&mtime)
606 .set_attrs(&attrs)
607 .set_bectx_params(bectx_params));
608 }
609 if (ret != 0) {
610 return ret;
f67539c2 611 }
f67539c2 612
20effc67 613 bucket_version = ep_ot.read_version;
f67539c2 614
20effc67
TL
615 if (get_stats) {
616 ret = store->ctl()->bucket->read_bucket_stats(info.bucket, &ent, y, dpp);
f67539c2
TL
617 }
618
20effc67 619 return ret;
f67539c2
TL
620}
621
20effc67
TL
622int RadosBucket::read_stats(const DoutPrefixProvider *dpp, int shard_id,
623 std::string* bucket_ver, std::string* master_ver,
f67539c2 624 std::map<RGWObjCategory, RGWStorageStats>& stats,
20effc67 625 std::string* max_marker, bool* syncstopped)
f67539c2 626{
20effc67 627 return store->getRados()->get_bucket_stats(dpp, info, shard_id, bucket_ver, master_ver, stats, max_marker, syncstopped);
f67539c2
TL
628}
629
20effc67 630int RadosBucket::read_stats_async(const DoutPrefixProvider *dpp, int shard_id, RGWGetBucketStats_CB* ctx)
f67539c2 631{
20effc67 632 return store->getRados()->get_bucket_stats_async(dpp, get_info(), shard_id, ctx);
f67539c2
TL
633}
634
20effc67 635int RadosBucket::sync_user_stats(const DoutPrefixProvider *dpp, optional_yield y)
f67539c2 636{
20effc67 637 return store->ctl()->bucket->sync_user_stats(dpp, owner->get_id(), info, y, &ent);
f67539c2
TL
638}
639
20effc67 640int RadosBucket::update_container_stats(const DoutPrefixProvider* dpp)
f67539c2
TL
641{
642 int ret;
643 map<std::string, RGWBucketEnt> m;
644
645 m[info.bucket.name] = ent;
b3b6e05e 646 ret = store->getRados()->update_containers_stats(m, dpp);
f67539c2
TL
647 if (!ret)
648 return -EEXIST;
649 if (ret < 0)
650 return ret;
651
20effc67 652 map<std::string, RGWBucketEnt>::iterator iter = m.find(info.bucket.name);
f67539c2
TL
653 if (iter == m.end())
654 return -EINVAL;
655
656 ent.count = iter->second.count;
657 ent.size = iter->second.size;
658 ent.size_rounded = iter->second.size_rounded;
659 ent.creation_time = iter->second.creation_time;
660 ent.placement_rule = std::move(iter->second.placement_rule);
661
662 info.creation_time = ent.creation_time;
663 info.placement_rule = ent.placement_rule;
664
665 return 0;
666}
667
20effc67 668int RadosBucket::check_bucket_shards(const DoutPrefixProvider* dpp)
f67539c2 669{
b3b6e05e 670 return store->getRados()->check_bucket_shards(info, info.bucket, get_count(), dpp);
f67539c2
TL
671}
672
20effc67 673int RadosBucket::link(const DoutPrefixProvider* dpp, User* new_user, optional_yield y, bool update_entrypoint, RGWObjVersionTracker* objv)
f67539c2
TL
674{
675 RGWBucketEntryPoint ep;
676 ep.bucket = info.bucket;
20effc67 677 ep.owner = new_user->get_id();
f67539c2
TL
678 ep.creation_time = get_creation_time();
679 ep.linked = true;
20effc67 680 Attrs ep_attrs;
f67539c2
TL
681 rgw_ep_info ep_data{ep, ep_attrs};
682
20effc67
TL
683 int r = store->ctl()->bucket->link_bucket(new_user->get_id(), info.bucket,
684 get_creation_time(), y, dpp, update_entrypoint,
685 &ep_data);
686 if (r < 0)
687 return r;
688
689 if (objv)
690 *objv = ep_data.ep_objv;
691
692 return r;
f67539c2
TL
693}
694
20effc67 695int RadosBucket::unlink(const DoutPrefixProvider* dpp, User* new_user, optional_yield y, bool update_entrypoint)
f67539c2 696{
20effc67 697 return store->ctl()->bucket->unlink_bucket(new_user->get_id(), info.bucket, y, dpp, update_entrypoint);
f67539c2
TL
698}
699
39ae355f 700int RadosBucket::chown(const DoutPrefixProvider* dpp, User& new_user, optional_yield y)
f67539c2 701{
20effc67 702 std::string obj_marker;
39ae355f 703 int r;
20effc67 704
39ae355f
TL
705 if (!owner) {
706 ldpp_dout(dpp, 0) << __func__ << " Cannot chown without an owner " << dendl;
707 return -EINVAL;
708 }
20effc67 709
39ae355f 710 r = this->unlink(dpp, owner, y);
20effc67
TL
711 if (r < 0) {
712 return r;
713 }
f67539c2 714
39ae355f 715 return this->link(dpp, &new_user, y);
f67539c2
TL
716}
717
20effc67 718int RadosBucket::put_info(const DoutPrefixProvider* dpp, bool exclusive, ceph::real_time _mtime)
f67539c2
TL
719{
720 mtime = _mtime;
b3b6e05e 721 return store->getRados()->put_bucket_instance_info(info, exclusive, mtime, &attrs, dpp);
f67539c2
TL
722}
723
724/* Make sure to call get_bucket_info() if you need it first */
20effc67 725bool RadosBucket::is_owner(User* user)
f67539c2 726{
20effc67 727 return (info.owner.compare(user->get_id()) == 0);
f67539c2
TL
728}
729
20effc67 730int RadosBucket::check_empty(const DoutPrefixProvider* dpp, optional_yield y)
f67539c2 731{
b3b6e05e 732 return store->getRados()->check_bucket_empty(dpp, info, y);
f67539c2
TL
733}
734
20effc67 735int RadosBucket::check_quota(const DoutPrefixProvider *dpp, RGWQuotaInfo& user_quota, RGWQuotaInfo& bucket_quota, uint64_t obj_size,
f67539c2
TL
736 optional_yield y, bool check_size_only)
737{
20effc67 738 return store->getRados()->check_quota(dpp, owner->get_id(), get_key(),
f67539c2
TL
739 user_quota, bucket_quota, obj_size, y, check_size_only);
740}
741
20effc67 742int RadosBucket::merge_and_store_attrs(const DoutPrefixProvider* dpp, Attrs& new_attrs, optional_yield y)
f67539c2 743{
20effc67
TL
744 for(auto& it : new_attrs) {
745 attrs[it.first] = it.second;
746 }
747 return store->ctl()->bucket->set_bucket_instance_attrs(get_info(),
748 new_attrs, &get_info().objv_tracker, y, dpp);
f67539c2
TL
749}
750
20effc67 751int RadosBucket::try_refresh_info(const DoutPrefixProvider* dpp, ceph::real_time* pmtime)
f67539c2 752{
b3b6e05e 753 return store->getRados()->try_refresh_bucket_info(info, pmtime, dpp, &attrs);
f67539c2
TL
754}
755
20effc67
TL
756int RadosBucket::read_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch,
757 uint32_t max_entries, bool* is_truncated,
f67539c2
TL
758 RGWUsageIter& usage_iter,
759 map<rgw_user_bucket, rgw_usage_log_entry>& usage)
760{
20effc67
TL
761 return store->getRados()->read_usage(dpp, owner->get_id(), get_name(), start_epoch,
762 end_epoch, max_entries, is_truncated,
763 usage_iter, usage);
f67539c2
TL
764}
765
20effc67 766int RadosBucket::trim_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch)
f67539c2 767{
20effc67
TL
768 return store->getRados()->trim_usage(dpp, owner->get_id(), get_name(), start_epoch, end_epoch);
769}
f67539c2 770
20effc67
TL
771int RadosBucket::remove_objs_from_index(const DoutPrefixProvider *dpp, std::list<rgw_obj_index_key>& objs_to_unlink)
772{
773 return store->getRados()->remove_objs_from_index(dpp, info, objs_to_unlink);
774}
f67539c2 775
20effc67
TL
776int RadosBucket::check_index(const DoutPrefixProvider *dpp, std::map<RGWObjCategory, RGWStorageStats>& existing_stats, std::map<RGWObjCategory, RGWStorageStats>& calculated_stats)
777{
778 return store->getRados()->bucket_check_index(dpp, info, &existing_stats, &calculated_stats);
f67539c2
TL
779}
780
20effc67 781int RadosBucket::rebuild_index(const DoutPrefixProvider *dpp)
f67539c2 782{
20effc67 783 return store->getRados()->bucket_rebuild_index(dpp, info);
f67539c2
TL
784}
785
20effc67 786int RadosBucket::set_tag_timeout(const DoutPrefixProvider *dpp, uint64_t timeout)
f67539c2 787{
20effc67
TL
788 return store->getRados()->cls_obj_set_bucket_tag_timeout(dpp, info, timeout);
789}
f67539c2 790
20effc67
TL
791int RadosBucket::purge_instance(const DoutPrefixProvider* dpp)
792{
793 int max_shards = (info.layout.current_index.layout.normal.num_shards > 0 ? info.layout.current_index.layout.normal.num_shards : 1);
794 for (int i = 0; i < max_shards; i++) {
795 RGWRados::BucketShard bs(store->getRados());
796 int shard_id = (info.layout.current_index.layout.normal.num_shards > 0 ? i : -1);
797 int ret = bs.init(info.bucket, shard_id, info.layout.current_index, nullptr, dpp);
798 if (ret < 0) {
799 cerr << "ERROR: bs.init(bucket=" << info.bucket << ", shard=" << shard_id
800 << "): " << cpp_strerror(-ret) << std::endl;
801 return ret;
802 }
803 ret = store->getRados()->bi_remove(dpp, bs);
804 if (ret < 0) {
805 cerr << "ERROR: failed to remove bucket index object: "
806 << cpp_strerror(-ret) << std::endl;
807 return ret;
808 }
809 }
810 return 0;
811}
812
813int RadosBucket::set_acl(const DoutPrefixProvider* dpp, RGWAccessControlPolicy &acl, optional_yield y)
814{
815 bufferlist aclbl;
816
817 acls = acl;
818 acl.encode(aclbl);
819 map<string, bufferlist>& attrs = get_attrs();
820
821 attrs[RGW_ATTR_ACL] = aclbl;
822 info.owner = acl.get_owner().get_id();
823
824 int r = store->ctl()->bucket->store_bucket_instance_info(info.bucket,
825 info, y, dpp,
826 RGWBucketCtl::BucketInstance::PutParams().set_attrs(&attrs));
827 if (r < 0) {
828 cerr << "ERROR: failed to set bucket owner: " << cpp_strerror(-r) << std::endl;
829 return r;
830 }
831
832 return 0;
833}
834
835std::unique_ptr<Object> RadosBucket::get_object(const rgw_obj_key& k)
836{
837 return std::make_unique<RadosObject>(this->store, k, this);
838}
839
840int RadosBucket::list(const DoutPrefixProvider* dpp, ListParams& params, int max, ListResults& results, optional_yield y)
841{
842 RGWRados::Bucket target(store->getRados(), get_info());
843 if (params.shard_id >= 0) {
844 target.set_shard_id(params.shard_id);
845 }
846 RGWRados::Bucket::List list_op(&target);
847
848 list_op.params.prefix = params.prefix;
f67539c2
TL
849 list_op.params.delim = params.delim;
850 list_op.params.marker = params.marker;
851 list_op.params.ns = params.ns;
852 list_op.params.end_marker = params.end_marker;
20effc67
TL
853 list_op.params.ns = params.ns;
854 list_op.params.enforce_ns = params.enforce_ns;
855 list_op.params.access_list_filter = params.access_list_filter;
856 list_op.params.force_check_filter = params.force_check_filter;
f67539c2
TL
857 list_op.params.list_versions = params.list_versions;
858 list_op.params.allow_unordered = params.allow_unordered;
859
b3b6e05e 860 int ret = list_op.list_objects(dpp, max, &results.objs, &results.common_prefixes, &results.is_truncated, y);
f67539c2
TL
861 if (ret >= 0) {
862 results.next_marker = list_op.get_next_marker();
522d829b 863 params.marker = results.next_marker;
f67539c2
TL
864 }
865
866 return ret;
867}
868
20effc67
TL
869std::unique_ptr<MultipartUpload> RadosBucket::get_multipart_upload(
870 const std::string& oid,
871 std::optional<std::string> upload_id,
872 ACLOwner owner, ceph::real_time mtime)
f67539c2 873{
20effc67
TL
874 return std::make_unique<RadosMultipartUpload>(this->store, this, oid, upload_id,
875 std::move(owner), mtime);
f67539c2
TL
876}
877
20effc67
TL
878int RadosBucket::list_multiparts(const DoutPrefixProvider *dpp,
879 const string& prefix,
880 string& marker,
881 const string& delim,
882 const int& max_uploads,
883 vector<std::unique_ptr<MultipartUpload>>& uploads,
884 map<string, bool> *common_prefixes,
885 bool *is_truncated)
f67539c2 886{
20effc67
TL
887 rgw::sal::Bucket::ListParams params;
888 rgw::sal::Bucket::ListResults results;
889 MultipartMetaFilter mp_filter;
f67539c2 890
20effc67
TL
891 params.prefix = prefix;
892 params.delim = delim;
893 params.marker = marker;
894 params.ns = RGW_OBJ_NS_MULTIPART;
895 params.access_list_filter = &mp_filter;
f67539c2 896
20effc67
TL
897 int ret = list(dpp, params, max_uploads, results, null_yield);
898
899 if (ret < 0)
900 return ret;
901
902 if (!results.objs.empty()) {
903 for (const rgw_bucket_dir_entry& dentry : results.objs) {
904 rgw_obj_key key(dentry.key);
905 ACLOwner owner(rgw_user(dentry.meta.owner));
906 owner.set_name(dentry.meta.owner_display_name);
907 uploads.push_back(this->get_multipart_upload(key.name,
908 std::nullopt, std::move(owner)));
f67539c2
TL
909 }
910 }
20effc67
TL
911 if (common_prefixes) {
912 *common_prefixes = std::move(results.common_prefixes);
913 }
914 *is_truncated = results.is_truncated;
915 marker = params.marker.name;
916
f67539c2
TL
917 return 0;
918}
919
20effc67
TL
920int RadosBucket::abort_multiparts(const DoutPrefixProvider* dpp,
921 CephContext* cct)
f67539c2 922{
20effc67
TL
923 constexpr int max = 1000;
924 int ret, num_deleted = 0;
925 vector<std::unique_ptr<MultipartUpload>> uploads;
926 RGWObjectCtx obj_ctx(store);
927 string marker;
928 bool is_truncated;
f67539c2 929
20effc67
TL
930 const std::string empty_delim;
931 const std::string empty_prefix;
f67539c2 932
20effc67
TL
933 do {
934 ret = list_multiparts(dpp, empty_prefix, marker, empty_delim,
935 max, uploads, nullptr, &is_truncated);
936 if (ret < 0) {
937 ldpp_dout(dpp, 0) << __func__ <<
938 " ERROR : calling list_bucket_multiparts; ret=" << ret <<
939 "; bucket=\"" << this << "\"" << dendl;
940 return ret;
941 }
942 ldpp_dout(dpp, 20) << __func__ <<
943 " INFO: aborting and cleaning up multipart upload(s); bucket=\"" <<
944 this << "\"; uploads.size()=" << uploads.size() <<
945 "; is_truncated=" << is_truncated << dendl;
946
947 if (!uploads.empty()) {
948 for (const auto& upload : uploads) {
949 ret = upload->abort(dpp, cct, &obj_ctx);
950 if (ret < 0) {
951 // we're doing a best-effort; if something cannot be found,
952 // log it and keep moving forward
953 if (ret != -ENOENT && ret != -ERR_NO_SUCH_UPLOAD) {
954 ldpp_dout(dpp, 0) << __func__ <<
955 " ERROR : failed to abort and clean-up multipart upload \"" <<
956 upload->get_meta() << "\"" << dendl;
957 return ret;
958 } else {
959 ldpp_dout(dpp, 10) << __func__ <<
960 " NOTE : unable to find part(s) of "
961 "aborted multipart upload of \"" << upload->get_meta() <<
962 "\" for cleaning up" << dendl;
963 }
964 }
965 num_deleted++;
966 }
967 if (num_deleted) {
968 ldpp_dout(dpp, 0) << __func__ <<
969 " WARNING : aborted " << num_deleted <<
970 " incomplete multipart uploads" << dendl;
971 }
972 }
973 } while (is_truncated);
f67539c2 974
20effc67 975 return 0;
f67539c2
TL
976}
977
20effc67 978std::unique_ptr<User> RadosStore::get_user(const rgw_user &u)
f67539c2 979{
20effc67 980 return std::make_unique<RadosUser>(this, u);
f67539c2
TL
981}
982
20effc67 983std::string RadosStore::get_cluster_id(const DoutPrefixProvider* dpp, optional_yield y)
f67539c2 984{
20effc67 985 return getRados()->get_cluster_fsid(dpp, y);
f67539c2
TL
986}
987
20effc67 988int RadosStore::get_user_by_access_key(const DoutPrefixProvider* dpp, const std::string& key, optional_yield y, std::unique_ptr<User>* user)
f67539c2 989{
20effc67
TL
990 RGWUserInfo uinfo;
991 User* u;
992 RGWObjVersionTracker objv_tracker;
993
994 int r = ctl()->user->get_info_by_access_key(dpp, key, &uinfo, y, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker));
995 if (r < 0)
f67539c2 996 return r;
f67539c2 997
20effc67
TL
998 u = new RadosUser(this, uinfo);
999 if (!u)
1000 return -ENOMEM;
f67539c2 1001
20effc67
TL
1002 u->get_version_tracker() = objv_tracker;
1003
1004 user->reset(u);
1005 return 0;
f67539c2
TL
1006}
1007
20effc67 1008int RadosStore::get_user_by_email(const DoutPrefixProvider* dpp, const std::string& email, optional_yield y, std::unique_ptr<User>* user)
f67539c2 1009{
20effc67
TL
1010 RGWUserInfo uinfo;
1011 User* u;
1012 RGWObjVersionTracker objv_tracker;
f67539c2 1013
20effc67
TL
1014 int r = ctl()->user->get_info_by_email(dpp, email, &uinfo, y, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker));
1015 if (r < 0)
1016 return r;
f67539c2 1017
20effc67
TL
1018 u = new RadosUser(this, uinfo);
1019 if (!u)
1020 return -ENOMEM;
f67539c2 1021
20effc67 1022 u->get_version_tracker() = objv_tracker;
f67539c2 1023
20effc67
TL
1024 user->reset(u);
1025 return 0;
f67539c2
TL
1026}
1027
20effc67 1028int RadosStore::get_user_by_swift(const DoutPrefixProvider* dpp, const std::string& user_str, optional_yield y, std::unique_ptr<User>* user)
f67539c2 1029{
20effc67
TL
1030 RGWUserInfo uinfo;
1031 User* u;
1032 RGWObjVersionTracker objv_tracker;
f67539c2 1033
20effc67
TL
1034 int r = ctl()->user->get_info_by_swift(dpp, user_str, &uinfo, y, RGWUserCtl::GetParams().set_objv_tracker(&objv_tracker));
1035 if (r < 0)
1036 return r;
f67539c2 1037
20effc67
TL
1038 u = new RadosUser(this, uinfo);
1039 if (!u)
1040 return -ENOMEM;
f67539c2 1041
20effc67 1042 u->get_version_tracker() = objv_tracker;
f67539c2 1043
20effc67
TL
1044 user->reset(u);
1045 return 0;
f67539c2
TL
1046}
1047
20effc67 1048std::unique_ptr<Object> RadosStore::get_object(const rgw_obj_key& k)
f67539c2 1049{
20effc67 1050 return std::make_unique<RadosObject>(this, k);
f67539c2
TL
1051}
1052
20effc67 1053int RadosStore::get_bucket(const DoutPrefixProvider* dpp, User* u, const rgw_bucket& b, std::unique_ptr<Bucket>* bucket, optional_yield y)
f67539c2
TL
1054{
1055 int ret;
20effc67 1056 Bucket* bp;
f67539c2 1057
20effc67
TL
1058 bp = new RadosBucket(this, b, u);
1059 ret = bp->load_bucket(dpp, y);
f67539c2 1060 if (ret < 0) {
20effc67 1061 delete bp;
f67539c2
TL
1062 return ret;
1063 }
1064
20effc67
TL
1065 bucket->reset(bp);
1066 return 0;
f67539c2
TL
1067}
1068
20effc67 1069int RadosStore::get_bucket(User* u, const RGWBucketInfo& i, std::unique_ptr<Bucket>* bucket)
f67539c2 1070{
20effc67 1071 Bucket* bp;
f67539c2 1072
20effc67
TL
1073 bp = new RadosBucket(this, i, u);
1074 /* Don't need to fetch the bucket info, use the provided one */
f67539c2 1075
20effc67
TL
1076 bucket->reset(bp);
1077 return 0;
f67539c2
TL
1078}
1079
20effc67 1080int RadosStore::get_bucket(const DoutPrefixProvider* dpp, User* u, const std::string& tenant, const std::string& name, std::unique_ptr<Bucket>* bucket, optional_yield y)
f67539c2 1081{
20effc67 1082 rgw_bucket b;
f67539c2 1083
20effc67
TL
1084 b.tenant = tenant;
1085 b.name = name;
f67539c2 1086
20effc67 1087 return get_bucket(dpp, u, b, bucket, y);
f67539c2
TL
1088}
1089
20effc67 1090bool RadosStore::is_meta_master()
f67539c2 1091{
20effc67 1092 return svc()->zone->is_meta_master();
f67539c2
TL
1093}
1094
20effc67
TL
1095int RadosStore::forward_request_to_master(const DoutPrefixProvider *dpp, User* user, obj_version* objv,
1096 bufferlist& in_data,
1097 JSONParser* jp, req_info& info,
1098 optional_yield y)
f67539c2 1099{
20effc67
TL
1100 if (is_meta_master()) {
1101 /* We're master, don't forward */
1102 return 0;
1103 }
f67539c2 1104
20effc67
TL
1105 if (!svc()->zone->get_master_conn()) {
1106 ldpp_dout(dpp, 0) << "rest connection is invalid" << dendl;
1107 return -EINVAL;
f67539c2 1108 }
20effc67
TL
1109 ldpp_dout(dpp, 0) << "sending request to master zonegroup" << dendl;
1110 bufferlist response;
1111 std::string uid_str = user->get_id().to_str();
1112#define MAX_REST_RESPONSE (128 * 1024) // we expect a very small response
1113 int ret = svc()->zone->get_master_conn()->forward(dpp, rgw_user(uid_str), info,
1114 objv, MAX_REST_RESPONSE,
1115 &in_data, &response, y);
1116 if (ret < 0)
1117 return ret;
1118
1119 ldpp_dout(dpp, 20) << "response: " << response.c_str() << dendl;
1120 if (jp && !jp->parse(response.c_str(), response.length())) {
1121 ldpp_dout(dpp, 0) << "failed parsing response from master zonegroup" << dendl;
1122 return -EINVAL;
f67539c2
TL
1123 }
1124
20effc67 1125 return 0;
f67539c2
TL
1126}
1127
39ae355f
TL
1128int RadosStore::forward_iam_request_to_master(const DoutPrefixProvider *dpp, const RGWAccessKey& key, obj_version* objv,
1129 bufferlist& in_data,
1130 RGWXMLDecoder::XMLParser* parser, req_info& info,
1131 optional_yield y)
1132{
1133 if (is_meta_master()) {
1134 /* We're master, don't forward */
1135 return 0;
1136 }
1137
1138 if (!svc()->zone->get_master_conn()) {
1139 ldpp_dout(dpp, 0) << "rest connection is invalid" << dendl;
1140 return -EINVAL;
1141 }
1142 ldpp_dout(dpp, 0) << "sending request to master zonegroup" << dendl;
1143 bufferlist response;
1144#define MAX_REST_RESPONSE (128 * 1024) // we expect a very small response
1145 int ret = svc()->zone->get_master_conn()->forward_iam_request(dpp, key, info,
1146 objv, MAX_REST_RESPONSE,
1147 &in_data, &response, y);
1148 if (ret < 0)
1149 return ret;
1150
1151 ldpp_dout(dpp, 20) << "response: " << response.c_str() << dendl;
1152
1153 std::string r = response.c_str();
1154 std::string str_to_search = "&quot;";
1155 std::string str_to_replace = "\"";
1156 boost::replace_all(r, str_to_search, str_to_replace);
1157 ldpp_dout(dpp, 20) << "r: " << r.c_str() << dendl;
1158
1159 if (parser && !parser->parse(r.c_str(), r.length(), 1)) {
1160 ldpp_dout(dpp, 0) << "ERROR: failed to parse response from master zonegroup" << dendl;
1161 return -EIO;
1162 }
1163
1164 return 0;
1165}
1166
20effc67 1167std::string RadosStore::zone_unique_id(uint64_t unique_num)
f67539c2 1168{
20effc67 1169 return svc()->zone_utils->unique_id(unique_num);
f67539c2
TL
1170}
1171
20effc67 1172std::string RadosStore::zone_unique_trans_id(const uint64_t unique_num)
f67539c2 1173{
20effc67
TL
1174 return svc()->zone_utils->unique_trans_id(unique_num);
1175}
f67539c2 1176
20effc67
TL
1177int RadosStore::cluster_stat(RGWClusterStat& stats)
1178{
1179 rados_cluster_stat_t rados_stats;
1180 int ret;
f67539c2 1181
20effc67 1182 ret = rados->get_rados_handle()->cluster_stat(rados_stats);
f67539c2
TL
1183 if (ret < 0)
1184 return ret;
1185
20effc67
TL
1186 stats.kb = rados_stats.kb;
1187 stats.kb_used = rados_stats.kb_used;
1188 stats.kb_avail = rados_stats.kb_avail;
1189 stats.num_objects = rados_stats.num_objects;
f67539c2
TL
1190
1191 return ret;
1192}
1193
20effc67 1194std::unique_ptr<Lifecycle> RadosStore::get_lifecycle(void)
f67539c2 1195{
20effc67 1196 return std::make_unique<RadosLifecycle>(this);
f67539c2
TL
1197}
1198
20effc67 1199std::unique_ptr<Completions> RadosStore::get_completions(void)
f67539c2 1200{
20effc67 1201 return std::make_unique<RadosCompletions>();
f67539c2
TL
1202}
1203
20effc67
TL
1204std::unique_ptr<Notification> RadosStore::get_notification(
1205 rgw::sal::Object* obj, rgw::sal::Object* src_obj, struct req_state* s, rgw::notify::EventType event_type, const std::string* object_name)
f67539c2 1206{
20effc67 1207 return std::make_unique<RadosNotification>(s, this, obj, src_obj, s, event_type, object_name);
f67539c2
TL
1208}
1209
20effc67 1210std::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)
f67539c2 1211{
20effc67
TL
1212 return std::make_unique<RadosNotification>(dpp, this, obj, src_obj, rctx, event_type, _bucket, _user_id, _user_tenant, _req_id, y);
1213}
f67539c2 1214
20effc67
TL
1215int RadosStore::delete_raw_obj(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj)
1216{
1217 return rados->delete_raw_obj(dpp, obj);
1218}
f67539c2 1219
20effc67
TL
1220int RadosStore::delete_raw_obj_aio(const DoutPrefixProvider *dpp, const rgw_raw_obj& obj, Completions* aio)
1221{
1222 RadosCompletions* raio = static_cast<RadosCompletions*>(aio);
f67539c2 1223
20effc67 1224 return rados->delete_raw_obj_aio(dpp, obj, raio->handles);
f67539c2
TL
1225}
1226
20effc67
TL
1227void RadosStore::get_raw_obj(const rgw_placement_rule& placement_rule, const rgw_obj& obj, rgw_raw_obj* raw_obj)
1228{
1229 rados->obj_to_raw(placement_rule, obj, raw_obj);
1230}
1231
1232int RadosStore::get_raw_chunk_size(const DoutPrefixProvider* dpp, const rgw_raw_obj& obj, uint64_t* chunk_size)
1233{
1234 return rados->get_max_chunk_size(obj.pool, chunk_size, dpp);
1235}
1236
1237int RadosStore::log_usage(const DoutPrefixProvider *dpp, map<rgw_user_bucket, RGWUsageBatch>& usage_info)
1238{
1239 return rados->log_usage(dpp, usage_info);
1240}
1241
1242int RadosStore::log_op(const DoutPrefixProvider *dpp, std::string& oid, bufferlist& bl)
1243{
1244 rgw_raw_obj obj(svc()->zone->get_zone_params().log_pool, oid);
1245
1246 int ret = rados->append_async(dpp, obj, bl.length(), bl);
1247 if (ret == -ENOENT) {
1248 ret = rados->create_pool(dpp, svc()->zone->get_zone_params().log_pool);
1249 if (ret < 0)
1250 return ret;
1251 // retry
1252 ret = rados->append_async(dpp, obj, bl.length(), bl);
1253 }
1254
1255 return ret;
1256}
1257
1258int RadosStore::register_to_service_map(const DoutPrefixProvider *dpp, const std::string& daemon_type,
1259 const map<std::string, std::string>& meta)
1260{
1261 return rados->register_to_service_map(dpp, daemon_type, meta);
1262}
1263
1264void RadosStore::get_quota(RGWQuotaInfo& bucket_quota, RGWQuotaInfo& user_quota)
1265{
1266 bucket_quota = svc()->quota->get_bucket_quota();
1267 user_quota = svc()->quota->get_user_quota();
1268}
1269
1270void RadosStore::get_ratelimit(RGWRateLimitInfo& bucket_ratelimit, RGWRateLimitInfo& user_ratelimit, RGWRateLimitInfo& anon_ratelimit)
1271{
1272 bucket_ratelimit = svc()->zone->get_current_period().get_config().bucket_ratelimit;
1273 user_ratelimit = svc()->zone->get_current_period().get_config().user_ratelimit;
1274 anon_ratelimit = svc()->zone->get_current_period().get_config().anon_ratelimit;
1275}
1276
1277int RadosStore::set_buckets_enabled(const DoutPrefixProvider* dpp, vector<rgw_bucket>& buckets, bool enabled)
1278{
1279 return rados->set_buckets_enabled(buckets, enabled, dpp);
1280}
1281
1282int RadosStore::get_sync_policy_handler(const DoutPrefixProvider* dpp,
1283 std::optional<rgw_zone_id> zone,
1284 std::optional<rgw_bucket> bucket,
1285 RGWBucketSyncPolicyHandlerRef* phandler,
1286 optional_yield y)
1287{
1288 return ctl()->bucket->get_sync_policy_handler(zone, bucket, phandler, y, dpp);
1289}
1290
1291RGWDataSyncStatusManager* RadosStore::get_data_sync_manager(const rgw_zone_id& source_zone)
1292{
1293 return rados->get_data_sync_manager(source_zone);
1294}
1295
1296int RadosStore::read_all_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch,
1297 uint32_t max_entries, bool* is_truncated,
1298 RGWUsageIter& usage_iter,
1299 map<rgw_user_bucket, rgw_usage_log_entry>& usage)
1300{
1301 rgw_user uid;
1302 std::string bucket_name;
1303
1304 return rados->read_usage(dpp, uid, bucket_name, start_epoch, end_epoch, max_entries,
1305 is_truncated, usage_iter, usage);
1306}
1307
1308int RadosStore::trim_all_usage(const DoutPrefixProvider *dpp, uint64_t start_epoch, uint64_t end_epoch)
1309{
1310 rgw_user uid;
1311 std::string bucket_name;
1312
1313 return rados->trim_usage(dpp, uid, bucket_name, start_epoch, end_epoch);
1314}
1315
1316int RadosStore::get_config_key_val(std::string name, bufferlist* bl)
1317{
1318 return svc()->config_key->get(name, true, bl);
1319}
1320
1321int RadosStore::meta_list_keys_init(const DoutPrefixProvider *dpp, const std::string& section, const std::string& marker, void** phandle)
1322{
1323 return ctl()->meta.mgr->list_keys_init(dpp, section, marker, phandle);
1324}
1325
1326int RadosStore::meta_list_keys_next(const DoutPrefixProvider *dpp, void* handle, int max, list<std::string>& keys, bool* truncated)
1327{
1328 return ctl()->meta.mgr->list_keys_next(dpp, handle, max, keys, truncated);
1329}
1330
1331void RadosStore::meta_list_keys_complete(void* handle)
1332{
1333 ctl()->meta.mgr->list_keys_complete(handle);
1334}
1335
1336std::string RadosStore::meta_get_marker(void* handle)
1337{
1338 return ctl()->meta.mgr->get_marker(handle);
1339}
1340
1341int RadosStore::meta_remove(const DoutPrefixProvider* dpp, std::string& metadata_key, optional_yield y)
1342{
1343 return ctl()->meta.mgr->remove(metadata_key, y, dpp);
1344}
1345
1346void RadosStore::finalize(void)
1347{
1348 if (rados)
1349 rados->finalize();
1350}
1351
1352std::unique_ptr<LuaScriptManager> RadosStore::get_lua_script_manager()
1353{
1354 return std::make_unique<RadosLuaScriptManager>(this);
1355}
1356
1357std::unique_ptr<RGWRole> RadosStore::get_role(std::string name,
1358 std::string tenant,
1359 std::string path,
1360 std::string trust_policy,
1361 std::string max_session_duration_str,
1362 std::multimap<std::string,std::string> tags)
1363{
1364 return std::make_unique<RadosRole>(this, name, tenant, path, trust_policy, max_session_duration_str, tags);
1365}
1366
1367std::unique_ptr<RGWRole> RadosStore::get_role(std::string id)
1368{
1369 return std::make_unique<RadosRole>(this, id);
1370}
1371
39ae355f
TL
1372std::unique_ptr<RGWRole> RadosStore::get_role(const RGWRoleInfo& info)
1373{
1374 return std::make_unique<RadosRole>(this, info);
1375}
1376
20effc67
TL
1377int RadosStore::get_roles(const DoutPrefixProvider *dpp,
1378 optional_yield y,
1379 const std::string& path_prefix,
1380 const std::string& tenant,
1381 vector<std::unique_ptr<RGWRole>>& roles)
1382{
1383 auto pool = get_zone()->get_params().roles_pool;
1384 std::string prefix;
1385
1386 // List all roles if path prefix is empty
1387 if (! path_prefix.empty()) {
1388 prefix = tenant + RGWRole::role_path_oid_prefix + path_prefix;
1389 } else {
1390 prefix = tenant + RGWRole::role_path_oid_prefix;
1391 }
1392
1393 //Get the filtered objects
1394 list<std::string> result;
1395 bool is_truncated;
1396 RGWListRawObjsCtx ctx;
1397 do {
1398 list<std::string> oids;
1399 int r = rados->list_raw_objects(dpp, pool, prefix, 1000, ctx, oids, &is_truncated);
1400 if (r < 0) {
1401 ldpp_dout(dpp, 0) << "ERROR: listing filtered objects failed: "
1402 << prefix << ": " << cpp_strerror(-r) << dendl;
1403 return r;
1404 }
1405 for (const auto& iter : oids) {
1406 result.push_back(iter.substr(RGWRole::role_path_oid_prefix.size()));
1407 }
1408 } while (is_truncated);
1409
1410 for (const auto& it : result) {
1411 //Find the role oid prefix from the end
1412 size_t pos = it.rfind(RGWRole::role_oid_prefix);
1413 if (pos == std::string::npos) {
1414 continue;
1415 }
1416 // Split the result into path and info_oid + id
1417 std::string path = it.substr(0, pos);
1418
1419 /*Make sure that prefix is part of path (False results could've been returned)
1420 because of the role info oid + id appended to the path)*/
1421 if(path_prefix.empty() || path.find(path_prefix) != std::string::npos) {
1422 //Get id from info oid prefix + id
1423 std::string id = it.substr(pos + RGWRole::role_oid_prefix.length());
1424
1425 std::unique_ptr<rgw::sal::RGWRole> role = get_role(id);
1426 int ret = role->read_info(dpp, y);
1427 if (ret < 0) {
1428 return ret;
1429 }
1430 roles.push_back(std::move(role));
1431 }
1432 }
1433
1434 return 0;
1435}
1436
1437std::unique_ptr<RGWOIDCProvider> RadosStore::get_oidc_provider()
1438{
1439 return std::make_unique<RadosOIDCProvider>(this);
1440}
1441
1442int RadosStore::get_oidc_providers(const DoutPrefixProvider *dpp,
1443 const std::string& tenant,
1444 vector<std::unique_ptr<RGWOIDCProvider>>& providers)
1445{
1446 std::string prefix = tenant + RGWOIDCProvider::oidc_url_oid_prefix;
1447 auto pool = zone.get_params().oidc_pool;
1448 auto obj_ctx = svc()->sysobj->init_obj_ctx();
1449
1450 //Get the filtered objects
1451 list<std::string> result;
1452 bool is_truncated;
1453 RGWListRawObjsCtx ctx;
1454 do {
1455 list<std::string> oids;
1456 int r = rados->list_raw_objects(dpp, pool, prefix, 1000, ctx, oids, &is_truncated);
1457 if (r < 0) {
1458 ldpp_dout(dpp, 0) << "ERROR: listing filtered objects failed: OIDC pool: "
1459 << pool.name << ": " << prefix << ": " << cpp_strerror(-r) << dendl;
1460 return r;
1461 }
1462 for (const auto& iter : oids) {
1463 std::unique_ptr<rgw::sal::RGWOIDCProvider> provider = get_oidc_provider();
1464 bufferlist bl;
1465
1466 r = rgw_get_system_obj(obj_ctx, pool, iter, bl, nullptr, nullptr, null_yield, dpp);
1467 if (r < 0) {
1468 return r;
1469 }
1470
1471 try {
1472 using ceph::decode;
1473 auto iter = bl.cbegin();
1474 decode(*provider, iter);
1475 } catch (buffer::error& err) {
1476 ldpp_dout(dpp, 0) << "ERROR: failed to decode oidc provider info from pool: "
1477 << pool.name << ": " << iter << dendl;
1478 return -EIO;
1479 }
1480
1481 providers.push_back(std::move(provider));
1482 }
1483 } while (is_truncated);
1484
1485 return 0;
1486}
1487
1488std::unique_ptr<Writer> RadosStore::get_append_writer(const DoutPrefixProvider *dpp,
1489 optional_yield y,
1490 std::unique_ptr<rgw::sal::Object> _head_obj,
1491 const rgw_user& owner, RGWObjectCtx& obj_ctx,
1492 const rgw_placement_rule *ptail_placement_rule,
1493 const std::string& unique_tag,
1494 uint64_t position,
1495 uint64_t *cur_accounted_size)
1496{
1497 auto aio = rgw::make_throttle(ctx()->_conf->rgw_put_obj_min_window_size, y);
1498 return std::make_unique<RadosAppendWriter>(dpp, y,
1499 std::move(_head_obj),
1500 this, std::move(aio), owner, obj_ctx,
1501 ptail_placement_rule,
1502 unique_tag, position,
1503 cur_accounted_size);
1504}
1505
1506std::unique_ptr<Writer> RadosStore::get_atomic_writer(const DoutPrefixProvider *dpp,
1507 optional_yield y,
1508 std::unique_ptr<rgw::sal::Object> _head_obj,
1509 const rgw_user& owner, RGWObjectCtx& obj_ctx,
1510 const rgw_placement_rule *ptail_placement_rule,
1511 uint64_t olh_epoch,
1512 const std::string& unique_tag)
1513{
1514 auto aio = rgw::make_throttle(ctx()->_conf->rgw_put_obj_min_window_size, y);
1515 return std::make_unique<RadosAtomicWriter>(dpp, y,
1516 std::move(_head_obj),
1517 this, std::move(aio), owner, obj_ctx,
1518 ptail_placement_rule,
1519 olh_epoch, unique_tag);
1520}
1521
1522int RadosStore::get_obj_head_ioctx(const DoutPrefixProvider *dpp, const RGWBucketInfo& bucket_info, const rgw_obj& obj, librados::IoCtx* ioctx)
1523{
1524 return rados->get_obj_head_ioctx(dpp, bucket_info, obj, ioctx);
1525}
1526
1527RadosObject::~RadosObject() {}
1528
1529int RadosObject::get_obj_state(const DoutPrefixProvider* dpp, RGWObjectCtx* rctx, RGWObjState **state, optional_yield y, bool follow_olh)
1530{
1531 return store->getRados()->get_obj_state(dpp, rctx, bucket->get_info(), get_obj(), state, follow_olh, y);
1532}
1533
1534int RadosObject::read_attrs(const DoutPrefixProvider* dpp, RGWRados::Object::Read &read_op, optional_yield y, rgw_obj* target_obj)
1535{
1536 read_op.params.attrs = &attrs;
1537 read_op.params.target_obj = target_obj;
1538 read_op.params.obj_size = &obj_size;
1539 read_op.params.lastmod = &mtime;
1540
1541 return read_op.prepare(y, dpp);
1542}
1543
1544int RadosObject::set_obj_attrs(const DoutPrefixProvider* dpp, RGWObjectCtx* rctx, Attrs* setattrs, Attrs* delattrs, optional_yield y, rgw_obj* target_obj)
1545{
1546 Attrs empty;
1547 rgw_obj target = get_obj();
1548
1549 if (!target_obj)
1550 target_obj = &target;
1551
1552 return store->getRados()->set_attrs(dpp, rctx,
1553 bucket->get_info(),
1554 *target_obj,
1555 setattrs ? *setattrs : empty,
1556 delattrs ? delattrs : nullptr,
1557 y);
1558}
1559
1560int RadosObject::get_obj_attrs(RGWObjectCtx* rctx, optional_yield y, const DoutPrefixProvider* dpp, rgw_obj* target_obj)
1561{
1562 RGWRados::Object op_target(store->getRados(), bucket->get_info(), *rctx, get_obj());
1563 RGWRados::Object::Read read_op(&op_target);
1564
1565 return read_attrs(dpp, read_op, y, target_obj);
1566}
1567
1568int RadosObject::modify_obj_attrs(RGWObjectCtx* rctx, const char* attr_name, bufferlist& attr_val, optional_yield y, const DoutPrefixProvider* dpp)
1569{
1570 rgw_obj target = get_obj();
1571 int r = get_obj_attrs(rctx, y, dpp, &target);
1572 if (r < 0) {
1573 return r;
1574 }
1575 set_atomic(rctx);
1576 attrs[attr_name] = attr_val;
1577 return set_obj_attrs(dpp, rctx, &attrs, nullptr, y, &target);
1578}
1579
1580int RadosObject::delete_obj_attrs(const DoutPrefixProvider* dpp, RGWObjectCtx* rctx, const char* attr_name, optional_yield y)
1581{
1582 Attrs rmattr;
1583 bufferlist bl;
1584
1585 set_atomic(rctx);
1586 rmattr[attr_name] = bl;
1587 return set_obj_attrs(dpp, rctx, nullptr, &rmattr, y);
1588}
1589
1590void RadosObject::set_compressed(RGWObjectCtx* rctx) {
1591 rgw_obj obj = get_obj();
1592 store->getRados()->set_compressed(rctx, obj);
1593}
1594
1595void RadosObject::set_atomic(RGWObjectCtx* rctx) const
1596{
1597 rgw_obj obj = get_obj();
1598 store->getRados()->set_atomic(rctx, obj);
1599}
1600
1601void RadosObject::set_prefetch_data(RGWObjectCtx* rctx)
1602{
1603 rgw_obj obj = get_obj();
1604 store->getRados()->set_prefetch_data(rctx, obj);
1605}
1606
1607bool RadosObject::is_expired() {
1608 auto iter = attrs.find(RGW_ATTR_DELETE_AT);
1609 if (iter != attrs.end()) {
1610 utime_t delete_at;
1611 try {
1612 auto bufit = iter->second.cbegin();
1613 decode(delete_at, bufit);
1614 } catch (buffer::error& err) {
1615 ldout(store->ctx(), 0) << "ERROR: " << __func__ << ": failed to decode " RGW_ATTR_DELETE_AT " attr" << dendl;
1616 return false;
1617 }
1618
1619 if (delete_at <= ceph_clock_now() && !delete_at.is_zero()) {
1620 return true;
1621 }
1622 }
1623
1624 return false;
1625}
1626
1627void RadosObject::gen_rand_obj_instance_name()
1628{
1629 store->getRados()->gen_rand_obj_instance_name(&key);
1630}
1631
1632void RadosObject::raw_obj_to_obj(const rgw_raw_obj& raw_obj)
1633{
1634 rgw_obj tobj = get_obj();
1635 RGWSI_Tier_RADOS::raw_obj_to_obj(get_bucket()->get_key(), raw_obj, &tobj);
1636 set_key(tobj.key);
1637}
1638
1639void RadosObject::get_raw_obj(rgw_raw_obj* raw_obj)
1640{
1641 store->getRados()->obj_to_raw((bucket->get_info()).placement_rule, get_obj(), raw_obj);
1642}
1643
1644int RadosObject::omap_get_vals(const DoutPrefixProvider *dpp, const std::string& marker, uint64_t count,
1645 std::map<std::string, bufferlist> *m,
1646 bool* pmore, optional_yield y)
1647{
1648 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
1649 rgw_raw_obj raw_obj;
1650 get_raw_obj(&raw_obj);
1651 auto sysobj = obj_ctx.get_obj(raw_obj);
1652
1653 return sysobj.omap().get_vals(dpp, marker, count, m, pmore, y);
1654}
1655
1656int RadosObject::omap_get_all(const DoutPrefixProvider *dpp, std::map<std::string, bufferlist> *m,
1657 optional_yield y)
1658{
1659 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
1660 rgw_raw_obj raw_obj;
1661 get_raw_obj(&raw_obj);
1662 auto sysobj = obj_ctx.get_obj(raw_obj);
1663
1664 return sysobj.omap().get_all(dpp, m, y);
1665}
1666
1667int RadosObject::omap_get_vals_by_keys(const DoutPrefixProvider *dpp, const std::string& oid,
1668 const std::set<std::string>& keys,
1669 Attrs* vals)
1670{
1671 int ret;
1672 rgw_raw_obj head_obj;
1673 librados::IoCtx cur_ioctx;
1674 rgw_obj obj = get_obj();
1675
1676 store->getRados()->obj_to_raw(bucket->get_placement_rule(), obj, &head_obj);
1677 ret = store->get_obj_head_ioctx(dpp, bucket->get_info(), obj, &cur_ioctx);
1678 if (ret < 0) {
1679 return ret;
1680 }
1681
1682 return cur_ioctx.omap_get_vals_by_keys(oid, keys, vals);
1683}
1684
1685int RadosObject::omap_set_val_by_key(const DoutPrefixProvider *dpp, const std::string& key, bufferlist& val,
1686 bool must_exist, optional_yield y)
1687{
1688 rgw_raw_obj raw_meta_obj;
1689 rgw_obj obj = get_obj();
1690
1691 store->getRados()->obj_to_raw(bucket->get_placement_rule(), obj, &raw_meta_obj);
1692
1693 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
1694 auto sysobj = obj_ctx.get_obj(raw_meta_obj);
1695
1696 return sysobj.omap().set_must_exist(must_exist).set(dpp, key, val, y);
1697}
1698
39ae355f
TL
1699int RadosObject::chown(User& new_user, const DoutPrefixProvider* dpp, optional_yield y)
1700{
1701 RGWObjectCtx obj_ctx(store);
1702 int r = get_obj_attrs(&obj_ctx, y, dpp);
1703 if (r < 0) {
1704 ldpp_dout(dpp, 0) << "ERROR: failed to read object attrs " << get_name() << cpp_strerror(-r) << dendl;
1705 return r;
1706 }
1707
1708 const auto& aiter = get_attrs().find(RGW_ATTR_ACL);
1709 if (aiter == get_attrs().end()) {
1710 ldpp_dout(dpp, 0) << "ERROR: no acls found for object " << get_name() << dendl;
1711 return -EINVAL;
1712 }
1713
1714 bufferlist& bl = aiter->second;
1715 RGWAccessControlPolicy policy(store->ctx());
1716 ACLOwner owner;
1717 auto bliter = bl.cbegin();
1718 try {
1719 policy.decode(bliter);
1720 owner = policy.get_owner();
1721 } catch (buffer::error& err) {
1722 ldpp_dout(dpp, 0) << "ERROR: decode policy failed" << err.what()
1723 << dendl;
1724 return -EIO;
1725 }
1726
1727 //Get the ACL from the policy
1728 RGWAccessControlList& acl = policy.get_acl();
1729
1730 //Remove grant that is set to old owner
1731 acl.remove_canon_user_grant(owner.get_id());
1732
1733 //Create a grant and add grant
1734 ACLGrant grant;
1735 grant.set_canon(new_user.get_id(), new_user.get_display_name(), RGW_PERM_FULL_CONTROL);
1736 acl.add_grant(&grant);
1737
1738 //Update the ACL owner to the new user
1739 owner.set_id(new_user.get_id());
1740 owner.set_name(new_user.get_display_name());
1741 policy.set_owner(owner);
1742
1743 bl.clear();
1744 encode(policy, bl);
1745
1746 set_atomic(&obj_ctx);
1747 map<string, bufferlist> attrs;
1748 attrs[RGW_ATTR_ACL] = bl;
1749 r = set_obj_attrs(dpp, &obj_ctx, &attrs, nullptr, y);
1750 if (r < 0) {
1751 ldpp_dout(dpp, 0) << "ERROR: modify attr failed " << cpp_strerror(-r) << dendl;
1752 return r;
1753 }
1754
1755 return 0;
1756}
1757
20effc67
TL
1758MPSerializer* RadosObject::get_serializer(const DoutPrefixProvider *dpp, const std::string& lock_name)
1759{
1760 return new MPRadosSerializer(dpp, store, this, lock_name);
1761}
1762
1763int RadosObject::transition(RGWObjectCtx& rctx,
1764 Bucket* bucket,
1765 const rgw_placement_rule& placement_rule,
1766 const real_time& mtime,
1767 uint64_t olh_epoch,
1768 const DoutPrefixProvider* dpp,
1769 optional_yield y)
1770{
1771 return store->getRados()->transition_obj(rctx, bucket, *this, placement_rule, mtime, olh_epoch, dpp, y);
1772}
1773
1774int RadosObject::get_max_chunk_size(const DoutPrefixProvider* dpp, rgw_placement_rule placement_rule, uint64_t* max_chunk_size, uint64_t* alignment)
1775{
1776 return store->getRados()->get_max_chunk_size(placement_rule, get_obj(), max_chunk_size, dpp, alignment);
1777}
1778
1779void RadosObject::get_max_aligned_size(uint64_t size, uint64_t alignment,
1780 uint64_t* max_size)
1781{
1782 store->getRados()->get_max_aligned_size(size, alignment, max_size);
1783}
1784
1785bool RadosObject::placement_rules_match(rgw_placement_rule& r1, rgw_placement_rule& r2)
1786{
1787 rgw_obj obj;
1788 rgw_pool p1, p2;
1789
1790 obj = get_obj();
1791
1792 if (r1 == r2)
1793 return true;
1794
1795 if (!store->getRados()->get_obj_data_pool(r1, obj, &p1)) {
1796 return false;
1797 }
1798 if (!store->getRados()->get_obj_data_pool(r2, obj, &p2)) {
1799 return false;
1800 }
1801
1802 return p1 == p2;
1803}
1804
1805int RadosObject::dump_obj_layout(const DoutPrefixProvider *dpp, optional_yield y, Formatter* f, RGWObjectCtx* obj_ctx)
1806{
1807 int ret;
1808 RGWObjManifest *manifest{nullptr};
1809 rgw_raw_obj head_obj;
1810
1811 RGWRados::Object op_target(store->getRados(), get_bucket()->get_info(),
1812 *obj_ctx, get_obj());
1813 RGWRados::Object::Read parent_op(&op_target);
1814 uint64_t obj_size;
1815
1816 parent_op.params.obj_size = &obj_size;
1817 parent_op.params.attrs = &get_attrs();
1818
1819 ret = parent_op.prepare(y, dpp);
1820 if (ret < 0) {
1821 return ret;
1822 }
1823
1824 head_obj = parent_op.state.head_obj;
1825
1826 ret = op_target.get_manifest(dpp, &manifest, y);
1827 if (ret < 0) {
1828 return ret;
1829 }
1830
1831 ::encode_json("head", head_obj, f);
1832 ::encode_json("manifest", *manifest, f);
1833 f->open_array_section("data_location");
1834 for (auto miter = manifest->obj_begin(dpp); miter != manifest->obj_end(dpp); ++miter) {
1835 f->open_object_section("obj");
1836 rgw_raw_obj raw_loc = miter.get_location().get_raw_obj(store);
1837 uint64_t ofs = miter.get_ofs();
1838 uint64_t left = manifest->get_obj_size() - ofs;
1839 ::encode_json("ofs", miter.get_ofs(), f);
1840 ::encode_json("loc", raw_loc, f);
1841 ::encode_json("loc_ofs", miter.location_ofs(), f);
1842 uint64_t loc_size = miter.get_stripe_size();
1843 if (loc_size > left) {
1844 loc_size = left;
1845 }
1846 ::encode_json("loc_size", loc_size, f);
1847 f->close_section();
1848 }
1849 f->close_section();
1850
1851 return 0;
1852}
1853
1854std::unique_ptr<Object::ReadOp> RadosObject::get_read_op(RGWObjectCtx* ctx)
1855{
1856 return std::make_unique<RadosObject::RadosReadOp>(this, ctx);
1857}
1858
1859RadosObject::RadosReadOp::RadosReadOp(RadosObject *_source, RGWObjectCtx *_rctx) :
1860 source(_source),
1861 rctx(_rctx),
1862 op_target(_source->store->getRados(),
1863 _source->get_bucket()->get_info(),
1864 *static_cast<RGWObjectCtx *>(rctx),
1865 _source->get_obj()),
1866 parent_op(&op_target)
1867{ }
1868
1869int RadosObject::RadosReadOp::prepare(optional_yield y, const DoutPrefixProvider* dpp)
1870{
1871 uint64_t obj_size;
1872
1873 parent_op.conds.mod_ptr = params.mod_ptr;
1874 parent_op.conds.unmod_ptr = params.unmod_ptr;
1875 parent_op.conds.high_precision_time = params.high_precision_time;
1876 parent_op.conds.mod_zone_id = params.mod_zone_id;
1877 parent_op.conds.mod_pg_ver = params.mod_pg_ver;
1878 parent_op.conds.if_match = params.if_match;
1879 parent_op.conds.if_nomatch = params.if_nomatch;
1880 parent_op.params.lastmod = params.lastmod;
1881 parent_op.params.target_obj = params.target_obj;
1882 parent_op.params.obj_size = &obj_size;
1883 parent_op.params.attrs = &source->get_attrs();
1884
1885 int ret = parent_op.prepare(y, dpp);
1886 if (ret < 0)
1887 return ret;
1888
1889 source->set_key(parent_op.state.obj.key);
1890 source->set_obj_size(obj_size);
1891
1892 return ret;
1893}
1894
1895int RadosObject::RadosReadOp::read(int64_t ofs, int64_t end, bufferlist& bl, optional_yield y, const DoutPrefixProvider* dpp)
1896{
1897 return parent_op.read(ofs, end, bl, y, dpp);
1898}
1899
1900int RadosObject::RadosReadOp::get_attr(const DoutPrefixProvider* dpp, const char* name, bufferlist& dest, optional_yield y)
1901{
1902 return parent_op.get_attr(dpp, name, dest, y);
1903}
1904
1905std::unique_ptr<Object::DeleteOp> RadosObject::get_delete_op(RGWObjectCtx* ctx)
1906{
1907 return std::make_unique<RadosObject::RadosDeleteOp>(this, ctx);
1908}
1909
1910RadosObject::RadosDeleteOp::RadosDeleteOp(RadosObject *_source, RGWObjectCtx *_rctx) :
1911 source(_source),
1912 rctx(_rctx),
1913 op_target(_source->store->getRados(),
1914 _source->get_bucket()->get_info(),
1915 *static_cast<RGWObjectCtx *>(rctx),
1916 _source->get_obj()),
1917 parent_op(&op_target)
1918{ }
1919
1920int RadosObject::RadosDeleteOp::delete_obj(const DoutPrefixProvider* dpp, optional_yield y)
1921{
1922 parent_op.params.bucket_owner = params.bucket_owner.get_id();
1923 parent_op.params.versioning_status = params.versioning_status;
1924 parent_op.params.obj_owner = params.obj_owner;
1925 parent_op.params.olh_epoch = params.olh_epoch;
1926 parent_op.params.marker_version_id = params.marker_version_id;
1927 parent_op.params.bilog_flags = params.bilog_flags;
1928 parent_op.params.remove_objs = params.remove_objs;
1929 parent_op.params.expiration_time = params.expiration_time;
1930 parent_op.params.unmod_since = params.unmod_since;
1931 parent_op.params.mtime = params.mtime;
1932 parent_op.params.high_precision_time = params.high_precision_time;
1933 parent_op.params.zones_trace = params.zones_trace;
1934 parent_op.params.abortmp = params.abortmp;
1935 parent_op.params.parts_accounted_size = params.parts_accounted_size;
1936
1937 int ret = parent_op.delete_obj(y, dpp);
1938 if (ret < 0)
1939 return ret;
1940
1941 result.delete_marker = parent_op.result.delete_marker;
1942 result.version_id = parent_op.result.version_id;
1943
1944 return ret;
1945}
1946
1947int RadosObject::delete_object(const DoutPrefixProvider* dpp,
1948 RGWObjectCtx* obj_ctx,
1949 optional_yield y,
1950 bool prevent_versioning)
1951{
1952 RGWRados::Object del_target(store->getRados(), bucket->get_info(), *obj_ctx, get_obj());
1953 RGWRados::Object::Delete del_op(&del_target);
1954
1955 del_op.params.bucket_owner = bucket->get_info().owner;
1956 del_op.params.versioning_status = prevent_versioning ? 0 : bucket->get_info().versioning_status();
1957
1958 return del_op.delete_obj(y, dpp);
1959}
1960
1961int RadosObject::delete_obj_aio(const DoutPrefixProvider* dpp, RGWObjState* astate,
1962 Completions* aio, bool keep_index_consistent,
1963 optional_yield y)
1964{
1965 RadosCompletions* raio = static_cast<RadosCompletions*>(aio);
1966
1967 return store->getRados()->delete_obj_aio(dpp, get_obj(), bucket->get_info(), astate,
1968 raio->handles, keep_index_consistent, y);
1969}
1970
1971int RadosObject::copy_object(RGWObjectCtx& obj_ctx,
1972 User* user,
1973 req_info* info,
1974 const rgw_zone_id& source_zone,
1975 rgw::sal::Object* dest_object,
1976 rgw::sal::Bucket* dest_bucket,
1977 rgw::sal::Bucket* src_bucket,
1978 const rgw_placement_rule& dest_placement,
1979 ceph::real_time* src_mtime,
1980 ceph::real_time* mtime,
1981 const ceph::real_time* mod_ptr,
1982 const ceph::real_time* unmod_ptr,
1983 bool high_precision_time,
1984 const char* if_match,
1985 const char* if_nomatch,
f67539c2
TL
1986 AttrsMod attrs_mod,
1987 bool copy_if_newer,
20effc67 1988 Attrs& attrs,
f67539c2
TL
1989 RGWObjCategory category,
1990 uint64_t olh_epoch,
1991 boost::optional<ceph::real_time> delete_at,
20effc67
TL
1992 std::string* version_id,
1993 std::string* tag,
1994 std::string* etag,
f67539c2 1995 void (*progress_cb)(off_t, void *),
20effc67
TL
1996 void* progress_data,
1997 const DoutPrefixProvider* dpp,
f67539c2
TL
1998 optional_yield y)
1999{
2000 return store->getRados()->copy_obj(obj_ctx,
2001 user->get_id(),
2002 info,
2003 source_zone,
2004 dest_object,
2005 this,
2006 dest_bucket,
2007 src_bucket,
2008 dest_placement,
2009 src_mtime,
2010 mtime,
2011 mod_ptr,
2012 unmod_ptr,
2013 high_precision_time,
2014 if_match,
2015 if_nomatch,
2016 static_cast<RGWRados::AttrsMod>(attrs_mod),
2017 copy_if_newer,
2018 attrs,
2019 category,
2020 olh_epoch,
2021 (delete_at ? *delete_at : real_time()),
2022 version_id,
2023 tag,
2024 etag,
2025 progress_cb,
20effc67
TL
2026 progress_data,
2027 dpp,
2028 y);
f67539c2
TL
2029}
2030
20effc67 2031int RadosObject::RadosReadOp::iterate(const DoutPrefixProvider* dpp, int64_t ofs, int64_t end, RGWGetDataCB* cb, optional_yield y)
f67539c2 2032{
20effc67 2033 return parent_op.iterate(dpp, ofs, end, cb, y);
f67539c2
TL
2034}
2035
20effc67 2036int RadosObject::swift_versioning_restore(RGWObjectCtx* obj_ctx,
f67539c2 2037 bool& restored,
20effc67 2038 const DoutPrefixProvider* dpp)
f67539c2
TL
2039{
2040 return store->getRados()->swift_versioning_restore(*obj_ctx,
2041 bucket->get_owner()->get_id(),
2042 bucket,
2043 this,
2044 restored,
2045 dpp);
2046}
2047
20effc67
TL
2048int RadosObject::swift_versioning_copy(RGWObjectCtx* obj_ctx,
2049 const DoutPrefixProvider* dpp,
f67539c2
TL
2050 optional_yield y)
2051{
2052 return store->getRados()->swift_versioning_copy(*obj_ctx,
2053 bucket->get_info().owner,
2054 bucket,
2055 this,
2056 dpp,
2057 y);
2058}
2059
20effc67
TL
2060int RadosMultipartUpload::abort(const DoutPrefixProvider *dpp, CephContext *cct,
2061 RGWObjectCtx *obj_ctx)
f67539c2 2062{
20effc67
TL
2063 std::unique_ptr<rgw::sal::Object> meta_obj = get_meta_obj();
2064 meta_obj->set_in_extra_data(true);
2065 meta_obj->set_hash_source(mp_obj.get_key());
2066 cls_rgw_obj_chain chain;
2067 list<rgw_obj_index_key> remove_objs;
2068 bool truncated;
2069 int marker = 0;
f67539c2 2070 int ret;
20effc67
TL
2071 uint64_t parts_accounted_size = 0;
2072
2073 do {
2074 ret = list_parts(dpp, cct, 1000, marker, &marker, &truncated);
2075 if (ret < 0) {
2076 ldpp_dout(dpp, 20) << __func__ << ": RadosMultipartUpload::list_parts returned " <<
2077 ret << dendl;
2078 return (ret == -ENOENT) ? -ERR_NO_SUCH_UPLOAD : ret;
2079 }
2080
2081 for (auto part_it = parts.begin();
2082 part_it != parts.end();
2083 ++part_it) {
2084 RadosMultipartPart* obj_part = dynamic_cast<RadosMultipartPart*>(part_it->second.get());
2085 if (obj_part->info.manifest.empty()) {
2086 std::unique_ptr<rgw::sal::Object> obj = bucket->get_object(
2087 rgw_obj_key(obj_part->oid, std::string(), RGW_OBJ_NS_MULTIPART));
2088 obj->set_hash_source(mp_obj.get_key());
2089 ret = obj->delete_object(dpp, obj_ctx, null_yield);
2090 if (ret < 0 && ret != -ENOENT)
2091 return ret;
2092 } else {
2093 auto target = meta_obj->get_obj();
2094 store->getRados()->update_gc_chain(dpp, target, obj_part->info.manifest, &chain);
2095 RGWObjManifest::obj_iterator oiter = obj_part->info.manifest.obj_begin(dpp);
2096 if (oiter != obj_part->info.manifest.obj_end(dpp)) {
2097 std::unique_ptr<rgw::sal::Object> head = bucket->get_object(rgw_obj_key());
2098 rgw_raw_obj raw_head = oiter.get_location().get_raw_obj(store);
2099 dynamic_cast<rgw::sal::RadosObject*>(head.get())->raw_obj_to_obj(raw_head);
2100
2101 rgw_obj_index_key key;
2102 head->get_key().get_index_key(&key);
2103 remove_objs.push_back(key);
2104 }
2105 }
2106 parts_accounted_size += obj_part->info.accounted_size;
2107 }
2108 } while (truncated);
2109
2110 if (store->getRados()->get_gc() == nullptr) {
2111 //Delete objects inline if gc hasn't been initialised (in case when bypass gc is specified)
2112 store->getRados()->delete_objs_inline(dpp, chain, mp_obj.get_upload_id());
2113 } else {
2114 /* use upload id as tag and do it synchronously */
39ae355f
TL
2115 auto [ret, leftover_chain] = store->getRados()->send_chain_to_gc(chain, mp_obj.get_upload_id());
2116 if (ret < 0 && leftover_chain) {
20effc67
TL
2117 ldpp_dout(dpp, 5) << __func__ << ": gc->send_chain() returned " << ret << dendl;
2118 if (ret == -ENOENT) {
2119 return -ERR_NO_SUCH_UPLOAD;
2120 }
2121 //Delete objects inline if send chain to gc fails
39ae355f 2122 store->getRados()->delete_objs_inline(dpp, *leftover_chain, mp_obj.get_upload_id());
20effc67
TL
2123 }
2124 }
f67539c2 2125
20effc67
TL
2126 std::unique_ptr<rgw::sal::Object::DeleteOp> del_op = meta_obj->get_delete_op(obj_ctx);
2127 del_op->params.bucket_owner = bucket->get_acl_owner();
2128 del_op->params.versioning_status = 0;
2129 if (!remove_objs.empty()) {
2130 del_op->params.remove_objs = &remove_objs;
2131 }
2132
2133 del_op->params.abortmp = true;
2134 del_op->params.parts_accounted_size = parts_accounted_size;
2135
2136 // and also remove the metadata obj
2137 ret = del_op->delete_obj(dpp, null_yield);
f67539c2 2138 if (ret < 0) {
20effc67
TL
2139 ldpp_dout(dpp, 20) << __func__ << ": del_op.delete_obj returned " <<
2140 ret << dendl;
f67539c2 2141 }
20effc67
TL
2142 return (ret == -ENOENT) ? -ERR_NO_SUCH_UPLOAD : ret;
2143}
f67539c2 2144
20effc67
TL
2145std::unique_ptr<rgw::sal::Object> RadosMultipartUpload::get_meta_obj()
2146{
2147 return bucket->get_object(rgw_obj_key(get_meta(), string(), mp_ns));
f67539c2
TL
2148}
2149
20effc67 2150int RadosMultipartUpload::init(const DoutPrefixProvider *dpp, optional_yield y, RGWObjectCtx* obj_ctx, ACLOwner& owner, rgw_placement_rule& dest_placement, rgw::sal::Attrs& attrs)
f67539c2 2151{
20effc67
TL
2152 int ret;
2153 std::string oid = mp_obj.get_key();
f67539c2 2154
20effc67
TL
2155 do {
2156 char buf[33];
2157 string tmp_obj_name;
2158 std::unique_ptr<rgw::sal::Object> obj;
2159 gen_rand_alphanumeric(store->ctx(), buf, sizeof(buf) - 1);
2160 std::string upload_id = MULTIPART_UPLOAD_ID_PREFIX; /* v2 upload id */
2161 upload_id.append(buf);
2162
2163 mp_obj.init(oid, upload_id);
2164 tmp_obj_name = mp_obj.get_meta();
2165
2166 obj = bucket->get_object(rgw_obj_key(tmp_obj_name, string(), mp_ns));
2167 // the meta object will be indexed with 0 size, we c
2168 obj->set_in_extra_data(true);
2169 obj->set_hash_source(oid);
2170
2171 RGWRados::Object op_target(store->getRados(),
2172 obj->get_bucket()->get_info(),
2173 *obj_ctx, obj->get_obj());
2174 RGWRados::Object::Write obj_op(&op_target);
2175
2176 op_target.set_versioning_disabled(true); /* no versioning for multipart meta */
2177 obj_op.meta.owner = owner.get_id();
2178 obj_op.meta.category = RGWObjCategory::MultiMeta;
2179 obj_op.meta.flags = PUT_OBJ_CREATE_EXCL;
2180 obj_op.meta.mtime = &mtime;
2181
2182 multipart_upload_info upload_info;
2183 upload_info.dest_placement = dest_placement;
2184
2185 bufferlist bl;
2186 encode(upload_info, bl);
2187 obj_op.meta.data = &bl;
2188
2189 ret = obj_op.write_meta(dpp, bl.length(), 0, attrs, y);
2190 } while (ret == -EEXIST);
f67539c2 2191
20effc67 2192 return ret;
f67539c2
TL
2193}
2194
20effc67
TL
2195int RadosMultipartUpload::list_parts(const DoutPrefixProvider *dpp, CephContext *cct,
2196 int num_parts, int marker,
2197 int *next_marker, bool *truncated,
2198 bool assume_unsorted)
f67539c2 2199{
20effc67
TL
2200 map<string, bufferlist> parts_map;
2201 map<string, bufferlist>::iterator iter;
f67539c2 2202
20effc67
TL
2203 std::unique_ptr<rgw::sal::Object> obj = bucket->get_object(
2204 rgw_obj_key(get_meta(), std::string(), RGW_OBJ_NS_MULTIPART));
2205 obj->set_in_extra_data(true);
f67539c2 2206
20effc67 2207 bool sorted_omap = is_v2_upload_id(get_upload_id()) && !assume_unsorted;
f67539c2 2208
20effc67
TL
2209 parts.clear();
2210
2211 int ret;
2212 if (sorted_omap) {
2213 string p;
2214 p = "part.";
2215 char buf[32];
2216
2217 snprintf(buf, sizeof(buf), "%08d", marker);
2218 p.append(buf);
2219
2220 ret = obj->omap_get_vals(dpp, p, num_parts + 1, &parts_map,
2221 nullptr, null_yield);
2222 } else {
2223 ret = obj->omap_get_all(dpp, &parts_map, null_yield);
f67539c2 2224 }
20effc67
TL
2225 if (ret < 0) {
2226 return ret;
f67539c2 2227 }
f67539c2 2228
20effc67
TL
2229 int i;
2230 int last_num = 0;
f67539c2 2231
20effc67 2232 uint32_t expected_next = marker + 1;
f67539c2 2233
20effc67
TL
2234 for (i = 0, iter = parts_map.begin();
2235 (i < num_parts || !sorted_omap) && iter != parts_map.end();
2236 ++iter, ++i) {
2237 bufferlist& bl = iter->second;
2238 auto bli = bl.cbegin();
2239 std::unique_ptr<RadosMultipartPart> part = std::make_unique<RadosMultipartPart>();
2240 try {
2241 decode(part->info, bli);
2242 } catch (buffer::error& err) {
2243 ldpp_dout(dpp, 0) << "ERROR: could not part info, caught buffer::error" <<
2244 dendl;
2245 return -EIO;
2246 }
2247 if (sorted_omap) {
2248 if (part->info.num != expected_next) {
2249 /* ouch, we expected a specific part num here, but we got a
2250 * different one. Either a part is missing, or it could be a
2251 * case of mixed rgw versions working on the same upload,
2252 * where one gateway doesn't support correctly sorted omap
2253 * keys for multipart upload just assume data is unsorted.
2254 */
2255 return list_parts(dpp, cct, num_parts, marker, next_marker, truncated, true);
2256 }
2257 expected_next++;
2258 }
2259 if (sorted_omap ||
2260 (int)part->info.num > marker) {
2261 last_num = part->info.num;
2262 parts[part->info.num] = std::move(part);
2263 }
f67539c2 2264 }
f67539c2 2265
20effc67
TL
2266 if (sorted_omap) {
2267 if (truncated) {
2268 *truncated = (iter != parts_map.end());
2269 }
2270 } else {
2271 /* rebuild a map with only num_parts entries */
2272 std::map<uint32_t, std::unique_ptr<MultipartPart>> new_parts;
2273 std::map<uint32_t, std::unique_ptr<MultipartPart>>::iterator piter;
2274 for (i = 0, piter = parts.begin();
2275 i < num_parts && piter != parts.end();
2276 ++i, ++piter) {
2277 last_num = piter->first;
2278 new_parts[piter->first] = std::move(piter->second);
2279 }
f67539c2 2280
20effc67
TL
2281 if (truncated) {
2282 *truncated = (piter != parts.end());
2283 }
f67539c2 2284
20effc67 2285 parts.swap(new_parts);
f67539c2 2286 }
f67539c2 2287
20effc67
TL
2288 if (next_marker) {
2289 *next_marker = last_num;
f67539c2
TL
2290 }
2291
2292 return 0;
2293}
2294
20effc67
TL
2295int RadosMultipartUpload::complete(const DoutPrefixProvider *dpp,
2296 optional_yield y, CephContext* cct,
2297 map<int, string>& part_etags,
2298 list<rgw_obj_index_key>& remove_objs,
2299 uint64_t& accounted_size, bool& compressed,
2300 RGWCompressionInfo& cs_info, off_t& ofs,
2301 std::string& tag, ACLOwner& owner,
2302 uint64_t olh_epoch,
2303 rgw::sal::Object* target_obj,
2304 RGWObjectCtx* obj_ctx)
2305{
2306 char final_etag[CEPH_CRYPTO_MD5_DIGESTSIZE];
2307 char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16];
2308 std::string etag;
2309 bufferlist etag_bl;
2310 MD5 hash;
2311 // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
2312 hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
2313 bool truncated;
2314 int ret;
f67539c2 2315
20effc67
TL
2316 int total_parts = 0;
2317 int handled_parts = 0;
2318 int max_parts = 1000;
2319 int marker = 0;
2320 uint64_t min_part_size = cct->_conf->rgw_multipart_min_part_size;
2321 auto etags_iter = part_etags.begin();
2322 rgw::sal::Attrs attrs = target_obj->get_attrs();
f67539c2 2323
20effc67
TL
2324 do {
2325 ret = list_parts(dpp, cct, max_parts, marker, &marker, &truncated);
2326 if (ret == -ENOENT) {
2327 ret = -ERR_NO_SUCH_UPLOAD;
2328 }
2329 if (ret < 0)
2330 return ret;
f67539c2 2331
20effc67
TL
2332 total_parts += parts.size();
2333 if (!truncated && total_parts != (int)part_etags.size()) {
2334 ldpp_dout(dpp, 0) << "NOTICE: total parts mismatch: have: " << total_parts
2335 << " expected: " << part_etags.size() << dendl;
2336 ret = -ERR_INVALID_PART;
2337 return ret;
2338 }
f67539c2 2339
20effc67
TL
2340 for (auto obj_iter = parts.begin(); etags_iter != part_etags.end() && obj_iter != parts.end(); ++etags_iter, ++obj_iter, ++handled_parts) {
2341 RadosMultipartPart* part = dynamic_cast<rgw::sal::RadosMultipartPart*>(obj_iter->second.get());
2342 uint64_t part_size = part->get_size();
2343 if (handled_parts < (int)part_etags.size() - 1 &&
2344 part_size < min_part_size) {
2345 ret = -ERR_TOO_SMALL;
2346 return ret;
2347 }
f67539c2 2348
20effc67
TL
2349 char petag[CEPH_CRYPTO_MD5_DIGESTSIZE];
2350 if (etags_iter->first != (int)obj_iter->first) {
2351 ldpp_dout(dpp, 0) << "NOTICE: parts num mismatch: next requested: "
2352 << etags_iter->first << " next uploaded: "
2353 << obj_iter->first << dendl;
2354 ret = -ERR_INVALID_PART;
2355 return ret;
2356 }
2357 string part_etag = rgw_string_unquote(etags_iter->second);
2358 if (part_etag.compare(part->get_etag()) != 0) {
2359 ldpp_dout(dpp, 0) << "NOTICE: etag mismatch: part: " << etags_iter->first
2360 << " etag: " << etags_iter->second << dendl;
2361 ret = -ERR_INVALID_PART;
2362 return ret;
2363 }
f67539c2 2364
20effc67
TL
2365 hex_to_buf(part->get_etag().c_str(), petag,
2366 CEPH_CRYPTO_MD5_DIGESTSIZE);
2367 hash.Update((const unsigned char *)petag, sizeof(petag));
f67539c2 2368
20effc67 2369 RGWUploadPartInfo& obj_part = part->info;
f67539c2 2370
20effc67
TL
2371 /* update manifest for part */
2372 string oid = mp_obj.get_part(part->info.num);
2373 rgw_obj src_obj;
2374 src_obj.init_ns(bucket->get_key(), oid, mp_ns);
f67539c2 2375
20effc67
TL
2376 if (obj_part.manifest.empty()) {
2377 ldpp_dout(dpp, 0) << "ERROR: empty manifest for object part: obj="
2378 << src_obj << dendl;
2379 ret = -ERR_INVALID_PART;
2380 return ret;
2381 } else {
2382 manifest.append(dpp, obj_part.manifest, store->get_zone());
2383 }
f67539c2 2384
20effc67
TL
2385 bool part_compressed = (obj_part.cs_info.compression_type != "none");
2386 if ((handled_parts > 0) &&
2387 ((part_compressed != compressed) ||
2388 (cs_info.compression_type != obj_part.cs_info.compression_type))) {
2389 ldpp_dout(dpp, 0) << "ERROR: compression type was changed during multipart upload ("
2390 << cs_info.compression_type << ">>" << obj_part.cs_info.compression_type << ")" << dendl;
2391 ret = -ERR_INVALID_PART;
2392 return ret;
2393 }
2394
2395 if (part_compressed) {
2396 int64_t new_ofs; // offset in compression data for new part
2397 if (cs_info.blocks.size() > 0)
2398 new_ofs = cs_info.blocks.back().new_ofs + cs_info.blocks.back().len;
2399 else
2400 new_ofs = 0;
2401 for (const auto& block : obj_part.cs_info.blocks) {
2402 compression_block cb;
2403 cb.old_ofs = block.old_ofs + cs_info.orig_size;
2404 cb.new_ofs = new_ofs;
2405 cb.len = block.len;
2406 cs_info.blocks.push_back(cb);
2407 new_ofs = cb.new_ofs + cb.len;
2408 }
2409 if (!compressed)
2410 cs_info.compression_type = obj_part.cs_info.compression_type;
2411 cs_info.orig_size += obj_part.cs_info.orig_size;
2412 compressed = true;
2413 }
f67539c2 2414
20effc67
TL
2415 rgw_obj_index_key remove_key;
2416 src_obj.key.get_index_key(&remove_key);
f67539c2 2417
20effc67
TL
2418 remove_objs.push_back(remove_key);
2419
2420 ofs += obj_part.size;
2421 accounted_size += obj_part.accounted_size;
f67539c2 2422 }
20effc67
TL
2423 } while (truncated);
2424 hash.Final((unsigned char *)final_etag);
2425
2426 buf_to_hex((unsigned char *)final_etag, sizeof(final_etag), final_etag_str);
2427 snprintf(&final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2],
2428 sizeof(final_etag_str) - CEPH_CRYPTO_MD5_DIGESTSIZE * 2,
2429 "-%lld", (long long)part_etags.size());
2430 etag = final_etag_str;
2431 ldpp_dout(dpp, 10) << "calculated etag: " << etag << dendl;
2432
2433 etag_bl.append(etag);
2434
2435 attrs[RGW_ATTR_ETAG] = etag_bl;
2436
2437 if (compressed) {
2438 // write compression attribute to full object
2439 bufferlist tmp;
2440 encode(cs_info, tmp);
2441 attrs[RGW_ATTR_COMPRESSION] = tmp;
f67539c2
TL
2442 }
2443
20effc67
TL
2444 target_obj->set_atomic(obj_ctx);
2445
2446 RGWRados::Object op_target(store->getRados(),
2447 target_obj->get_bucket()->get_info(),
2448 *obj_ctx, target_obj->get_obj());
2449 RGWRados::Object::Write obj_op(&op_target);
2450
2451 obj_op.meta.manifest = &manifest;
2452 obj_op.meta.remove_objs = &remove_objs;
2453
2454 obj_op.meta.ptag = &tag; /* use req_id as operation tag */
2455 obj_op.meta.owner = owner.get_id();
2456 obj_op.meta.flags = PUT_OBJ_CREATE;
2457 obj_op.meta.modify_tail = true;
2458 obj_op.meta.completeMultipart = true;
2459 obj_op.meta.olh_epoch = olh_epoch;
2460
2461 ret = obj_op.write_meta(dpp, ofs, accounted_size, attrs, y);
2462 if (ret < 0)
2463 return ret;
2464
2465 return ret;
2466}
2467
2468int RadosMultipartUpload::get_info(const DoutPrefixProvider *dpp, optional_yield y, RGWObjectCtx* obj_ctx, rgw_placement_rule** rule, rgw::sal::Attrs* attrs)
2469{
2470 if (!rule && !attrs) {
2471 return 0;
f67539c2
TL
2472 }
2473
20effc67
TL
2474 if (rule) {
2475 if (!placement.empty()) {
2476 *rule = &placement;
2477 if (!attrs) {
2478 /* Don't need attrs, done */
2479 return 0;
2480 }
2481 } else {
2482 *rule = nullptr;
f67539c2 2483 }
20effc67 2484 }
f67539c2 2485
20effc67
TL
2486 /* We need either attributes or placement, so we need a read */
2487 std::unique_ptr<rgw::sal::Object> meta_obj;
2488 meta_obj = get_meta_obj();
2489 meta_obj->set_in_extra_data(true);
2490
2491 multipart_upload_info upload_info;
2492 bufferlist headbl;
2493
2494 /* Read the obj head which contains the multipart_upload_info */
2495 std::unique_ptr<rgw::sal::Object::ReadOp> read_op = meta_obj->get_read_op(obj_ctx);
2496 meta_obj->set_prefetch_data(obj_ctx);
2497
2498 int ret = read_op->prepare(y, dpp);
2499 if (ret < 0) {
2500 if (ret == -ENOENT) {
2501 return -ERR_NO_SUCH_UPLOAD;
f67539c2 2502 }
20effc67 2503 return ret;
f67539c2
TL
2504 }
2505
20effc67 2506 extract_span_context(meta_obj->get_attrs(), trace_ctx);
f67539c2 2507
20effc67
TL
2508 if (attrs) {
2509 /* Attrs are filled in by prepare */
2510 *attrs = meta_obj->get_attrs();
2511 if (!rule || *rule != nullptr) {
2512 /* placement was cached; don't actually read */
2513 return 0;
2514 }
2515 }
f67539c2 2516
20effc67
TL
2517 /* Now read the placement from the head */
2518 ret = read_op->read(0, store->ctx()->_conf->rgw_max_chunk_size, headbl, y, dpp);
2519 if (ret < 0) {
2520 if (ret == -ENOENT) {
2521 return -ERR_NO_SUCH_UPLOAD;
2522 }
2523 return ret;
2524 }
f67539c2 2525
20effc67
TL
2526 if (headbl.length() <= 0) {
2527 return -ERR_NO_SUCH_UPLOAD;
2528 }
f67539c2 2529
20effc67
TL
2530 /* Decode multipart_upload_info */
2531 auto hiter = headbl.cbegin();
2532 try {
2533 decode(upload_info, hiter);
2534 } catch (buffer::error& err) {
2535 ldpp_dout(dpp, 0) << "ERROR: failed to decode multipart upload info" << dendl;
2536 return -EIO;
2537 }
2538 placement = upload_info.dest_placement;
2539 *rule = &placement;
f67539c2 2540
20effc67 2541 return 0;
f67539c2
TL
2542}
2543
20effc67
TL
2544std::unique_ptr<Writer> RadosMultipartUpload::get_writer(
2545 const DoutPrefixProvider *dpp,
2546 optional_yield y,
2547 std::unique_ptr<rgw::sal::Object> _head_obj,
2548 const rgw_user& owner, RGWObjectCtx& obj_ctx,
2549 const rgw_placement_rule *ptail_placement_rule,
2550 uint64_t part_num,
2551 const std::string& part_num_str)
f67539c2 2552{
20effc67
TL
2553 auto aio = rgw::make_throttle(store->ctx()->_conf->rgw_put_obj_min_window_size, y);
2554 return std::make_unique<RadosMultipartWriter>(dpp, y, this,
2555 std::move(_head_obj), store, std::move(aio), owner,
2556 obj_ctx, ptail_placement_rule, part_num, part_num_str);
f67539c2
TL
2557}
2558
20effc67 2559MPRadosSerializer::MPRadosSerializer(const DoutPrefixProvider *dpp, RadosStore* store, RadosObject* obj, const std::string& lock_name) :
f67539c2
TL
2560 lock(lock_name)
2561{
2562 rgw_pool meta_pool;
2563 rgw_raw_obj raw_obj;
2564
2565 obj->get_raw_obj(&raw_obj);
2566 oid = raw_obj.oid;
2567 store->getRados()->get_obj_data_pool(obj->get_bucket()->get_placement_rule(),
2568 obj->get_obj(), &meta_pool);
b3b6e05e 2569 store->getRados()->open_pool_ctx(dpp, meta_pool, ioctx, true);
f67539c2
TL
2570}
2571
b3b6e05e 2572int MPRadosSerializer::try_lock(const DoutPrefixProvider *dpp, utime_t dur, optional_yield y)
f67539c2
TL
2573{
2574 op.assert_exists();
2575 lock.set_duration(dur);
2576 lock.lock_exclusive(&op);
b3b6e05e 2577 int ret = rgw_rados_operate(dpp, ioctx, oid, &op, y);
f67539c2
TL
2578 if (! ret) {
2579 locked = true;
2580 }
2581 return ret;
2582}
2583
20effc67 2584LCRadosSerializer::LCRadosSerializer(RadosStore* store, const std::string& _oid, const std::string& lock_name, const std::string& cookie) :
f67539c2
TL
2585 lock(lock_name), oid(_oid)
2586{
2587 ioctx = &store->getRados()->lc_pool_ctx;
2588 lock.set_cookie(cookie);
2589}
2590
b3b6e05e 2591int LCRadosSerializer::try_lock(const DoutPrefixProvider *dpp, utime_t dur, optional_yield y)
f67539c2
TL
2592{
2593 lock.set_duration(dur);
2594 return lock.lock_exclusive(ioctx, oid);
2595}
2596
20effc67 2597int RadosLifecycle::get_entry(const std::string& oid, const std::string& marker,
f67539c2
TL
2598 LCEntry& entry)
2599{
2600 cls_rgw_lc_entry cls_entry;
2601 int ret = cls_rgw_lc_get_entry(*store->getRados()->get_lc_pool_ctx(), oid, marker, cls_entry);
2602
2603 entry.bucket = cls_entry.bucket;
2604 entry.start_time = cls_entry.start_time;
2605 entry.status = cls_entry.status;
2606
2607 return ret;
2608}
2609
20effc67 2610int RadosLifecycle::get_next_entry(const std::string& oid, std::string& marker,
f67539c2
TL
2611 LCEntry& entry)
2612{
2613 cls_rgw_lc_entry cls_entry;
2614 int ret = cls_rgw_lc_get_next_entry(*store->getRados()->get_lc_pool_ctx(), oid, marker,
2615 cls_entry);
2616
2617 entry.bucket = cls_entry.bucket;
2618 entry.start_time = cls_entry.start_time;
2619 entry.status = cls_entry.status;
2620
2621 return ret;
2622}
2623
20effc67 2624int RadosLifecycle::set_entry(const std::string& oid, const LCEntry& entry)
f67539c2
TL
2625{
2626 cls_rgw_lc_entry cls_entry;
2627
2628 cls_entry.bucket = entry.bucket;
2629 cls_entry.start_time = entry.start_time;
2630 cls_entry.status = entry.status;
2631
2632 return cls_rgw_lc_set_entry(*store->getRados()->get_lc_pool_ctx(), oid, cls_entry);
2633}
2634
20effc67 2635int RadosLifecycle::list_entries(const std::string& oid, const std::string& marker,
f67539c2
TL
2636 uint32_t max_entries, vector<LCEntry>& entries)
2637{
2638 entries.clear();
2639
2640 vector<cls_rgw_lc_entry> cls_entries;
2641 int ret = cls_rgw_lc_list(*store->getRados()->get_lc_pool_ctx(), oid, marker, max_entries, cls_entries);
2642
2643 if (ret < 0)
2644 return ret;
2645
2646 for (auto& entry : cls_entries) {
2647 entries.push_back(LCEntry(entry.bucket, entry.start_time, entry.status));
2648 }
2649
2650 return ret;
2651}
2652
20effc67 2653int RadosLifecycle::rm_entry(const std::string& oid, const LCEntry& entry)
f67539c2
TL
2654{
2655 cls_rgw_lc_entry cls_entry;
2656
2657 cls_entry.bucket = entry.bucket;
2658 cls_entry.start_time = entry.start_time;
2659 cls_entry.status = entry.status;
2660
2661 return cls_rgw_lc_rm_entry(*store->getRados()->get_lc_pool_ctx(), oid, cls_entry);
2662}
2663
20effc67 2664int RadosLifecycle::get_head(const std::string& oid, LCHead& head)
f67539c2
TL
2665{
2666 cls_rgw_lc_obj_head cls_head;
2667 int ret = cls_rgw_lc_get_head(*store->getRados()->get_lc_pool_ctx(), oid, cls_head);
2668
2669 head.marker = cls_head.marker;
2670 head.start_date = cls_head.start_date;
2671
2672 return ret;
2673}
2674
20effc67 2675int RadosLifecycle::put_head(const std::string& oid, const LCHead& head)
f67539c2
TL
2676{
2677 cls_rgw_lc_obj_head cls_head;
2678
2679 cls_head.marker = head.marker;
2680 cls_head.start_date = head.start_date;
2681
2682 return cls_rgw_lc_put_head(*store->getRados()->get_lc_pool_ctx(), oid, cls_head);
2683}
2684
2685LCSerializer* RadosLifecycle::get_serializer(const std::string& lock_name, const std::string& oid, const std::string& cookie)
2686{
2687 return new LCRadosSerializer(store, oid, lock_name, cookie);
2688}
2689
20effc67
TL
2690int RadosNotification::publish_reserve(const DoutPrefixProvider *dpp, RGWObjTags* obj_tags)
2691{
2692 return rgw::notify::publish_reserve(dpp, event_type, res, obj_tags);
2693}
2694
2695int RadosNotification::publish_commit(const DoutPrefixProvider* dpp, uint64_t size,
2696 const ceph::real_time& mtime, const std::string& etag, const std::string& version)
2697{
2698 return rgw::notify::publish_commit(obj, size, mtime, etag, version, event_type, res, dpp);
2699}
2700
2701int RadosAtomicWriter::prepare(optional_yield y)
2702{
2703 return processor.prepare(y);
2704}
2705
2706int RadosAtomicWriter::process(bufferlist&& data, uint64_t offset)
2707{
2708 return processor.process(std::move(data), offset);
2709}
2710
2711int RadosAtomicWriter::complete(size_t accounted_size, const std::string& etag,
2712 ceph::real_time *mtime, ceph::real_time set_mtime,
2713 std::map<std::string, bufferlist>& attrs,
2714 ceph::real_time delete_at,
2715 const char *if_match, const char *if_nomatch,
2716 const std::string *user_data,
2717 rgw_zone_set *zones_trace, bool *canceled,
2718 optional_yield y)
2719{
2720 return processor.complete(accounted_size, etag, mtime, set_mtime, attrs, delete_at,
2721 if_match, if_nomatch, user_data, zones_trace, canceled, y);
2722}
2723
2724int RadosAppendWriter::prepare(optional_yield y)
2725{
2726 return processor.prepare(y);
2727}
2728
2729int RadosAppendWriter::process(bufferlist&& data, uint64_t offset)
2730{
2731 return processor.process(std::move(data), offset);
2732}
2733
2734int RadosAppendWriter::complete(size_t accounted_size, const std::string& etag,
2735 ceph::real_time *mtime, ceph::real_time set_mtime,
2736 std::map<std::string, bufferlist>& attrs,
2737 ceph::real_time delete_at,
2738 const char *if_match, const char *if_nomatch,
2739 const std::string *user_data,
2740 rgw_zone_set *zones_trace, bool *canceled,
2741 optional_yield y)
2742{
2743 return processor.complete(accounted_size, etag, mtime, set_mtime, attrs, delete_at,
2744 if_match, if_nomatch, user_data, zones_trace, canceled, y);
2745}
2746
2747int RadosMultipartWriter::prepare(optional_yield y)
2748{
2749 return processor.prepare(y);
2750}
2751
2752int RadosMultipartWriter::process(bufferlist&& data, uint64_t offset)
2753{
2754 return processor.process(std::move(data), offset);
2755}
2756
2757int RadosMultipartWriter::complete(size_t accounted_size, const std::string& etag,
2758 ceph::real_time *mtime, ceph::real_time set_mtime,
2759 std::map<std::string, bufferlist>& attrs,
2760 ceph::real_time delete_at,
2761 const char *if_match, const char *if_nomatch,
2762 const std::string *user_data,
2763 rgw_zone_set *zones_trace, bool *canceled,
2764 optional_yield y)
2765{
2766 return processor.complete(accounted_size, etag, mtime, set_mtime, attrs, delete_at,
2767 if_match, if_nomatch, user_data, zones_trace, canceled, y);
2768}
2769
2770const RGWZoneGroup& RadosZone::get_zonegroup()
2771{
2772 return store->svc()->zone->get_zonegroup();
2773}
2774
2775int RadosZone::get_zonegroup(const std::string& id, RGWZoneGroup& zonegroup)
2776{
2777 return store->svc()->zone->get_zonegroup(id, zonegroup);
2778}
2779
2780const RGWZoneParams& RadosZone::get_params()
2781{
2782 return store->svc()->zone->get_zone_params();
2783}
2784
2785const rgw_zone_id& RadosZone::get_id()
2786{
2787 return store->svc()->zone->zone_id();
2788}
2789
2790const RGWRealm& RadosZone::get_realm()
2791{
2792 return store->svc()->zone->get_realm();
2793}
2794
2795const std::string& RadosZone::get_name() const
2796{
2797 return store->svc()->zone->zone_name();
2798}
2799
2800bool RadosZone::is_writeable()
2801{
2802 return store->svc()->zone->zone_is_writeable();
2803}
2804
2805bool RadosZone::get_redirect_endpoint(std::string* endpoint)
2806{
2807 return store->svc()->zone->get_redirect_zone_endpoint(endpoint);
2808}
2809
2810bool RadosZone::has_zonegroup_api(const std::string& api) const
2811{
2812 return store->svc()->zone->has_zonegroup_api(api);
2813}
2814
2815const std::string& RadosZone::get_current_period_id()
2816{
2817 return store->svc()->zone->get_current_period_id();
2818}
f67539c2 2819
20effc67 2820int RadosLuaScriptManager::get(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, std::string& script)
f67539c2 2821{
20effc67
TL
2822 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2823 bufferlist bl;
f67539c2 2824
20effc67
TL
2825 int r = rgw_get_system_obj(obj_ctx, pool, key, bl, nullptr, nullptr, y, dpp);
2826 if (r < 0) {
2827 return r;
2828 }
f67539c2 2829
20effc67
TL
2830 auto iter = bl.cbegin();
2831 try {
2832 ceph::decode(script, iter);
2833 } catch (buffer::error& err) {
2834 return -EIO;
f67539c2
TL
2835 }
2836
20effc67
TL
2837 return 0;
2838}
2839
2840int RadosLuaScriptManager::put(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, const std::string& script)
2841{
2842 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2843 bufferlist bl;
2844 ceph::encode(script, bl);
2845
2846 int r = rgw_put_system_obj(dpp, obj_ctx, pool, key, bl, false, nullptr, real_time(), y);
2847 if (r < 0) {
2848 return r;
2849 }
2850
2851 return 0;
2852}
2853
2854int RadosLuaScriptManager::del(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key)
2855{
2856 int r = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, key, nullptr, y);
2857 if (r < 0 && r != -ENOENT) {
2858 return r;
2859 }
2860
2861 return 0;
2862}
2863
2864int RadosOIDCProvider::store_url(const DoutPrefixProvider *dpp, const std::string& url, bool exclusive, optional_yield y)
2865{
2866 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2867 std::string oid = tenant + get_url_oid_prefix() + url;
2868
2869 bufferlist bl;
2870 using ceph::encode;
2871 encode(*this, bl);
2872 return rgw_put_system_obj(dpp, obj_ctx, store->get_zone()->get_params().oidc_pool, oid, bl, exclusive, nullptr, real_time(), y);
f67539c2
TL
2873}
2874
20effc67 2875int RadosOIDCProvider::read_url(const DoutPrefixProvider *dpp, const std::string& url, const std::string& tenant)
f67539c2 2876{
20effc67
TL
2877 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2878 auto& pool = store->get_zone()->get_params().oidc_pool;
2879 std::string oid = tenant + get_url_oid_prefix() + url;
2880 bufferlist bl;
2881
2882 int ret = rgw_get_system_obj(obj_ctx, pool, oid, bl, nullptr, nullptr, null_yield, dpp);
2883 if (ret < 0) {
2884 return ret;
2885 }
2886
2887 try {
2888 using ceph::decode;
2889 auto iter = bl.cbegin();
2890 decode(*this, iter);
2891 } catch (buffer::error& err) {
2892 ldpp_dout(dpp, 0) << "ERROR: failed to decode oidc provider info from pool: " << pool.name <<
2893 ": " << url << dendl;
2894 return -EIO;
2895 }
f67539c2 2896
20effc67
TL
2897 return 0;
2898}
f67539c2 2899
20effc67
TL
2900int RadosOIDCProvider::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
2901{
2902 auto& pool = store->get_zone()->get_params().oidc_pool;
f67539c2 2903
20effc67
TL
2904 std::string url, tenant;
2905 auto ret = get_tenant_url_from_arn(tenant, url);
f67539c2 2906 if (ret < 0) {
20effc67
TL
2907 ldpp_dout(dpp, 0) << "ERROR: failed to parse arn" << dendl;
2908 return -EINVAL;
f67539c2
TL
2909 }
2910
20effc67
TL
2911 if (this->tenant != tenant) {
2912 ldpp_dout(dpp, 0) << "ERROR: tenant in arn doesn't match that of user " << this->tenant << ", "
2913 << tenant << ": " << dendl;
2914 return -EINVAL;
f67539c2
TL
2915 }
2916
20effc67
TL
2917 // Delete url
2918 std::string oid = tenant + get_url_oid_prefix() + url;
2919 ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
2920 if (ret < 0) {
2921 ldpp_dout(dpp, 0) << "ERROR: deleting oidc url from pool: " << pool.name << ": "
2922 << provider_url << ": " << cpp_strerror(-ret) << dendl;
2923 }
2924
2925 return ret;
f67539c2
TL
2926}
2927
20effc67 2928int RadosRole::store_info(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
f67539c2 2929{
20effc67 2930 using ceph::encode;
39ae355f
TL
2931 std::string oid;
2932
2933 oid = info.id;
20effc67
TL
2934
2935 bufferlist bl;
39ae355f 2936 encode(this->info, bl);
20effc67 2937
39ae355f 2938 if (!this->info.tags.empty()) {
20effc67 2939 bufferlist bl_tags;
39ae355f 2940 encode(this->info.tags, bl_tags);
20effc67
TL
2941 map<string, bufferlist> attrs;
2942 attrs.emplace("tagging", bl_tags);
20effc67 2943
39ae355f
TL
2944 RGWSI_MBSObj_PutParams params(bl, &attrs, info.mtime, exclusive);
2945 std::unique_ptr<RGWSI_MetaBackend::Context> ctx(store->svc()->role->svc.meta_be->alloc_ctx());
2946 ctx->init(store->svc()->role->get_be_handler());
2947 return store->svc()->role->svc.meta_be->put(ctx.get(), oid, params, &info.objv_tracker, y, dpp);
2948 } else {
2949 RGWSI_MBSObj_PutParams params(bl, nullptr, info.mtime, exclusive);
2950 std::unique_ptr<RGWSI_MetaBackend::Context> ctx(store->svc()->role->svc.meta_be->alloc_ctx());
2951 ctx->init(store->svc()->role->get_be_handler());
2952 return store->svc()->role->svc.meta_be->put(ctx.get(), oid, params, &info.objv_tracker, y, dpp);
2953 }
20effc67
TL
2954}
2955
2956int RadosRole::store_name(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
2957{
2958 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
2959 RGWNameToId nameToId;
39ae355f 2960 nameToId.obj_id = info.id;
20effc67 2961
39ae355f 2962 std::string oid = info.tenant + get_names_oid_prefix() + info.name;
20effc67
TL
2963
2964 bufferlist bl;
2965 using ceph::encode;
2966 encode(nameToId, bl);
2967
39ae355f 2968 return rgw_put_system_obj(dpp, obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, &info.objv_tracker, real_time(), y);
20effc67
TL
2969}
2970
2971int RadosRole::store_path(const DoutPrefixProvider *dpp, bool exclusive, optional_yield y)
2972{
2973 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
39ae355f 2974 std::string oid = info.tenant + get_path_oid_prefix() + info.path + get_info_oid_prefix() + info.id;
20effc67
TL
2975
2976 bufferlist bl;
2977
39ae355f 2978 return rgw_put_system_obj(dpp, obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, exclusive, &info.objv_tracker, real_time(), y);
20effc67
TL
2979}
2980
2981int RadosRole::read_id(const DoutPrefixProvider *dpp, const std::string& role_name, const std::string& tenant, std::string& role_id, optional_yield y)
2982{
2983 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
39ae355f 2984 std::string oid = info.tenant + get_names_oid_prefix() + role_name;
20effc67
TL
2985 bufferlist bl;
2986
2987 int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, dpp);
2988 if (ret < 0) {
2989 return ret;
2990 }
2991
2992 RGWNameToId nameToId;
2993 try {
2994 auto iter = bl.cbegin();
2995 using ceph::decode;
2996 decode(nameToId, iter);
2997 } catch (buffer::error& err) {
2998 ldpp_dout(dpp, 0) << "ERROR: failed to decode role from Role pool: " << role_name << dendl;
2999 return -EIO;
3000 }
3001 role_id = nameToId.obj_id;
3002 return 0;
3003}
3004
3005int RadosRole::read_name(const DoutPrefixProvider *dpp, optional_yield y)
3006{
3007 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
39ae355f 3008 std::string oid = info.tenant + get_names_oid_prefix() + info.name;
20effc67
TL
3009 bufferlist bl;
3010
3011 int ret = rgw_get_system_obj(obj_ctx, store->get_zone()->get_params().roles_pool, oid, bl, nullptr, nullptr, null_yield, dpp);
3012 if (ret < 0) {
39ae355f 3013 ldpp_dout(dpp, 0) << "ERROR: failed reading role name from Role pool: " << info.name <<
20effc67
TL
3014 ": " << cpp_strerror(-ret) << dendl;
3015 return ret;
3016 }
3017
3018 RGWNameToId nameToId;
3019 try {
3020 using ceph::decode;
3021 auto iter = bl.cbegin();
3022 decode(nameToId, iter);
3023 } catch (buffer::error& err) {
39ae355f 3024 ldpp_dout(dpp, 0) << "ERROR: failed to decode role name from Role pool: " << info.name << dendl;
20effc67
TL
3025 return -EIO;
3026 }
39ae355f 3027 info.id = nameToId.obj_id;
20effc67
TL
3028 return 0;
3029}
3030
3031int RadosRole::read_info(const DoutPrefixProvider *dpp, optional_yield y)
3032{
3033 auto obj_ctx = store->svc()->sysobj->init_obj_ctx();
39ae355f
TL
3034 std::string oid;
3035
3036 oid = info.id;
3037 ldpp_dout(dpp, 20) << "INFO: oid in read_info is: " << oid << dendl;
3038
20effc67
TL
3039 bufferlist bl;
3040
39ae355f
TL
3041 RGWSI_MBSObj_GetParams params(&bl, &info.attrs, &info.mtime);
3042 std::unique_ptr<RGWSI_MetaBackend::Context> ctx(store->svc()->role->svc.meta_be->alloc_ctx());
3043 ctx->init(store->svc()->role->get_be_handler());
3044 int ret = store->svc()->role->svc.meta_be->get(ctx.get(), oid, params, &info.objv_tracker, y, dpp, true);
20effc67 3045 if (ret < 0) {
39ae355f 3046 ldpp_dout(dpp, 0) << "ERROR: failed reading role info from Role pool: " << info.id << ": " << cpp_strerror(-ret) << dendl;
20effc67
TL
3047 return ret;
3048 }
3049
3050 try {
3051 using ceph::decode;
3052 auto iter = bl.cbegin();
39ae355f 3053 decode(this->info, iter);
20effc67 3054 } catch (buffer::error& err) {
39ae355f 3055 ldpp_dout(dpp, 0) << "ERROR: failed to decode role info from Role pool: " << info.id << dendl;
20effc67
TL
3056 return -EIO;
3057 }
3058
39ae355f
TL
3059 auto it = info.attrs.find("tagging");
3060 if (it != info.attrs.end()) {
20effc67
TL
3061 bufferlist bl_tags = it->second;
3062 try {
3063 using ceph::decode;
3064 auto iter = bl_tags.cbegin();
39ae355f 3065 decode(info.tags, iter);
20effc67 3066 } catch (buffer::error& err) {
39ae355f 3067 ldpp_dout(dpp, 0) << "ERROR: failed to decode attrs" << info.id << dendl;
20effc67
TL
3068 return -EIO;
3069 }
3070 }
3071
3072 return 0;
f67539c2
TL
3073}
3074
39ae355f 3075int RadosRole::create(const DoutPrefixProvider *dpp, bool exclusive, const std::string& role_id, optional_yield y)
f67539c2 3076{
20effc67
TL
3077 int ret;
3078
3079 if (! validate_input(dpp)) {
3080 return -EINVAL;
3081 }
3082
39ae355f
TL
3083 if (!role_id.empty()) {
3084 info.id = role_id;
3085 }
3086
20effc67 3087 /* check to see the name is not used */
39ae355f 3088 ret = read_id(dpp, info.name, info.tenant, info.id, y);
20effc67 3089 if (exclusive && ret == 0) {
39ae355f
TL
3090 ldpp_dout(dpp, 0) << "ERROR: name " << info.name << " already in use for role id "
3091 << info.id << dendl;
20effc67
TL
3092 return -EEXIST;
3093 } else if ( ret < 0 && ret != -ENOENT) {
39ae355f 3094 ldpp_dout(dpp, 0) << "failed reading role id " << info.id << ": "
20effc67
TL
3095 << cpp_strerror(-ret) << dendl;
3096 return ret;
3097 }
3098
39ae355f
TL
3099 if (info.id.empty()) {
3100 /* create unique id */
3101 uuid_d new_uuid;
3102 char uuid_str[37];
3103 new_uuid.generate_random();
3104 new_uuid.print(uuid_str);
3105 info.id = uuid_str;
3106 }
20effc67
TL
3107
3108 //arn
39ae355f 3109 info.arn = role_arn_prefix + info.tenant + ":role" + info.path + info.name;
20effc67
TL
3110
3111 // Creation time
3112 real_clock::time_point t = real_clock::now();
3113
3114 struct timeval tv;
3115 real_clock::to_timeval(t, tv);
3116
3117 char buf[30];
3118 struct tm result;
3119 gmtime_r(&tv.tv_sec, &result);
3120 strftime(buf,30,"%Y-%m-%dT%H:%M:%S", &result);
3121 sprintf(buf + strlen(buf),".%dZ",(int)tv.tv_usec/1000);
39ae355f 3122 info.creation_date.assign(buf, strlen(buf));
20effc67
TL
3123
3124 auto& pool = store->get_zone()->get_params().roles_pool;
3125 ret = store_info(dpp, exclusive, y);
3126 if (ret < 0) {
3127 ldpp_dout(dpp, 0) << "ERROR: storing role info in Role pool: "
39ae355f 3128 << info.id << ": " << cpp_strerror(-ret) << dendl;
20effc67
TL
3129 return ret;
3130 }
3131
3132 ret = store_name(dpp, exclusive, y);
3133 if (ret < 0) {
3134 ldpp_dout(dpp, 0) << "ERROR: storing role name in Role pool: "
39ae355f 3135 << info.name << ": " << cpp_strerror(-ret) << dendl;
20effc67
TL
3136
3137 //Delete the role info that was stored in the previous call
39ae355f 3138 std::string oid = get_info_oid_prefix() + info.id;
20effc67
TL
3139 int info_ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
3140 if (info_ret < 0) {
3141 ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from Role pool: "
39ae355f 3142 << info.id << ": " << cpp_strerror(-info_ret) << dendl;
20effc67
TL
3143 }
3144 return ret;
3145 }
3146
3147 ret = store_path(dpp, exclusive, y);
3148 if (ret < 0) {
3149 ldpp_dout(dpp, 0) << "ERROR: storing role path in Role pool: "
39ae355f 3150 << info.path << ": " << cpp_strerror(-ret) << dendl;
20effc67 3151 //Delete the role info that was stored in the previous call
39ae355f 3152 std::string oid = get_info_oid_prefix() + info.id;
20effc67
TL
3153 int info_ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
3154 if (info_ret < 0) {
3155 ldpp_dout(dpp, 0) << "ERROR: cleanup of role id from Role pool: "
39ae355f 3156 << info.id << ": " << cpp_strerror(-info_ret) << dendl;
20effc67
TL
3157 }
3158 //Delete role name that was stored in previous call
39ae355f 3159 oid = info.tenant + get_names_oid_prefix() + info.name;
20effc67
TL
3160 int name_ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
3161 if (name_ret < 0) {
3162 ldpp_dout(dpp, 0) << "ERROR: cleanup of role name from Role pool: "
39ae355f 3163 << info.name << ": " << cpp_strerror(-name_ret) << dendl;
20effc67
TL
3164 }
3165 return ret;
3166 }
3167 return 0;
3168}
3169
3170int RadosRole::delete_obj(const DoutPrefixProvider *dpp, optional_yield y)
3171{
3172 auto& pool = store->get_zone()->get_params().roles_pool;
f67539c2 3173
20effc67
TL
3174 int ret = read_name(dpp, y);
3175 if (ret < 0) {
3176 return ret;
3177 }
3178
3179 ret = read_info(dpp, y);
3180 if (ret < 0) {
3181 return ret;
3182 }
3183
39ae355f 3184 if (! info.perm_policy_map.empty()) {
20effc67
TL
3185 return -ERR_DELETE_CONFLICT;
3186 }
3187
3188 // Delete id
39ae355f 3189 std::string oid = get_info_oid_prefix() + info.id;
20effc67
TL
3190 ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
3191 if (ret < 0) {
3192 ldpp_dout(dpp, 0) << "ERROR: deleting role id from Role pool: "
39ae355f 3193 << info.id << ": " << cpp_strerror(-ret) << dendl;
20effc67
TL
3194 }
3195
3196 // Delete name
39ae355f 3197 oid = info.tenant + get_names_oid_prefix() + info.name;
20effc67
TL
3198 ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
3199 if (ret < 0) {
3200 ldpp_dout(dpp, 0) << "ERROR: deleting role name from Role pool: "
39ae355f 3201 << info.name << ": " << cpp_strerror(-ret) << dendl;
20effc67
TL
3202 }
3203
3204 // Delete path
39ae355f 3205 oid = info.tenant + get_path_oid_prefix() + info.path + get_info_oid_prefix() + info.id;
20effc67
TL
3206 ret = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, oid, nullptr, y);
3207 if (ret < 0) {
3208 ldpp_dout(dpp, 0) << "ERROR: deleting role path from Role pool: "
39ae355f 3209 << info.path << ": " << cpp_strerror(-ret) << dendl;
20effc67
TL
3210 }
3211 return ret;
3212}
3213
20effc67
TL
3214} // namespace rgw::sal
3215
3216extern "C" {
3217
3218void* newStore(void)
3219{
3220 rgw::sal::RadosStore* store = new rgw::sal::RadosStore();
3221 if (store) {
3222 RGWRados* rados = new RGWRados();
3223
3224 if (!rados) {
3225 delete store; store = nullptr;
3226 } else {
3227 store->setRados(rados);
3228 rados->set_store(store);
3229 }
3230 }
3231
3232 return store;
3233}
f67539c2 3234
f67539c2 3235}