From 70d5e211a3ce97daf4f62f9b57958899e7b65f01 Mon Sep 17 00:00:00 2001 From: Marcus Watts Date: Tue, 23 Jul 2019 20:43:38 -0400 Subject: [PATCH] Fix bucket versioning vs. swift metadata bug. When a bucket and object was "versioned", it was not possible to set swift metadata on an existing object. In swift, it is possible to post metadata (stored as extended attributes with specific names) on objects without bumping the version on a versioned object. In ceph, objects in versioned buckets *may* be versioned. Versioned objects have a "olh" (object logical header) header which points to the versioned header which contains or points to the current actual data for the object. Pre-existing logic here correctly sets the attributes for non-versioned objects. For versioned ojbects it incorrectly stored those attributes in the olh rather than in the versioned header. The corrected logic here retains the target object name and stores the attributes in the correct header for both cases rather than in the olh for the versioned object. Fixes: https://tracker.ceph.com/issues/37531 Signed-off-by: Marcus Watts --- src/rgw/rgw_op.cc | 9 ++++++--- src/rgw/rgw_rados.cc | 3 +++ src/rgw/rgw_rados.h | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 32971653f7c0..6d72e63e4bc3 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -321,12 +321,13 @@ vector get_iam_user_policy_from_attr(CephContext* cct, return policies; } -static int get_obj_attrs(RGWRados *store, struct req_state *s, const rgw_obj& obj, map& attrs) +static int get_obj_attrs(RGWRados *store, struct req_state *s, const rgw_obj& obj, map& attrs, rgw_obj *target_obj = nullptr) { RGWRados::Object op_target(store, s->bucket_info, *static_cast(s->obj_ctx), obj); RGWRados::Object::Read read_op(&op_target); read_op.params.attrs = &attrs; + read_op.params.target_obj = target_obj; return read_op.prepare(s->yield); } @@ -4497,6 +4498,7 @@ void RGWPutMetadataObject::pre_exec() void RGWPutMetadataObject::execute() { rgw_obj obj(s->bucket, s->object); + rgw_obj target_obj; map attrs, orig_attrs, rmattrs; store->set_atomic(s->obj_ctx, obj); @@ -4512,7 +4514,7 @@ void RGWPutMetadataObject::execute() } /* check if obj exists, read orig attrs */ - op_ret = get_obj_attrs(store, s, obj, orig_attrs); + op_ret = get_obj_attrs(store, s, obj, orig_attrs, &target_obj); if (op_ret < 0) { return; } @@ -4537,7 +4539,8 @@ void RGWPutMetadataObject::execute() } } - op_ret = store->set_attrs(s->obj_ctx, s->bucket_info, obj, attrs, &rmattrs, s->yield); + op_ret = store->set_attrs(s->obj_ctx, s->bucket_info, target_obj, + attrs, &rmattrs, s->yield); } int RGWDeleteObj::handle_slo_manifest(bufferlist& bl) diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 556aeda9503f..6ad79a8667e7 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -6351,6 +6351,9 @@ int RGWRados::Object::Read::prepare(optional_yield y) if (r < 0) { return r; } + if (params.target_obj) { + *params.target_obj = state.obj; + } if (params.attrs) { *params.attrs = astate->attrset; if (cct->_conf->subsys.should_gather()) { diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index 235dfab0a095..24df1102870c 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -1567,8 +1567,10 @@ public: ceph::real_time *lastmod; uint64_t *obj_size; map *attrs; + rgw_obj *target_obj; - Params() : lastmod(NULL), obj_size(NULL), attrs(NULL) {} + Params() : lastmod(nullptr), obj_size(nullptr), attrs(nullptr), + target_obj(nullptr) {} } params; explicit Read(RGWRados::Object *_source) : source(_source) {} -- 2.47.3