From 190f2935505dd504ee2c33d9966e84020d17faa0 Mon Sep 17 00:00:00 2001 From: Marcus Watts Date: Sat, 25 Aug 2018 05:48:41 -0400 Subject: [PATCH] rgw: bucket link: use data from bucket_info to rewrite bucket_endpoint. The bucket link command was doing a fetch of the entrypoint late in the link process. This makes it harder to do "bucket move" functionality, because then it would need to know the old bucket late in the process. The bucketinfo structure has all the data elements necessary to recreate the endpoint, so the changes here arrange to just use that data. In order to write the object it's also necessary to propagate xattrs. The only xattr that seems to be present on the endpoint is "ceph.objclass.version", so that's what this copies out. It appears that attribute may be set set separately by cls, so I'm not sure this is actually necessary. However, the old code would have written it, so this code preserves that behavior. Fixes: http://tracker.ceph.com/issues/35885 Signed-off-by: Marcus Watts --- src/rgw/rgw_bucket.cc | 45 ++++++++++++++++++++++++++++++++++--------- src/rgw/rgw_bucket.h | 10 +++++++++- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index f4c664c9a6a9c..de1175e71ad78 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -33,6 +33,10 @@ #include "rgw_common.h" #include "rgw_reshard.h" #include "rgw_lc.h" + +// stolen from src/cls/version/cls_version.cc +#define VERSION_ATTR "ceph.objclass.version" + #include "cls/user/cls_user_types.h" #define dout_context g_ceph_context @@ -189,7 +193,8 @@ int rgw_link_bucket(RGWRados* const store, const rgw_user& user_id, rgw_bucket& bucket, ceph::real_time creation_time, - bool update_entrypoint) + bool update_entrypoint, + rgw_ep_info *pinfo) { int ret; string& tenant_name = bucket.tenant; @@ -207,14 +212,22 @@ int rgw_link_bucket(RGWRados* const store, else new_bucket.creation_time = creation_time; - map attrs; - RGWSysObjectCtx obj_ctx = store->svc.sysobj->init_obj_ctx(); + map attrs, *pattrs; if (update_entrypoint) { - ret = store->get_bucket_entrypoint_info(obj_ctx, tenant_name, bucket_name, ep, &ot, NULL, &attrs); - if (ret < 0 && ret != -ENOENT) { - ldout(store->ctx(), 0) << "ERROR: store->get_bucket_entrypoint_info() returned: " - << cpp_strerror(-ret) << dendl; + if (pinfo) { + ep = pinfo->ep; + pattrs = &pinfo->attrs; + } else { + RGWSysObjectCtx obj_ctx = store->svc.sysobj->init_obj_ctx(); + + ret = store->get_bucket_entrypoint_info(obj_ctx, + tenant_name, bucket_name, ep, &ot, NULL, &attrs); + if (ret < 0 && ret != -ENOENT) { + ldout(store->ctx(), 0) << "ERROR: store->get_bucket_entrypoint_info() returned: " + << cpp_strerror(-ret) << dendl; + } + pattrs = &attrs; } } @@ -235,7 +248,7 @@ int rgw_link_bucket(RGWRados* const store, ep.linked = true; ep.owner = user_id; ep.bucket = bucket; - ret = store->put_bucket_entrypoint_info(tenant_name, bucket_name, ep, false, ot, real_time(), &attrs); + ret = store->put_bucket_entrypoint_info(tenant_name, bucket_name, ep, false, ot, real_time(), pattrs); if (ret < 0) goto done_err; @@ -921,8 +934,22 @@ int RGWBucket::link(RGWBucketAdminOpState& op_state, return r; } + RGWBucketEntryPoint ep; + ep.bucket = bucket_info.bucket; + ep.owner = user_info.user_id; + ep.creation_time = bucket_info.creation_time; + ep.linked = true; + map ep_attrs; + // XXX I am not convinced this is at all necessary; but previous + // versions would have found and copied VERSION_ATTR so I will + // do likewise for now... mdw 20180825 + auto version_iter = attrs.find(VERSION_ATTR); + if (version_iter != attrs.end()) + ep_attrs[VERSION_ATTR] = version_iter->second; + rgw_ep_info ep_data{ep, ep_attrs}; + r = rgw_link_bucket(store, user_info.user_id, bucket_info.bucket, - ceph::real_time()); + ceph::real_time(), true, &ep_data); if (r < 0) { set_err_msg(err_msg, "failed to relink bucket"); return r; diff --git a/src/rgw/rgw_bucket.h b/src/rgw/rgw_bucket.h index e9528b9c3e64a..166f2e4a0619e 100644 --- a/src/rgw/rgw_bucket.h +++ b/src/rgw/rgw_bucket.h @@ -200,11 +200,19 @@ extern int rgw_read_user_buckets(RGWRados *store, bool* is_truncated, uint64_t default_amount = 1000); +struct rgw_ep_info { + RGWBucketEntryPoint &ep; + map& attrs; + rgw_ep_info(RGWBucketEntryPoint &ep, map& attrs) + : ep(ep), attrs(attrs) { } +}; + extern int rgw_link_bucket(RGWRados* store, const rgw_user& user_id, rgw_bucket& bucket, ceph::real_time creation_time, - bool update_entrypoint = true); + bool update_entrypoint = true, + rgw_ep_info *pinfo = nullptr); extern int rgw_unlink_bucket(RGWRados *store, const rgw_user& user_id, const string& tenant_name, const string& bucket_name, bool update_entrypoint = true); -- 2.39.5