From: Prasad Krishnan Date: Fri, 6 Mar 2020 05:08:05 +0000 (+0000) Subject: [RGW][Multisite] Add multisite verifier support for MPU objects X-Git-Tag: v15.2.9~47^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=37a4ab2609c031bb981c19efe73d81266bd985fa;p=ceph.git [RGW][Multisite] Add multisite verifier support for MPU objects The Etag for MPU objects is calculated using a method different from how it is done for atomic objects. This patch makes use of the RGWObjManifest to determine the parts in the source cluster and re-computes the ETag in a similar fashion at the destination cluster during multisite sync for verification. Signed-off-by: Prasad Krishnan (cherry picked from commit 6f085bb9cb6cffddcf2eed18a7295a3dd59f755f) --- diff --git a/src/rgw/rgw_obj_manifest.h b/src/rgw/rgw_obj_manifest.h index 4b3e66e9fd6..227eaff50f2 100644 --- a/src/rgw/rgw_obj_manifest.h +++ b/src/rgw/rgw_obj_manifest.h @@ -466,6 +466,10 @@ public: return location; } + int get_cur_part_id() const { + return cur_part_id; + } + /* start of current stripe */ uint64_t get_stripe_ofs() { if (manifest->explicit_objs) { diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index 97849712191..b46c2e24eb2 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -3261,7 +3261,7 @@ class RGWRadosPutObj : public RGWHTTPStreamRWRequest::ReceiveCB rgw::putobj::ObjectProcessor *processor; void (*progress_cb)(off_t, void *); void *progress_data; - bufferlist extra_data_bl, full_obj; + bufferlist extra_data_bl, full_obj, manifest_bl; uint64_t extra_data_left{0}; bool need_to_process_attrs{true}; uint64_t data_len{0}; @@ -3298,7 +3298,8 @@ public: JSONDecoder::decode_json("attrs", src_attrs, &jp); src_attrs.erase(RGW_ATTR_COMPRESSION); - src_attrs.erase(RGW_ATTR_MANIFEST); // not interested in original object layout + /* We need the manifest to recompute the ETag for verification */ + manifest_bl = src_attrs[RGW_ATTR_MANIFEST]; // filter out olh attributes auto iter = src_attrs.lower_bound(RGW_ATTR_OLH_PREFIX); @@ -3396,15 +3397,84 @@ public: } string get_calculated_etag() { - MD5 hash; - unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE]; + MD5 hash, mpu_etag_hash; + unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE], mpu_m[CEPH_CRYPTO_MD5_DIGESTSIZE]; char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1]; + char calc_md5_part[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1]; + char final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16]; + RGWObjManifest manifest; + std::string calculated_etag_part; + int prev_part_id = 1, cur_part_id = 1; + + auto miter = manifest_bl.cbegin(); + try { + decode(manifest, miter); + } catch (buffer::error& err) { + ldout(cct, 0) << "ERROR: couldn't decode manifest" << dendl; + return std::string(); + } + RGWObjManifest::obj_iterator mi; + + RGWObjManifestRule rule; + bool found = manifest.get_rule(0, &rule); + if (!found) { + lderr(cct) << "ERROR: manifest->get_rule() could not find rule" << dendl; + return std::string(); + } + + /* + * Check if the object was created using multipart upload. This check is + * required as MPU objects' ETag != MD5sum. + */ + if (rule.part_size == 0) { + hash.Update((const unsigned char *)full_obj.c_str(), data_len); + hash.Final(m); + buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5); + calculated_etag = calc_md5; + ldout(cct, 20) << "Single part object: " << manifest.get_obj().get_oid() << + " size:" << manifest.get_obj_size() << " etag:" << + calculated_etag << dendl; + return calculated_etag; + } + + for (mi = manifest.obj_begin(); mi != manifest.obj_end(); ++mi) { + bufferlist obj_stripe; + + cur_part_id = mi.get_cur_part_id(); + if (cur_part_id != prev_part_id) { + hash.Final(m); + mpu_etag_hash.Update((const unsigned char *)m, sizeof(m)); + hash.Restart(); + buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5_part); + calculated_etag_part = calc_md5_part; + ldout(cct, 20) << "Part " << prev_part_id << " etag: " << + calculated_etag_part << dendl; + prev_part_id = cur_part_id; + } + full_obj.splice(0, mi.get_stripe_size(), &obj_stripe); + hash.Update((const unsigned char *)obj_stripe.c_str(), mi.get_stripe_size()); + } - hash.Update((const unsigned char *)full_obj.c_str(), data_len); hash.Final(m); - buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5); - calculated_etag = calc_md5; + mpu_etag_hash.Update((const unsigned char *)m, sizeof(m)); + + buf_to_hex(m, CEPH_CRYPTO_MD5_DIGESTSIZE, calc_md5_part); + calculated_etag_part = calc_md5_part; + ldout(cct, 20) << "Part " << prev_part_id << " etag: " << calculated_etag_part << dendl; + + /* Refer RGWCompleteMultipart::execute() for ETag calculation for MPU object */ + mpu_etag_hash.Final(mpu_m); + buf_to_hex(mpu_m, CEPH_CRYPTO_MD5_DIGESTSIZE, final_etag_str); + snprintf(&final_etag_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2], + sizeof(final_etag_str) - CEPH_CRYPTO_MD5_DIGESTSIZE * 2, + "-%lld", (long long)(mi.get_cur_part_id() - 1)); + calculated_etag = final_etag_str; + + ldout(cct, 20) << "MPU calculated ETag:"<< calculated_etag << " Object:" << + manifest.get_obj().get_oid() << + " size:" << manifest.get_obj_size() << dendl; return calculated_etag; + } };