]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw_file: fixup attrs across renames 8563/head
authorMatt Benjamin <mbenjamin@redhat.com>
Wed, 13 Apr 2016 23:46:25 +0000 (19:46 -0400)
committerMatt Benjamin <mbenjamin@redhat.com>
Wed, 13 Apr 2016 23:46:25 +0000 (19:46 -0400)
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>
src/rgw/rgw_common.h
src/rgw/rgw_file.cc
src/rgw/rgw_file.h

index 707dbd174c6d454a0becb43f034801bfbfb146c7..39e0d4acd3f5016f0872fc1118d0b819e3885482 100644 (file)
@@ -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"
 
index 1a1007d2ec4ae1d5c1adbe6d971411b9fbc1d01a..1bc6b1f4a480ddd5e06adad59acfc00ee3a7a8e6 100644 (file)
@@ -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) {
index d1c627c1fd66f89b98b81928c9e735f0fd069787..42b6649105187a18b75f84be369c93ce91eebc98 100644 (file)
@@ -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