mirror of
https://github.com/ceph/ceph
synced 2025-01-19 09:32:00 +00:00
rgw_file: fixup attrs across renames
Once Unix attributes were materialized as RGW object/bucket attributes, it became possible to verify the serialized bucket and object hashes with the expected values (based on the file-type invariant path to the object). Prior to this change, we saved the serialized hash values with the rest of the Unix attrs, in RGW_ATTR_UNIX1. Unfortunately, these values were invalidated by rename operations. To address this problem, and to faciliate future operations on objects by their hashed ids, the id hashes have been moved into their own RGW attr RGW_ATTR_UNIX_KEY1. This should allow more efficient search by, but more importantly to the invalidation problem, allows us to use the ATTRSMOD_MERGE behavior in RGWCopyObj to get copy offload while still fixing up the object id. The code at this commit doesn't use the serialized unix_mode value as the outgoing st.st_mode result for rgw_getattr operations, pending a bugfix for Ganesha's expected value range. Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
This commit is contained in:
parent
b6297a704b
commit
a353eaca61
@ -96,7 +96,8 @@ using ceph::crypto::MD5;
|
||||
#define RGW_ATTR_OLH_PENDING_PREFIX RGW_ATTR_OLH_PREFIX "pending."
|
||||
|
||||
/* RGW File Attributes */
|
||||
#define RGW_ATTR_UNIX1 RGW_ATTR_PREFIX "unix1"
|
||||
#define RGW_ATTR_UNIX_KEY1 RGW_ATTR_PREFIX "unix-key1"
|
||||
#define RGW_ATTR_UNIX1 RGW_ATTR_PREFIX "unix1"
|
||||
|
||||
#define RGW_BUCKETS_OBJ_SUFFIX ".buckets"
|
||||
|
||||
|
@ -55,9 +55,10 @@ namespace rgw {
|
||||
if (get<0>(fhr)) {
|
||||
RGWFileHandle* rgw_fh = get<0>(fhr);
|
||||
/* restore attributes */
|
||||
auto ux_key = req.get_attr(RGW_ATTR_UNIX_KEY1);
|
||||
auto ux_attrs = req.get_attr(RGW_ATTR_UNIX1);
|
||||
if (ux_attrs) {
|
||||
rgw_fh->decode_attrs(ux_attrs);
|
||||
if (ux_key && ux_attrs) {
|
||||
rgw_fh->decode_attrs(ux_key, ux_attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,9 +119,10 @@ namespace rgw {
|
||||
rgw_fh->set_size(req.get_size());
|
||||
rgw_fh->set_mtime(real_clock::to_timespec(req.get_mtime()));
|
||||
/* restore attributes */
|
||||
auto ux_key = req.get_attr(RGW_ATTR_UNIX_KEY1);
|
||||
auto ux_attrs = req.get_attr(RGW_ATTR_UNIX1);
|
||||
if (ux_attrs) {
|
||||
rgw_fh->decode_attrs(ux_attrs);
|
||||
if (ux_key && ux_attrs) {
|
||||
rgw_fh->decode_attrs(ux_key, ux_attrs);
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
@ -143,9 +145,10 @@ namespace rgw {
|
||||
rgw_fh->set_size(req.get_size());
|
||||
rgw_fh->set_mtime(real_clock::to_timespec(req.get_mtime()));
|
||||
/* restore attributes */
|
||||
auto ux_key = req.get_attr(RGW_ATTR_UNIX_KEY1);
|
||||
auto ux_attrs = req.get_attr(RGW_ATTR_UNIX1);
|
||||
if (ux_attrs) {
|
||||
rgw_fh->decode_attrs(ux_attrs);
|
||||
if (ux_key && ux_attrs) {
|
||||
rgw_fh->decode_attrs(ux_key, ux_attrs);
|
||||
}
|
||||
}
|
||||
goto done;
|
||||
@ -321,7 +324,7 @@ namespace rgw {
|
||||
|
||||
LookupFHResult fhr;
|
||||
RGWFileHandle* rgw_fh = nullptr;
|
||||
buffer::list ux_attrs;
|
||||
buffer::list ux_key, ux_attrs;
|
||||
|
||||
fhr = lookup_fh(parent, name,
|
||||
RGWFileHandle::FLAG_CREATE|
|
||||
@ -332,7 +335,7 @@ namespace rgw {
|
||||
rgw_fh->create_stat(st, mask);
|
||||
rgw_fh->set_times(real_clock::now());
|
||||
/* save attrs */
|
||||
rgw_fh->encode_attrs(ux_attrs);
|
||||
rgw_fh->encode_attrs(ux_key, ux_attrs);
|
||||
rgw_fh->stat(st);
|
||||
get<0>(mkr) = rgw_fh;
|
||||
} else {
|
||||
@ -355,7 +358,11 @@ namespace rgw {
|
||||
|
||||
string uri = "/" + bname; /* XXX get rid of URI some day soon */
|
||||
RGWCreateBucketRequest req(get_context(), get_user(), uri);
|
||||
|
||||
/* save attrs */
|
||||
req.emplace_attr(RGW_ATTR_UNIX_KEY1, std::move(ux_key));
|
||||
req.emplace_attr(RGW_ATTR_UNIX1, std::move(ux_attrs));
|
||||
|
||||
rc = rgwlib.get_fe()->execute_req(&req);
|
||||
rc2 = req.get_ret();
|
||||
} else {
|
||||
@ -369,9 +376,14 @@ namespace rgw {
|
||||
dir_name += "/";
|
||||
dir_name += name;
|
||||
dir_name += "/";
|
||||
|
||||
RGWPutObjRequest req(get_context(), get_user(), parent->bucket_name(),
|
||||
dir_name, bl);
|
||||
|
||||
/* save attrs */
|
||||
req.emplace_attr(RGW_ATTR_UNIX_KEY1, std::move(ux_key));
|
||||
req.emplace_attr(RGW_ATTR_UNIX1, std::move(ux_attrs));
|
||||
|
||||
rc = rgwlib.get_fe()->execute_req(&req);
|
||||
rc2 = req.get_ret();
|
||||
}
|
||||
@ -549,15 +561,24 @@ namespace rgw {
|
||||
} while (! stop);
|
||||
} /* RGWLibFS::gc */
|
||||
|
||||
void RGWFileHandle::encode_attrs(buffer::list& bl)
|
||||
void RGWFileHandle::encode_attrs(ceph::buffer::list& ux_key1,
|
||||
ceph::buffer::list& ux_attrs1)
|
||||
{
|
||||
rgw::encode(*this, bl);
|
||||
} /* RGWFileHandle::decode_attrs */
|
||||
fh_key fhk(this->fh.fh_hk);
|
||||
rgw::encode(fhk, ux_key1);
|
||||
rgw::encode(*this, ux_attrs1);
|
||||
} /* RGWFileHandle::encode_attrs */
|
||||
|
||||
void RGWFileHandle::decode_attrs(const buffer::list* cbl)
|
||||
void RGWFileHandle::decode_attrs(const ceph::buffer::list* ux_key1,
|
||||
const ceph::buffer::list* ux_attrs1)
|
||||
{
|
||||
auto bl_iter = const_cast<buffer::list*>(cbl)->begin();
|
||||
rgw::decode(*this, bl_iter);
|
||||
fh_key fhk;
|
||||
auto bl_iter_key1 = const_cast<buffer::list*>(ux_key1)->begin();
|
||||
rgw::decode(fhk, bl_iter_key1);
|
||||
assert(this->fh.fh_hk == fhk.fh_hk);
|
||||
|
||||
auto bl_iter_unix1 = const_cast<buffer::list*>(ux_attrs1)->begin();
|
||||
rgw::decode(*this, bl_iter_unix1);
|
||||
} /* RGWFileHandle::decode_attrs */
|
||||
|
||||
bool RGWFileHandle::reclaim() {
|
||||
@ -779,7 +800,7 @@ namespace rgw {
|
||||
|
||||
int RGWWriteRequest::exec_finish()
|
||||
{
|
||||
buffer::list bl, aclbl, bl_unix;
|
||||
buffer::list bl, aclbl, ux_key, ux_attrs;
|
||||
map<string, string>::iterator iter;
|
||||
char calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
|
||||
unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE];
|
||||
@ -806,8 +827,9 @@ namespace rgw {
|
||||
policy.encode(aclbl);
|
||||
emplace_attr(RGW_ATTR_ACL, std::move(aclbl));
|
||||
|
||||
rgw_fh->encode_attrs(bl_unix);
|
||||
emplace_attr(RGW_ATTR_UNIX1, std::move(bl_unix));
|
||||
rgw_fh->encode_attrs(ux_key, ux_attrs);
|
||||
emplace_attr(RGW_ATTR_UNIX_KEY1, std::move(ux_key));
|
||||
emplace_attr(RGW_ATTR_UNIX1, std::move(ux_attrs));
|
||||
|
||||
for (iter = s->generic_attrs.begin(); iter != s->generic_attrs.end();
|
||||
++iter) {
|
||||
|
@ -100,8 +100,24 @@ namespace rgw {
|
||||
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(fh_hk.bucket, bl);
|
||||
::encode(fh_hk.object, bl);
|
||||
ENCODE_FINISH(bl);
|
||||
}
|
||||
|
||||
void decode(bufferlist::iterator& bl) {
|
||||
DECODE_START(1, bl);
|
||||
::decode(fh_hk.bucket, bl);
|
||||
::decode(fh_hk.object, bl);
|
||||
DECODE_FINISH(bl);
|
||||
}
|
||||
}; /* fh_key */
|
||||
|
||||
WRITE_CLASS_ENCODER(fh_key);
|
||||
|
||||
inline bool operator<(const fh_key& lhs, const fh_key& rhs)
|
||||
{
|
||||
return ((lhs.fh_hk.bucket < rhs.fh_hk.bucket) ||
|
||||
@ -326,10 +342,10 @@ namespace rgw {
|
||||
if (mask & RGW_SETATTR_MODE) {
|
||||
switch (fh.fh_type) {
|
||||
case RGW_FS_TYPE_DIRECTORY:
|
||||
st->st_mode = state.unix_mode|S_IFDIR;
|
||||
state.unix_mode = st->st_mode|S_IFDIR;
|
||||
break;
|
||||
case RGW_FS_TYPE_FILE:
|
||||
st->st_mode = state.unix_mode|S_IFREG;
|
||||
state.unix_mode = st->st_mode|S_IFREG;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -353,11 +369,11 @@ namespace rgw {
|
||||
|
||||
switch (fh.fh_type) {
|
||||
case RGW_FS_TYPE_DIRECTORY:
|
||||
st->st_mode = RGW_RWXMODE|S_IFDIR;
|
||||
st->st_mode = RGW_RWXMODE|S_IFDIR /* state.unix_mode|S_IFDIR */;
|
||||
st->st_nlink = 3;
|
||||
break;
|
||||
case RGW_FS_TYPE_FILE:
|
||||
st->st_mode = RGW_RWMODE|S_IFREG;
|
||||
st->st_mode = RGW_RWMODE|S_IFREG /* state.unix_mode|S_IFREG */;
|
||||
st->st_nlink = 1;
|
||||
st->st_blksize = 4096;
|
||||
st->st_size = state.size;
|
||||
@ -430,7 +446,7 @@ namespace rgw {
|
||||
return fh_key(fhk.fh_hk.object, name.c_str());
|
||||
else {
|
||||
std::string key_name = make_key_name(name.c_str());
|
||||
return fh_key(fhk.fh_hk.object, key_name.c_str());
|
||||
return fh_key(fhk.fh_hk.bucket, key_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@ -528,8 +544,6 @@ namespace rgw {
|
||||
void encode(buffer::list& bl) const {
|
||||
ENCODE_START(1, 1, bl);
|
||||
::encode(uint32_t(fh.fh_type), bl);
|
||||
::encode(fh.fh_hk.bucket, bl);
|
||||
::encode(fh.fh_hk.object, bl);
|
||||
::encode(state.dev, bl);
|
||||
::encode(state.size, bl);
|
||||
::encode(state.nlink, bl);
|
||||
@ -544,13 +558,9 @@ namespace rgw {
|
||||
|
||||
void decode(bufferlist::iterator& bl) {
|
||||
DECODE_START(1, bl);
|
||||
struct rgw_file_handle tfh;
|
||||
uint32_t fh_type;
|
||||
::decode(fh_type, bl);
|
||||
tfh.fh_type = static_cast<enum rgw_fh_type>(fh_type);
|
||||
::decode(tfh.fh_hk.bucket, bl);
|
||||
::decode(tfh.fh_hk.object, bl);
|
||||
assert(fh.fh_hk == tfh.fh_hk);
|
||||
assert(fh.fh_type == fh_type);
|
||||
::decode(state.dev, bl);
|
||||
::decode(state.size, bl);
|
||||
::decode(state.nlink, bl);
|
||||
@ -565,9 +575,11 @@ namespace rgw {
|
||||
DECODE_FINISH(bl);
|
||||
}
|
||||
|
||||
void decode_attrs(const ceph::buffer::list* bl);
|
||||
void encode_attrs(ceph::buffer::list& ux_key1,
|
||||
ceph::buffer::list& ux_attrs1);
|
||||
|
||||
void encode_attrs(ceph::buffer::list& bl);
|
||||
void decode_attrs(const ceph::buffer::list* ux_key1,
|
||||
const ceph::buffer::list* ux_attrs1);
|
||||
|
||||
virtual bool reclaim();
|
||||
|
||||
@ -801,6 +813,12 @@ namespace rgw {
|
||||
std::string obj_name{name};
|
||||
std::string key_name{parent->make_key_name(name)};
|
||||
|
||||
lsubdout(get_context(), rgw, 10)
|
||||
<< __func__ << " lookup called on "
|
||||
<< parent->object_name() << " for " << key_name
|
||||
<< " (" << obj_name << ")"
|
||||
<< dendl;
|
||||
|
||||
fh_key fhk = parent->make_fhk(key_name);
|
||||
|
||||
retry:
|
||||
@ -1972,7 +1990,11 @@ public:
|
||||
const std::string& _src_name, const std::string& _dst_name)
|
||||
: RGWLibRequest(_cct, _user), src_parent(_src_parent),
|
||||
dst_parent(_dst_parent), src_name(_src_name), dst_name(_dst_name) {
|
||||
/* all requests have this */
|
||||
op = this;
|
||||
|
||||
/* allow this request to replace selected attrs */
|
||||
attrs_mod = RGWRados::ATTRSMOD_MERGE;
|
||||
}
|
||||
|
||||
virtual bool only_bucket() { return true; }
|
||||
@ -2008,6 +2030,14 @@ public:
|
||||
if (! valid_s3_object_name(dest_object))
|
||||
return -ERR_INVALID_OBJECT_NAME;
|
||||
|
||||
/* 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);
|
||||
rgw::encode(fhk, ux_key);
|
||||
emplace_attr(RGW_ATTR_UNIX_KEY1, std::move(ux_key));
|
||||
|
||||
#if 0 /* XXX needed? */
|
||||
s->relative_uri = uri;
|
||||
s->info.request_uri = uri; // XXX
|
||||
|
Loading…
Reference in New Issue
Block a user