From 949480c2e9760855ed6a0501d364d5e766c8207d Mon Sep 17 00:00:00 2001 From: "Javier M. Mellid" Date: Tue, 26 Jul 2016 14:53:44 +0200 Subject: [PATCH 01/10] rgw: multipart uploads copy part support Add multipart uploads copy part feature. Fixes: http://tracker.ceph.com/issues/12790 Signed-off-by: Javier M. Mellid --- src/rgw/rgw_common.h | 2 + src/rgw/rgw_op.cc | 92 ++++++++++++++++++++++++++++++++- src/rgw/rgw_op.h | 16 ++++++ src/rgw/rgw_rest_s3.cc | 113 ++++++++++++++++++++++++++++++++++------- 4 files changed, 204 insertions(+), 19 deletions(-) diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 42a1ec8219872..fee2f0cd2369e 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -1357,6 +1357,8 @@ struct req_state { string req_id; string trans_id; + const char *copy_source; + req_state(CephContext* _cct, RGWEnv* e, RGWUserInfo* u); ~req_state(); }; diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 2c820e4030b45..a844fc9bbbc9c 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2484,6 +2484,27 @@ void RGWDeleteBucket::execute() int RGWPutObj::verify_permission() { + if (copy_source) { + + RGWAccessControlPolicy cs_policy(s->cct); + map cs_attrs; + rgw_bucket cs_bucket(copy_source_bucket_info.bucket); + rgw_obj_key cs_object(copy_source_object_name); + rgw_obj cs_obj(cs_bucket, cs_object); + + /* check source object permissions */ + if (read_policy(store, s, copy_source_bucket_info, cs_attrs, &cs_policy, cs_bucket, cs_object) < 0) { + return -EACCES; + } + + /* admin request overrides permission checks */ + if (!s->auth_identity->is_admin_of(cs_policy.get_owner().get_id()) && + !cs_policy.verify_permission(*s->auth_identity, s->perm_mask, RGW_PERM_READ)) { + return -EACCES; + } + + } + if (!verify_bucket_permission(s, RGW_PERM_WRITE)) { return -EACCES; } @@ -2662,6 +2683,58 @@ void RGWPutObj::pre_exec() rgw_bucket_object_pre_exec(s); } +class RGWPutObj_CB : public RGWGetDataCB +{ + RGWPutObj *op; +public: + RGWPutObj_CB(RGWPutObj *_op) : op(_op) {} + virtual ~RGWPutObj_CB() {} + + int handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) { + return op->get_data_cb(bl, bl_ofs, bl_len); + } +}; + +int RGWPutObj::get_data_cb(bufferlist& bl, off_t bl_ofs, off_t bl_len) +{ + bufferlist bl_tmp; + bl.copy(bl_ofs, bl_len, bl_tmp); + + bl_aux.append(bl_tmp); + + return bl_len; +} + +int RGWPutObj::get_data(const off_t fst, const off_t lst, bufferlist& bl) +{ + RGWPutObj_CB cb(this); + int ret = 0; + + int64_t new_ofs, new_end; + + new_ofs = fst; + new_end = lst; + + rgw_obj_key obj_key(copy_source_object_name); + rgw_obj obj(copy_source_bucket_info.bucket, obj_key); + + RGWRados::Object op_target(store, copy_source_bucket_info, *static_cast(s->obj_ctx), obj); + RGWRados::Object::Read read_op(&op_target); + + ret = read_op.prepare(&new_ofs, &new_end); + if (ret < 0) + return ret; + + ret = read_op.iterate(new_ofs, new_end, &cb); + if (ret < 0) { + return ret; + } + + bl_aux.copy(0, bl_aux.length(), bl); + + return ret; +} + void RGWPutObj::execute() { RGWPutObjProcessor *processor = NULL; @@ -2675,6 +2748,9 @@ void RGWPutObj::execute() map::iterator iter; bool multipart; + off_t fst; + off_t lst; + bool need_calc_md5 = (dlo_manifest == NULL) && (slo_info == NULL); perfcounter->inc(l_rgw_put); @@ -2753,9 +2829,23 @@ void RGWPutObj::execute() goto done; } + fst = copy_source_range_fst; + lst = copy_source_range_lst; + do { bufferlist data_in; - len = get_data(data_in); + if (fst > lst) + break; + if (!copy_source) { + len = get_data(data_in); + } else { + op_ret = get_data(fst, lst, data_in); + if (op_ret < 0) + goto done; + len = data_in.length(); + s->content_length += len; + fst += len; + } if (len < 0) { op_ret = len; goto done; diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 87d19334efb60..6a970045a3449 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -653,6 +653,14 @@ class RGWPutObj : public RGWOp { const char *supplied_etag; const char *if_match; const char *if_nomatch; + const char *copy_source; + const char *copy_source_range; + RGWBucketInfo copy_source_bucket_info; + string copy_source_tenant_name; + string copy_source_bucket_name; + string copy_source_object_name; + off_t copy_source_range_fst; + off_t copy_source_range_lst; string etag; bool chunked_upload; RGWAccessControlPolicy policy; @@ -662,6 +670,7 @@ class RGWPutObj : public RGWOp { ceph::real_time mtime; uint64_t olh_epoch; string version_id; + bufferlist bl_aux; ceph::real_time delete_at; @@ -671,6 +680,10 @@ class RGWPutObj : public RGWOp { supplied_etag(NULL), if_match(NULL), if_nomatch(NULL), + copy_source(NULL), + copy_source_range(NULL), + copy_source_range_fst(0), + copy_source_range_lst(0), chunked_upload(0), dlo_manifest(NULL), slo_info(NULL), @@ -696,6 +709,9 @@ class RGWPutObj : public RGWOp { void pre_exec(); void execute(); + int get_data_cb(bufferlist& bl, off_t bl_ofs, off_t bl_len); + int get_data(const off_t fst, const off_t lst, bufferlist& bl); + virtual int get_params() = 0; virtual int get_data(bufferlist& bl) = 0; virtual void send_response() = 0; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 9b0bb50177c09..07073dbfbed2d 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1040,18 +1040,78 @@ void RGWDeleteBucket_ObjStore_S3::send_response() int RGWPutObj_ObjStore_S3::get_params() { + RGWObjectCtx& obj_ctx = *static_cast(s->obj_ctx); + map src_attrs; + size_t pos; + int ret; + RGWAccessControlPolicy_S3 s3policy(s->cct); if (!s->length) return -ERR_LENGTH_REQUIRED; - int r = create_s3_policy(s, store, s3policy, s->owner); - if (r < 0) - return r; + ret = create_s3_policy(s, store, s3policy, s->owner); + if (ret < 0) + return ret; policy = s3policy; if_match = s->info.env->get("HTTP_IF_MATCH"); if_nomatch = s->info.env->get("HTTP_IF_NONE_MATCH"); + copy_source = s->info.env->get("HTTP_X_AMZ_COPY_SOURCE"); + copy_source_range = s->info.env->get("HTTP_X_AMZ_COPY_SOURCE_RANGE"); + + /* handle x-amz-copy-source */ + + if (copy_source) { + copy_source_bucket_name = copy_source; + pos = copy_source_bucket_name.find("/"); + if (pos == std::string::npos) { + ret = -EINVAL; + ldout(s->cct, 0) << "x-amz-copy-source bad format" << dendl; + return ret; + } + copy_source_object_name = copy_source_bucket_name.substr(pos + 1, copy_source_bucket_name.size()); + copy_source_bucket_name = copy_source_bucket_name.substr(0, pos); + pos = copy_source_bucket_name.find(":"); + if (pos == std::string::npos) { + copy_source_tenant_name = s->src_tenant_name; + } else { + copy_source_tenant_name = copy_source_bucket_name.substr(0, pos); + copy_source_bucket_name = copy_source_bucket_name.substr(pos + 1, copy_source_bucket_name.size()); + } + ret = store->get_bucket_info(obj_ctx, + copy_source_tenant_name, + copy_source_bucket_name, + copy_source_bucket_info, + NULL, &src_attrs); + if (ret < 0) { + return ret; + } + + /* handle x-amz-copy-source-range */ + + if (copy_source_range) { + string range = copy_source_range; + pos = range.find("="); + if (pos == std::string::npos) { + ret = -EINVAL; + ldout(s->cct, 0) << "x-amz-copy-source-range bad format" << dendl; + return ret; + } + range = range.substr(pos + 1, range.size()); + pos = range.find("-"); + if (pos == std::string::npos) { + ret = -EINVAL; + ldout(s->cct, 0) << "x-amz-copy-source-range bad format" << dendl; + return ret; + } + string first = range.substr(0, pos); + string last = range.substr(pos + 1, range.size()); + copy_source_range_fst = strtoull(first.c_str(), NULL, 10); + copy_source_range_lst = strtoull(last.c_str(), NULL, 10); + } + + } /* copy_source */ return RGWPutObj_ObjStore::get_params(); } @@ -1237,8 +1297,28 @@ void RGWPutObj_ObjStore_S3::send_response() s->cct->_conf->rgw_s3_success_create_obj_status); set_req_state_err(s, op_ret); } - dump_etag(s, etag.c_str()); - dump_content_length(s, 0); + if (!s->info.env->get("HTTP_X_AMZ_COPY_SOURCE")) { + dump_etag(s, etag.c_str()); + dump_content_length(s, 0); + } else { + dump_errno(s); + end_header(s, this, "application/xml"); + dump_start(s); + struct tm tmp; + utime_t ut(mtime); + time_t secs = (time_t)ut.sec(); + gmtime_r(&secs, &tmp); + char buf[TIME_BUF_SIZE]; + s->formatter->open_object_section_in_ns("CopyPartResult", + "http://s3.amazonaws.com/doc/2006-03-01/"); + if (strftime(buf, sizeof(buf), "%Y-%m-%dT%T.000Z", &tmp) > 0) { + s->formatter->dump_string("LastModified", buf); + } + s->formatter->dump_string("ETag", etag); + s->formatter->close_section(); + rgw_flush_formatter_and_reset(s, s->formatter); + return; + } } if (s->system_request && !real_clock::is_zero(mtime)) { dump_epoch_header(s, "Rgwx-Mtime", mtime); @@ -2084,10 +2164,6 @@ int RGWCopyObj_ObjStore_S3::init_dest_policy() int RGWCopyObj_ObjStore_S3::get_params() { - if (s->info.env->get("HTTP_X_AMZ_COPY_SOURCE_RANGE")) { - return -ERR_NOT_IMPLEMENTED; - } - if_mod = s->info.env->get("HTTP_X_AMZ_COPY_IF_MODIFIED_SINCE"); if_unmod = s->info.env->get("HTTP_X_AMZ_COPY_IF_UNMODIFIED_SINCE"); if_match = s->info.env->get("HTTP_X_AMZ_COPY_IF_MATCH"); @@ -3113,15 +3189,16 @@ int RGWHandler_REST_S3::init(RGWRados *store, struct req_state *s, s->has_acl_header = s->info.env->exists_prefix("HTTP_X_AMZ_GRANT"); - const char *copy_source = s->info.env->get("HTTP_X_AMZ_COPY_SOURCE"); - if (copy_source) { - ret = RGWCopyObj::parse_copy_location(copy_source, - s->init_state.src_bucket, - s->src_object); - if (!ret) { - ldout(s->cct, 0) << "failed to parse copy location" << dendl; - return -EINVAL; // XXX why not -ERR_INVALID_BUCKET_NAME or -ERR_BAD_URL? - } + if (!s->info.env->get("HTTP_X_AMZ_COPY_SOURCE_RANGE") && + s->info.env->get("HTTP_X_AMZ_COPY_SOURCE")) { + + ret = RGWCopyObj::parse_copy_location(s->copy_source, + s->init_state.src_bucket, + s->src_object); + if (!ret) { + ldout(s->cct, 0) << "failed to parse copy location" << dendl; + return -EINVAL; // XXX why not -ERR_INVALID_BUCKET_NAME or -ERR_BAD_URL? + } } return RGWHandler_REST::init(store, s, cio); From 8a7ebeee2ff3f10ceb23b7fa43e43c3c450efe22 Mon Sep 17 00:00:00 2001 From: "Javier M. Mellid" Date: Tue, 26 Jul 2016 14:56:50 +0200 Subject: [PATCH 02/10] rgw: doc: add multipart uploads copy part feature as supported Signed-off-by: Javier M. Mellid --- doc/radosgw/s3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/radosgw/s3.rst b/doc/radosgw/s3.rst index 9ec1ff9563738..504abbc661a5d 100644 --- a/doc/radosgw/s3.rst +++ b/doc/radosgw/s3.rst @@ -70,7 +70,7 @@ The following table describes the support status for current Amazon S3 functiona +---------------------------------+-----------------+----------------------------------------+ | **Copy Object** | Supported | | +---------------------------------+-----------------+----------------------------------------+ -| **Multipart Uploads** | Supported | (missing Copy Part) | +| **Multipart Uploads** | Supported | | +---------------------------------+-----------------+----------------------------------------+ Unsupported Header Fields From 4049e47a0cfc1eef6efd502590b68ba7234589d3 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 29 Sep 2016 14:07:14 -0700 Subject: [PATCH 03/10] rgw: multipart copy part, chunked read Don't read the entire range from source object, read it in parts. Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_op.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index a844fc9bbbc9c..37f419197b04c 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2730,7 +2730,7 @@ int RGWPutObj::get_data(const off_t fst, const off_t lst, bufferlist& bl) return ret; } - bl_aux.copy(0, bl_aux.length(), bl); + bl.claim_append(bl_aux); return ret; } @@ -2839,7 +2839,8 @@ void RGWPutObj::execute() if (!copy_source) { len = get_data(data_in); } else { - op_ret = get_data(fst, lst, data_in); + uint64_t cur_lst = min(fst + s->cct->_conf->rgw_max_chunk_size - 1, lst); + op_ret = get_data(fst, cur_lst, data_in); if (op_ret < 0) goto done; len = data_in.length(); From 2bcb3d286b230ef917d5ba96c8276a942f544689 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 29 Sep 2016 14:11:43 -0700 Subject: [PATCH 04/10] rgw: multipart copy, check for empty bucket, improve logging also reduce log level for non critical user errors. Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_rest_s3.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 07073dbfbed2d..c333c108af04d 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1067,7 +1067,7 @@ int RGWPutObj_ObjStore_S3::get_params() pos = copy_source_bucket_name.find("/"); if (pos == std::string::npos) { ret = -EINVAL; - ldout(s->cct, 0) << "x-amz-copy-source bad format" << dendl; + ldout(s->cct, 5) << "x-amz-copy-source bad format" << dendl; return ret; } copy_source_object_name = copy_source_bucket_name.substr(pos + 1, copy_source_bucket_name.size()); @@ -1078,6 +1078,11 @@ int RGWPutObj_ObjStore_S3::get_params() } else { copy_source_tenant_name = copy_source_bucket_name.substr(0, pos); copy_source_bucket_name = copy_source_bucket_name.substr(pos + 1, copy_source_bucket_name.size()); + if (copy_source_bucket_name.empty()) { + ret = -EINVAL; + ldout(s->cct, 5) << "source bucket name is empty" << dendl; + return ret; + } } ret = store->get_bucket_info(obj_ctx, copy_source_tenant_name, @@ -1085,6 +1090,7 @@ int RGWPutObj_ObjStore_S3::get_params() copy_source_bucket_info, NULL, &src_attrs); if (ret < 0) { + ldout(s->cct, 5) << __func__ << "(): get_bucket_info() returned ret=" << ret << dendl; return ret; } @@ -1095,14 +1101,14 @@ int RGWPutObj_ObjStore_S3::get_params() pos = range.find("="); if (pos == std::string::npos) { ret = -EINVAL; - ldout(s->cct, 0) << "x-amz-copy-source-range bad format" << dendl; + ldout(s->cct, 5) << "x-amz-copy-source-range bad format" << dendl; return ret; } range = range.substr(pos + 1, range.size()); pos = range.find("-"); if (pos == std::string::npos) { ret = -EINVAL; - ldout(s->cct, 0) << "x-amz-copy-source-range bad format" << dendl; + ldout(s->cct, 5) << "x-amz-copy-source-range bad format" << dendl; return ret; } string first = range.substr(0, pos); From 6e9b824d5d4017239d58b4752ebc43bfad8f698d Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 29 Sep 2016 14:24:13 -0700 Subject: [PATCH 05/10] rgw: multipart copy part minor parsing cleanup no need for range.size() Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_rest_s3.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index c333c108af04d..0435080d7928f 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1104,7 +1104,7 @@ int RGWPutObj_ObjStore_S3::get_params() ldout(s->cct, 5) << "x-amz-copy-source-range bad format" << dendl; return ret; } - range = range.substr(pos + 1, range.size()); + range = range.substr(pos + 1); pos = range.find("-"); if (pos == std::string::npos) { ret = -EINVAL; @@ -1112,7 +1112,7 @@ int RGWPutObj_ObjStore_S3::get_params() return ret; } string first = range.substr(0, pos); - string last = range.substr(pos + 1, range.size()); + string last = range.substr(pos + 1); copy_source_range_fst = strtoull(first.c_str(), NULL, 10); copy_source_range_lst = strtoull(last.c_str(), NULL, 10); } From 53521efffb1cb92e5f5ce992d4127bf9498d7c33 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 29 Sep 2016 17:43:35 -0700 Subject: [PATCH 06/10] rgw: multipart copy-part handle versionId Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_op.h | 1 + src/rgw/rgw_rest_s3.cc | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index 6a970045a3449..4d955cd4cbfd9 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -659,6 +659,7 @@ class RGWPutObj : public RGWOp { string copy_source_tenant_name; string copy_source_bucket_name; string copy_source_object_name; + string copy_source_version_id; off_t copy_source_range_fst; off_t copy_source_range_lst; string etag; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 0435080d7928f..74ca71b21dac6 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1072,6 +1072,14 @@ int RGWPutObj_ObjStore_S3::get_params() } copy_source_object_name = copy_source_bucket_name.substr(pos + 1, copy_source_bucket_name.size()); copy_source_bucket_name = copy_source_bucket_name.substr(0, pos); +#define VERSION_ID_STR "?versionId=" + pos = copy_source_object_name.find(VERSION_ID_STR); + if (pos == std::string::npos) { + url_decode(copy_source_object_name, copy_source_object_name); + } else { + copy_source_version_id = copy_source_object_name.substr(pos + sizeof(VERSION_ID_STR) - 1); + url_decode(copy_source_object_name.substr(0, pos), copy_source_object_name); + } pos = copy_source_bucket_name.find(":"); if (pos == std::string::npos) { copy_source_tenant_name = s->src_tenant_name; From 29fece3545cc1df404a25eec46706b16f893a5df Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 29 Sep 2016 17:43:00 -0700 Subject: [PATCH 07/10] rgw: rgw_obj_key use adjustment in multipart copy part This fixes a case where objects start with double underscore. Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_op.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 37f419197b04c..16c6280a652e7 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2489,8 +2489,7 @@ int RGWPutObj::verify_permission() RGWAccessControlPolicy cs_policy(s->cct); map cs_attrs; rgw_bucket cs_bucket(copy_source_bucket_info.bucket); - rgw_obj_key cs_object(copy_source_object_name); - rgw_obj cs_obj(cs_bucket, cs_object); + rgw_obj_key cs_object(copy_source_object_name, copy_source_version_id); /* check source object permissions */ if (read_policy(store, s, copy_source_bucket_info, cs_attrs, &cs_policy, cs_bucket, cs_object) < 0) { @@ -2715,8 +2714,9 @@ int RGWPutObj::get_data(const off_t fst, const off_t lst, bufferlist& bl) new_ofs = fst; new_end = lst; - rgw_obj_key obj_key(copy_source_object_name); - rgw_obj obj(copy_source_bucket_info.bucket, obj_key); + rgw_obj_key obj_key(copy_source_object_name, copy_source_version_id); + rgw_obj obj(copy_source_bucket_info.bucket, obj_key.name); + obj.set_instance(obj_key.instance); RGWRados::Object op_target(store, copy_source_bucket_info, *static_cast(s->obj_ctx), obj); RGWRados::Object::Read read_op(&op_target); From 4919dc9987c6376d3d4e143702c26417449524c5 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 29 Sep 2016 17:44:08 -0700 Subject: [PATCH 08/10] rgw: minor optimization Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_rest_s3.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 74ca71b21dac6..e360bb9a8724c 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -1311,7 +1311,7 @@ void RGWPutObj_ObjStore_S3::send_response() s->cct->_conf->rgw_s3_success_create_obj_status); set_req_state_err(s, op_ret); } - if (!s->info.env->get("HTTP_X_AMZ_COPY_SOURCE")) { + if (!copy_source) { dump_etag(s, etag.c_str()); dump_content_length(s, 0); } else { From 66fbe9384703c004c01783eb664f55895d310439 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 29 Sep 2016 22:20:10 -0700 Subject: [PATCH 09/10] rgw: multipart part copy, fix regression Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_common.h | 2 -- src/rgw/rgw_rest_s3.cc | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index fee2f0cd2369e..42a1ec8219872 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -1357,8 +1357,6 @@ struct req_state { string req_id; string trans_id; - const char *copy_source; - req_state(CephContext* _cct, RGWEnv* e, RGWUserInfo* u); ~req_state(); }; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index e360bb9a8724c..1ab2eb02b8b8c 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -3203,16 +3203,16 @@ int RGWHandler_REST_S3::init(RGWRados *store, struct req_state *s, s->has_acl_header = s->info.env->exists_prefix("HTTP_X_AMZ_GRANT"); - if (!s->info.env->get("HTTP_X_AMZ_COPY_SOURCE_RANGE") && - s->info.env->get("HTTP_X_AMZ_COPY_SOURCE")) { - - ret = RGWCopyObj::parse_copy_location(s->copy_source, - s->init_state.src_bucket, - s->src_object); - if (!ret) { - ldout(s->cct, 0) << "failed to parse copy location" << dendl; - return -EINVAL; // XXX why not -ERR_INVALID_BUCKET_NAME or -ERR_BAD_URL? - } + const char *copy_source = s->info.env->get("HTTP_X_AMZ_COPY_SOURCE"); + + if (copy_source && !s->info.env->get("HTTP_X_AMZ_COPY_SOURCE_RANGE")) { + ret = RGWCopyObj::parse_copy_location(copy_source, + s->init_state.src_bucket, + s->src_object); + if (!ret) { + ldout(s->cct, 0) << "failed to parse copy location" << dendl; + return -EINVAL; // XXX why not -ERR_INVALID_BUCKET_NAME or -ERR_BAD_URL? + } } return RGWHandler_REST::init(store, s, cio); From 3e34380553ee728d3d2e32a3420f417bb9c6ac25 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Fri, 30 Sep 2016 14:40:33 -0700 Subject: [PATCH 10/10] rgw: set multipart copy source object as atomic, prefetch Object's head should only be read once. Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_op.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 16c6280a652e7..f7774b3d9e282 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -2491,6 +2491,11 @@ int RGWPutObj::verify_permission() rgw_bucket cs_bucket(copy_source_bucket_info.bucket); rgw_obj_key cs_object(copy_source_object_name, copy_source_version_id); + rgw_obj obj(cs_bucket, cs_object.name); + obj.set_instance(cs_object.instance); + store->set_atomic(s->obj_ctx, obj); + store->set_prefetch_data(s->obj_ctx, obj); + /* check source object permissions */ if (read_policy(store, s, copy_source_bucket_info, cs_attrs, &cs_policy, cs_bucket, cs_object) < 0) { return -EACCES;