Skip to content

Commit a75cf5c

Browse files
authored
Merge pull request ceph#55259 from linuxbox2/wip-object-attributes
rgw: implement GetObjectAttributes
2 parents 8eac760 + 8f5f3fa commit a75cf5c

22 files changed

+625
-19
lines changed

src/rgw/driver/posix/rgw_sal_posix.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2893,6 +2893,14 @@ int POSIXObject::copy_object(const ACLOwner& owner,
28932893
return dobj->set_obj_attrs(dpp, &attrs, nullptr, y, rgw::sal::FLAG_LOG_OP);
28942894
}
28952895

2896+
int POSIXObject::list_parts(const DoutPrefixProvider* dpp, CephContext* cct,
2897+
int max_parts, int marker, int* next_marker,
2898+
bool* truncated, list_parts_each_t each_func,
2899+
optional_yield y)
2900+
{
2901+
return -EOPNOTSUPP;
2902+
}
2903+
28962904
int POSIXObject::load_obj_state(const DoutPrefixProvider* dpp, optional_yield y, bool follow_olh)
28972905
{
28982906
int ret = stat(dpp);

src/rgw/driver/posix/rgw_sal_posix.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,13 @@ class POSIXObject : public StoreObject {
653653
const DoutPrefixProvider* dpp, optional_yield y) override;
654654
virtual RGWAccessControlPolicy& get_acl(void) override { return acls; }
655655
virtual int set_acl(const RGWAccessControlPolicy& acl) override { acls = acl; return 0; }
656+
657+
/** If multipart, enumerate (a range [marker..marker+[min(max_parts, parts_count-1)] of) parts of the object */
658+
virtual int list_parts(const DoutPrefixProvider* dpp, CephContext* cct,
659+
int max_parts, int marker, int* next_marker,
660+
bool* truncated, list_parts_each_t each_func,
661+
optional_yield y) override;
662+
656663
virtual int load_obj_state(const DoutPrefixProvider* dpp, optional_yield y, bool follow_olh = true) override;
657664
virtual int set_obj_attrs(const DoutPrefixProvider* dpp, Attrs* setattrs,
658665
Attrs* delattrs, optional_yield y, uint32_t flags) override;

src/rgw/driver/rados/rgw_rados.cc

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6962,13 +6962,13 @@ int RGWRados::set_attrs(const DoutPrefixProvider *dpp, RGWObjectCtx* octx, RGWBu
69626962
}
69636963

69646964
return 0;
6965-
}
6965+
} /* RGWRados::set_attrs() */
69666966

6967-
static int get_part_obj_state(const DoutPrefixProvider* dpp, optional_yield y,
6968-
RGWRados* store, RGWBucketInfo& bucket_info,
6969-
RGWObjectCtx* rctx, RGWObjManifest* manifest,
6970-
int part_num, int* parts_count, bool prefetch,
6971-
RGWObjState** pstate, RGWObjManifest** pmanifest)
6967+
int RGWRados::get_part_obj_state(const DoutPrefixProvider* dpp, optional_yield y,
6968+
RGWRados* store, RGWBucketInfo& bucket_info,
6969+
RGWObjectCtx* rctx, RGWObjManifest* manifest,
6970+
int part_num, int* parts_count, bool prefetch,
6971+
RGWObjState** pstate, RGWObjManifest** pmanifest)
69726972
{
69736973
if (!manifest) {
69746974
return -ERR_INVALID_PART;
@@ -7047,6 +7047,9 @@ static int get_part_obj_state(const DoutPrefixProvider* dpp, optional_yield y,
70477047

70487048
// update the object size
70497049
sm->state.size = part_manifest.get_obj_size();
7050+
if (!sm->state.attrset.count(RGW_ATTR_COMPRESSION)) {
7051+
sm->state.accounted_size = sm->state.size;
7052+
}
70507053

70517054
*pmanifest = &part_manifest;
70527055
return 0;

src/rgw/driver/rados/rgw_rados.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,6 +1071,12 @@ class RGWRados
10711071
}; // class RGWRados::Bucket::List
10721072
}; // class RGWRados::Bucket
10731073

1074+
static int get_part_obj_state(const DoutPrefixProvider* dpp, optional_yield y,
1075+
RGWRados* store, RGWBucketInfo& bucket_info,
1076+
RGWObjectCtx* rctx, RGWObjManifest* manifest,
1077+
int part_num, int* parts_count, bool prefetch,
1078+
RGWObjState** pstate, RGWObjManifest** pmanifest);
1079+
10741080
int on_last_entry_in_listing(const DoutPrefixProvider *dpp,
10751081
RGWBucketInfo& bucket_info,
10761082
const std::string& obj_prefix,

src/rgw/driver/rados/rgw_sal_rados.cc

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2471,7 +2471,108 @@ bool RadosObject::is_sync_completed(const DoutPrefixProvider* dpp,
24712471

24722472
const rgw_bi_log_entry& earliest_marker = entries.front();
24732473
return earliest_marker.timestamp > obj_mtime;
2474-
}
2474+
} /* is_sync_completed */
2475+
2476+
int RadosObject::list_parts(const DoutPrefixProvider* dpp, CephContext* cct,
2477+
int max_parts, int marker, int* next_marker,
2478+
bool* truncated, list_parts_each_t each_func,
2479+
optional_yield y)
2480+
{
2481+
int ret{0};
2482+
2483+
/* require an object with a manifest, so call to get_obj_state() must precede this */
2484+
if (! manifest) {
2485+
return -EINVAL;
2486+
}
2487+
2488+
RGWObjManifest::obj_iterator end = manifest->obj_end(dpp);
2489+
if (end.get_cur_part_id() == 0) { // not multipart
2490+
ldpp_dout(dpp, 20) << __func__ << " object does not have a multipart manifest"
2491+
<< dendl;
2492+
return 0;
2493+
}
2494+
2495+
auto end_part_id = end.get_cur_part_id();
2496+
auto parts_count = (end_part_id == 1) ? 1 : end_part_id - 1;
2497+
if (marker > (parts_count - 1)) {
2498+
return 0;
2499+
}
2500+
2501+
RGWObjManifest::obj_iterator part_iter = manifest->obj_begin(dpp);
2502+
2503+
if (marker != 0) {
2504+
ldpp_dout_fmt(dpp, 20,
2505+
"{} seeking to part #{} in the object manifest",
2506+
__func__, marker);
2507+
2508+
part_iter = manifest->obj_find_part(dpp, marker + 1);
2509+
2510+
if (part_iter == end) {
2511+
ldpp_dout_fmt(dpp, 5,
2512+
"{} failed to find part #{} in the object manifest",
2513+
__func__, marker + 1);
2514+
return 0;
2515+
}
2516+
}
2517+
2518+
RGWObjectCtx& obj_ctx = get_ctx();
2519+
RGWBucketInfo& bucket_info = get_bucket()->get_info();
2520+
2521+
Object::Part obj_part{};
2522+
for (; part_iter != manifest->obj_end(dpp); ++part_iter) {
2523+
2524+
/* we're only interested in the first object in each logical part */
2525+
auto cur_part_id = part_iter.get_cur_part_id();
2526+
if (cur_part_id == obj_part.part_number) {
2527+
continue;
2528+
}
2529+
2530+
if (max_parts < 1) {
2531+
*truncated = true;
2532+
break;
2533+
}
2534+
2535+
/* get_part_obj_state alters the passed manifest** to point to a part
2536+
* manifest, which we don't want to leak out here */
2537+
RGWObjManifest* obj_m = manifest;
2538+
RGWObjState* astate;
2539+
bool part_prefetch = false;
2540+
ret = RGWRados::get_part_obj_state(dpp, y, store->getRados(), bucket_info, &obj_ctx,
2541+
obj_m, cur_part_id, &parts_count,
2542+
part_prefetch, &astate, &obj_m);
2543+
2544+
if (ret < 0) {
2545+
ldpp_dout_fmt(dpp, 4,
2546+
"{} get_part_obj_state() failed ret={}",
2547+
__func__, ret);
2548+
break;
2549+
}
2550+
2551+
obj_part.part_number = part_iter.get_cur_part_id();
2552+
obj_part.part_size = astate->accounted_size;
2553+
2554+
if (auto iter = astate->attrset.find(RGW_ATTR_CKSUM);
2555+
iter != astate->attrset.end()) {
2556+
try {
2557+
rgw::cksum::Cksum part_cksum;
2558+
auto ck_iter = iter->second.cbegin();
2559+
part_cksum.decode(ck_iter);
2560+
obj_part.cksum = std::move(part_cksum);
2561+
} catch (buffer::error& err) {
2562+
ldpp_dout_fmt(dpp, 4,
2563+
"WARN: {} could not decode stored cksum, "
2564+
"caught buffer::error",
2565+
__func__);
2566+
}
2567+
}
2568+
2569+
each_func(obj_part);
2570+
*next_marker = ++marker;
2571+
--max_parts;
2572+
} /* each part */
2573+
2574+
return ret;
2575+
} /* RadosObject::list_parts */
24752576

24762577
int RadosObject::load_obj_state(const DoutPrefixProvider* dpp, optional_yield y, bool follow_olh)
24772578
{

src/rgw/driver/rados/rgw_sal_rados.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,12 +592,18 @@ class RadosObject : public StoreObject {
592592
StoreObject::set_compressed();
593593
}
594594

595-
596595
virtual bool is_sync_completed(const DoutPrefixProvider* dpp,
597596
const ceph::real_time& obj_mtime) override;
598597
/* For rgw_admin.cc */
599598
RGWObjState& get_state() { return state; }
600599
virtual int load_obj_state(const DoutPrefixProvider* dpp, optional_yield y, bool follow_olh = true) override;
600+
601+
/** If multipart, enumerate (a range [marker..marker+[min(max_parts, parts_count-1)] of) parts of the object */
602+
virtual int list_parts(const DoutPrefixProvider* dpp, CephContext* cct,
603+
int max_parts, int marker, int* next_marker,
604+
bool* truncated, list_parts_each_t each_func,
605+
optional_yield y) override;
606+
601607
virtual int set_obj_attrs(const DoutPrefixProvider* dpp, Attrs* setattrs, Attrs* delattrs, optional_yield y, uint32_t flags) override;
602608
virtual int get_obj_attrs(optional_yield y, const DoutPrefixProvider* dpp, rgw_obj* target_obj = NULL) override;
603609
virtual int modify_obj_attrs(const char* attr_name, bufferlist& attr_val, optional_yield y, const DoutPrefixProvider* dpp) override;

src/rgw/rgw_cksum_pipe.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <string>
1919
#include <fmt/format.h>
2020
#include <boost/algorithm/string.hpp>
21+
#include "rgw_cksum.h"
2122
#include "rgw_common.h"
2223
#include "common/dout.h"
2324
#include "rgw_client_io.h"
@@ -34,7 +35,8 @@ namespace rgw::putobj {
3435
{}
3536

3637
std::unique_ptr<RGWPutObj_Cksum> RGWPutObj_Cksum::Factory(
37-
rgw::sal::DataProcessor* next, const RGWEnv& env)
38+
rgw::sal::DataProcessor* next, const RGWEnv& env,
39+
rgw::cksum::Type override_type)
3840
{
3941
/* look for matching headers */
4042
auto algo_header = cksum_algorithm_hdr(env);
@@ -49,6 +51,13 @@ namespace rgw::putobj {
4951
throw rgw::io::Exception(EINVAL, std::system_category());
5052
}
5153
/* no checksum header */
54+
if (override_type != rgw::cksum::Type::none) {
55+
/* XXXX safe? do we need to fixup env as well? */
56+
auto algo_header = cksum_algorithm_hdr(override_type);
57+
return
58+
std::make_unique<RGWPutObj_Cksum>(
59+
next, override_type, std::move(algo_header));
60+
}
5261
return std::unique_ptr<RGWPutObj_Cksum>();
5362
}
5463

src/rgw/rgw_cksum_pipe.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <tuple>
2121
#include <cstring>
2222
#include <boost/algorithm/string/case_conv.hpp>
23+
#include "rgw_cksum.h"
2324
#include "rgw_cksum_digest.h"
2425
#include "rgw_common.h"
2526
#include "rgw_putobj.h"
@@ -29,6 +30,38 @@ namespace rgw::putobj {
2930
namespace cksum = rgw::cksum;
3031
using cksum_hdr_t = std::pair<const char*, const char*>;
3132

33+
static inline const cksum_hdr_t cksum_algorithm_hdr(rgw::cksum::Type t) {
34+
static constexpr std::string_view hdr =
35+
"HTTP_X_AMZ_SDK_CHECKSUM_ALGORITHM";
36+
using rgw::cksum::Type;
37+
switch (t) {
38+
case Type::sha256:
39+
return cksum_hdr_t(hdr.data(), "SHA256");
40+
break;
41+
case Type::crc32:
42+
return cksum_hdr_t(hdr.data(), "CRC32");
43+
break;
44+
case Type::crc32c:
45+
return cksum_hdr_t(hdr.data(), "CRC32C");
46+
break;
47+
case Type::xxh3:
48+
return cksum_hdr_t(hdr.data(), "XX3");
49+
break;
50+
case Type::sha1:
51+
return cksum_hdr_t(hdr.data(), "SHA1");
52+
break;
53+
case Type::sha512:
54+
return cksum_hdr_t(hdr.data(), "SHA512");
55+
break;
56+
case Type::blake3:
57+
return cksum_hdr_t(hdr.data(), "BLAKE3");
58+
break;
59+
default:
60+
break;
61+
};
62+
return cksum_hdr_t(nullptr, nullptr);;
63+
}
64+
3265
static inline const cksum_hdr_t cksum_algorithm_hdr(const RGWEnv& env) {
3366
/* If the individual checksum value you provide through
3467
x-amz-checksum-algorithm doesn't match the checksum algorithm
@@ -102,7 +135,8 @@ namespace rgw::putobj {
102135
using VerifyResult = std::tuple<bool, const cksum::Cksum&>;
103136

104137
static std::unique_ptr<RGWPutObj_Cksum> Factory(
105-
rgw::sal::DataProcessor* next, const RGWEnv&);
138+
rgw::sal::DataProcessor* next, const RGWEnv&,
139+
rgw::cksum::Type override_type);
106140

107141
RGWPutObj_Cksum(rgw::sal::DataProcessor* next, rgw::cksum::Type _type,
108142
cksum_hdr_t&& _hdr);

src/rgw/rgw_iam_policy.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ static const actpair actpairs[] =
9494
{ "s3:GetPublicAccessBlock", s3GetPublicAccessBlock },
9595
{ "s3:GetObjectAcl", s3GetObjectAcl },
9696
{ "s3:GetObject", s3GetObject },
97+
{ "s3:GetObjectAttributes", s3GetObjectAttributes },
98+
{ "s3:GetObjectVersionAttributes", s3GetObjectVersionAttributes },
9799
{ "s3:GetObjectTorrent", s3GetObjectTorrent },
98100
{ "s3:GetObjectVersionAcl", s3GetObjectVersionAcl },
99101
{ "s3:GetObjectVersion", s3GetObjectVersion },
@@ -1335,6 +1337,7 @@ const char* action_bit_string(uint64_t action) {
13351337

13361338
case s3ListBucketVersions:
13371339
return "s3:ListBucketVersions";
1340+
13381341
case s3ListAllMyBuckets:
13391342
return "s3:ListAllMyBuckets";
13401343

@@ -1479,6 +1482,12 @@ const char* action_bit_string(uint64_t action) {
14791482
case s3BypassGovernanceRetention:
14801483
return "s3:BypassGovernanceRetention";
14811484

1485+
case s3GetObjectAttributes:
1486+
return "s3:GetObjectAttributes";
1487+
1488+
case s3GetObjectVersionAttributes:
1489+
return "s3:GetObjectVersionAttributes";
1490+
14821491
case s3DescribeJob:
14831492
return "s3:DescribeJob";
14841493

src/rgw/rgw_iam_policy.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ enum {
115115
s3GetBucketEncryption,
116116
s3PutBucketEncryption,
117117
s3DescribeJob,
118+
s3GetObjectAttributes,
119+
s3GetObjectVersionAttributes,
118120
s3All,
119121

120122
s3objectlambdaGetObject,
@@ -247,6 +249,8 @@ inline int op_to_perm(std::uint64_t op) {
247249
case s3GetObjectVersionTagging:
248250
case s3GetObjectRetention:
249251
case s3GetObjectLegalHold:
252+
case s3GetObjectAttributes:
253+
case s3GetObjectVersionAttributes:
250254
case s3ListAllMyBuckets:
251255
case s3ListBucket:
252256
case s3ListBucketMultipartUploads:

0 commit comments

Comments
 (0)