From 54ea09c3628344fcca6d0e18972ecc5393e343c7 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Tue, 1 Mar 2016 16:46:47 -0800 Subject: [PATCH] rgw: copy swift versioned object to destination if overwritten Only allow if target bucket owner is the source bucket owner. Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_rados.cc | 88 +++++++++++++++++++++++++++++++++++++++++++- src/rgw/rgw_rados.h | 2 + 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 0aaf4426bb5e5..6c6b5ca8cac95 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -5651,6 +5651,76 @@ int RGWRados::BucketShard::init(rgw_bucket& _bucket, rgw_obj& obj) } +int RGWRados::swift_versioning_copy(RGWBucketInfo& bucket_info, RGWRados::Object *source, RGWObjState *state, + rgw_user& user) +{ + if (!bucket_info.has_swift_versioning() || bucket_info.swift_ver_location.empty()) { + return 0; + } + + if (!state->exists) { + return 0; + } + + string client_id; + string op_id; + + rgw_obj& obj = source->get_obj(); + const string& src_name = obj.get_object(); + char buf[src_name.size() + 32]; + snprintf(buf, sizeof(buf), "%03d%s%lld.%06d", (int)src_name.size(), src_name.c_str(), (long long)state->mtime, 0); + + RGWBucketInfo dest_bucket_info; + + int r = get_bucket_info(source->get_ctx(), bucket_info.bucket.tenant, bucket_info.swift_ver_location, dest_bucket_info, NULL, NULL); + if (r < 0) { + ldout(cct, 10) << "failed to read dest bucket info: r=" << r << dendl; + return r; + } + + if (dest_bucket_info.owner != bucket_info.owner) { + return -EPERM; + } + + rgw_obj dest_obj(dest_bucket_info.bucket, buf); + + string no_zone; + + r = copy_obj(source->get_ctx(), + user, + client_id, + op_id, + NULL, /* req_info *info */ + no_zone, + dest_obj, + obj, + dest_bucket_info, + bucket_info, + NULL, /* time_t *src_mtime */ + NULL, /* time_t *mtime */ + NULL, /* const time_t *mod_ptr */ + NULL, /* const time_t *unmod_ptr */ + NULL, /* const char *if_match */ + NULL, /* const char *if_nomatch */ + RGWRados::ATTRSMOD_NONE, + true, /* bool copy_if_newer */ + state->attrset, + RGW_OBJ_CATEGORY_MAIN, + 0, /* uint64_t olh_epoch */ + 0, /* time_t delete_at */ + NULL, /* string *version_id */ + NULL, /* string *ptag */ + NULL, /* string *petag */ + NULL, /* struct rgw_err *err */ + NULL, /* void (*progress_cb)(off_t, void *) */ + NULL); /* void *progress_data */ + if (r == -ECANCELED || r == -ENOENT) { /* has already been overwritten, meaning another rgw process already copied it out */ + return 0; + } + + return r; +} + /** * Write/overwrite an object to the bucket storage. * bucket: the bucket to store the object in @@ -5779,13 +5849,20 @@ int RGWRados::Object::Write::write_meta(uint64_t size, bool versioned_op = (target->versioning_enabled() || is_olh || versioned_target); - RGWRados::Bucket bop(store, target->get_bucket_info()); + RGWBucketInfo& bucket_info = target->get_bucket_info(); + + RGWRados::Bucket bop(store, bucket_info); RGWRados::Bucket::UpdateIndex index_op(&bop, obj, state); if (versioned_op) { index_op.set_bilog_flags(RGW_BILOG_FLAG_VERSIONED_OP); } + r = store->swift_versioning_copy(bucket_info, target, state, meta.owner); + if (r < 0) { + goto done_cancel; + } + r = index_op.prepare(CLS_RGW_OP_ADD); if (r < 0) return r; @@ -7362,11 +7439,18 @@ int RGWRados::Object::Delete::delete_obj() bool ret_not_existed = (!state->exists); - RGWRados::Bucket bop(store, target->get_bucket_info()); + RGWBucketInfo& bucket_info = target->get_bucket_info(); + + RGWRados::Bucket bop(store, bucket_info); RGWRados::Bucket::UpdateIndex index_op(&bop, obj, state); index_op.set_bilog_flags(params.bilog_flags); + r = store->swift_versioning_copy(bucket_info, target, state, params.bucket_owner); + if (r < 0) { + return r; + } + r = index_op.prepare(CLS_RGW_OP_DEL); if (r < 0) return r; diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index bf36a1e9ee54d..feea80f06744a 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -2448,6 +2448,8 @@ public: struct rgw_err *err, void (*progress_cb)(off_t, void *), void *progress_data); + int swift_versioning_copy(RGWBucketInfo& bucket_info, RGWRados::Object *source, RGWObjState *state, + rgw_user& user); int copy_obj_to_remote_dest(RGWObjState *astate, map& src_attrs, RGWRados::Object::Read& read_op, -- 2.39.5