From 123321f4790423e276bd50bb4723ee975e669c62 Mon Sep 17 00:00:00 2001 From: Gui Hecheng Date: Fri, 2 Jun 2017 10:00:48 +0800 Subject: [PATCH] rgw_file: fix misuse of make_key_name before make_fhk The make_fhk calls make_key_name internally. Also, because this makes the stored fhk and the new constructed fhk mismatch, we make the assertion check conditional based on versioned fhk and bump up the version. Also, we shall safely update the old_key using update_fhk(). Signed-off-by: Gui Hecheng --- src/rgw/rgw_file.cc | 61 +++++++++++++++++++++++++++++++++++++++++---- src/rgw/rgw_file.h | 32 ++++++++++++++++-------- 2 files changed, 77 insertions(+), 16 deletions(-) diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc index e5032d0a5104a..ca8a5c4b4b879 100644 --- a/src/rgw/rgw_file.cc +++ b/src/rgw/rgw_file.cc @@ -92,7 +92,10 @@ namespace rgw { auto ux_key = req.get_attr(RGW_ATTR_UNIX_KEY1); auto ux_attrs = req.get_attr(RGW_ATTR_UNIX1); if (ux_key && ux_attrs) { - rgw_fh->decode_attrs(ux_key, ux_attrs); + bool old_key = rgw_fh->decode_attrs(ux_key, ux_attrs); + if (old_key) { + update_fhk(rgw_fh); + } } if (! (flags & RGWFileHandle::FLAG_LOCKED)) { rgw_fh->mtx.unlock(); @@ -144,7 +147,10 @@ namespace rgw { auto ux_key = req.get_attr(RGW_ATTR_UNIX_KEY1); auto ux_attrs = req.get_attr(RGW_ATTR_UNIX1); if (ux_key && ux_attrs) { - rgw_fh->decode_attrs(ux_key, ux_attrs); + bool old_key = rgw_fh->decode_attrs(ux_key, ux_attrs); + if (old_key) { + update_fhk(rgw_fh); + } } } goto done; @@ -175,7 +181,10 @@ namespace rgw { auto ux_key = req.get_attr(RGW_ATTR_UNIX_KEY1); auto ux_attrs = req.get_attr(RGW_ATTR_UNIX1); if (ux_key && ux_attrs) { - rgw_fh->decode_attrs(ux_key, ux_attrs); + bool old_key = rgw_fh->decode_attrs(ux_key, ux_attrs); + if (old_key) { + update_fhk(rgw_fh); + } } } goto done; @@ -734,6 +743,41 @@ namespace rgw { return 0; } /* RGWLibFS::setattr */ + /* called under rgw_fh->mtx held */ + void RGWLibFS::update_fhk(RGWFileHandle *rgw_fh) + { + int rc, rc2; + string obj_name{rgw_fh->relative_object_name()}; + buffer::list ux_key, ux_attrs; + + if (rgw_fh->is_dir() && + (likely(! rgw_fh->is_bucket()))) { + obj_name += "/"; + } + + lsubdout(get_context(), rgw, 17) + << __func__ + << " update old versioned fhk : " << obj_name + << dendl; + + RGWSetAttrsRequest req(cct, get_user(), rgw_fh->bucket_name(), obj_name); + + rgw_fh->encode_attrs(ux_key, ux_attrs); + + /* update ux_key only */ + req.emplace_attr(RGW_ATTR_UNIX_KEY1, std::move(ux_key)); + + rc = rgwlib.get_fe()->execute_req(&req); + rc2 = req.get_ret(); + + if ((rc != 0) || (rc2 != 0)) { + lsubdout(get_context(), rgw, 17) + << __func__ + << " update fhk failed : " << obj_name + << dendl; + } + } /* RGWLibFS::update_fhk */ + void RGWLibFS::close() { state.flags |= FLAG_CLOSED; @@ -933,16 +977,23 @@ namespace rgw { rgw::encode(*this, ux_attrs1); } /* RGWFileHandle::encode_attrs */ - void RGWFileHandle::decode_attrs(const ceph::buffer::list* ux_key1, + bool RGWFileHandle::decode_attrs(const ceph::buffer::list* ux_key1, const ceph::buffer::list* ux_attrs1) { + bool old_key = false; fh_key fhk; auto bl_iter_key1 = const_cast(ux_key1)->begin(); rgw::decode(fhk, bl_iter_key1); - assert(this->fh.fh_hk == fhk.fh_hk); + if (fhk.version >= 2) { + assert(this->fh.fh_hk == fhk.fh_hk); + } else { + old_key = true; + } auto bl_iter_unix1 = const_cast(ux_attrs1)->begin(); rgw::decode(*this, bl_iter_unix1); + + return old_key; } /* RGWFileHandle::decode_attrs */ bool RGWFileHandle::reclaim() { diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h index bfda28055a6d6..bd9dcd168eb4a 100644 --- a/src/rgw/rgw_file.h +++ b/src/rgw/rgw_file.h @@ -91,42 +91,50 @@ namespace rgw { struct fh_key { rgw_fh_hk fh_hk; + uint32_t version; static constexpr uint64_t seed = 8675309; - fh_key() {} + fh_key() : version(0) {} fh_key(const rgw_fh_hk& _hk) - : fh_hk(_hk) { + : fh_hk(_hk), version(0) { // nothing } - fh_key(const uint64_t bk, const uint64_t ok) { + fh_key(const uint64_t bk, const uint64_t ok) + : version(0) { fh_hk.bucket = bk; fh_hk.object = ok; } - fh_key(const uint64_t bk, const char *_o) { + fh_key(const uint64_t bk, const char *_o) + : version(0) { fh_hk.bucket = bk; fh_hk.object = XXH64(_o, ::strlen(_o), seed); } - fh_key(const std::string& _b, const std::string& _o) { + fh_key(const std::string& _b, const std::string& _o) + : version(0) { fh_hk.bucket = XXH64(_b.c_str(), _o.length(), seed); fh_hk.object = XXH64(_o.c_str(), _o.length(), seed); } void encode(buffer::list& bl) const { - ENCODE_START(1, 1, bl); + ENCODE_START(2, 1, bl); ::encode(fh_hk.bucket, bl); ::encode(fh_hk.object, bl); + ::encode((uint32_t)2, bl); ENCODE_FINISH(bl); } void decode(bufferlist::iterator& bl) { - DECODE_START(1, bl); + DECODE_START(2, bl); ::decode(fh_hk.bucket, bl); ::decode(fh_hk.object, bl); + if (struct_v >= 2) { + ::decode(version, bl); + } DECODE_FINISH(bl); } }; /* fh_key */ @@ -613,7 +621,7 @@ namespace rgw { void encode_attrs(ceph::buffer::list& ux_key1, ceph::buffer::list& ux_attrs1); - void decode_attrs(const ceph::buffer::list* ux_key1, + bool decode_attrs(const ceph::buffer::list* ux_key1, const ceph::buffer::list* ux_attrs1); void invalidate(); @@ -982,7 +990,7 @@ namespace rgw { << " (" << obj_name << ")" << dendl; - fh_key fhk = parent->make_fhk(key_name); + fh_key fhk = parent->make_fhk(obj_name); retry: RGWFileHandle* fh = @@ -1066,6 +1074,9 @@ namespace rgw { int setattr(RGWFileHandle* rgw_fh, struct stat* st, uint32_t mask, uint32_t flags); + void update_fhk(RGWFileHandle *rgw_fh); + + LookupFHResult stat_bucket(RGWFileHandle* parent, const char *path, RGWLibFS::BucketStats& bs, uint32_t flags); @@ -2343,8 +2354,7 @@ public: /* XXX and fixup key attr (could optimize w/string ref and * dest_object) */ buffer::list ux_key; - std::string key_name{dst_parent->make_key_name(dst_name.c_str())}; - fh_key fhk = dst_parent->make_fhk(key_name); + fh_key fhk = dst_parent->make_fhk(dst_name); rgw::encode(fhk, ux_key); emplace_attr(RGW_ATTR_UNIX_KEY1, std::move(ux_key)); -- 2.39.5