]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw_file: dont deadlock in advance_mtime() 29801/head
authorMatt Benjamin <mbenjamin@redhat.com>
Thu, 8 Aug 2019 20:21:24 +0000 (16:21 -0400)
committerNathan Cutler <ncutler@suse.com>
Wed, 21 Aug 2019 17:09:54 +0000 (19:09 +0200)
Fixes: https://tracker.ceph.com/issues/41173
Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
(cherry picked from commit 0d3338c2d2271bbf6f4c7774ad175f7ee42d07f6)

src/rgw/rgw_file.cc
src/rgw/rgw_file.h

index f88a6e2450c2c9a4ef70ed10903b274eeb28fd9d..6bdda2b460f2d01360aff3a014a77af3d31bfddb 100644 (file)
@@ -551,7 +551,7 @@ namespace rgw {
       /* save attrs */
       rgw_fh->encode_attrs(ux_key, ux_attrs);
       if (st)
-        rgw_fh->stat(st);
+        rgw_fh->stat(st, RGWFileHandle::FLAG_LOCKED);
       get<0>(mkr) = rgw_fh;
     } else {
       get<1>(mkr) = -EIO;
@@ -681,7 +681,7 @@ namespace rgw {
          parent->set_ctime(real_clock::to_timespec(t));
        }
         if (st)
-          (void) rgw_fh->stat(st);
+         (void) rgw_fh->stat(st, RGWFileHandle::FLAG_LOCKED);
 
         rgw_fh->set_etag(*(req.get_attr(RGW_ATTR_ETAG)));
         rgw_fh->set_acls(*(req.get_attr(RGW_ATTR_ACL))); 
@@ -1224,8 +1224,11 @@ namespace rgw {
     }
 
     bool initial_off;
+    char* mk{nullptr};
+
     if (likely(!! get<const char*>(&offset))) {
-      initial_off = ! get<const char*>(offset);
+      mk = const_cast<char*>(get<const char*>(offset));
+      initial_off = !mk;
     } else {
       initial_off = (*get<uint64_t*>(offset) == 0);
     }
@@ -1438,10 +1441,14 @@ namespace rgw {
     }
   }
 
-  void RGWFileHandle::advance_mtime() {
+  void RGWFileHandle::advance_mtime(uint32_t flags) {
     /* intended for use on directories, fast-forward mtime so as to
      * ensure a new, higher value for the change attribute */
-    lock_guard guard(mtx);
+    unique_lock uniq(mtx, std::defer_lock);
+    if (likely(! (flags & RGWFileHandle::FLAG_LOCKED))) {
+      uniq.lock();
+    }
+
     /* advance mtime only if stored mtime is older than the
      * configured namespace expiration */
     auto now = real_clock::now();
index 46f28fda7cffe92f718068133bb4aca0998bd44d..46623ecb4b0f62aadf165743af11e8398d4bb7cf 100644 (file)
@@ -238,7 +238,7 @@ namespace rgw {
     };
 
     void clear_state();
-    void advance_mtime();
+    void advance_mtime(uint32_t flags = FLAG_NONE);
 
     boost::variant<file, directory> variant_type;
 
@@ -433,7 +433,7 @@ namespace rgw {
        state.ctime = st->st_ctim;
     }
 
-    int stat(struct stat* st) {
+    int stat(struct stat* st, uint32_t flags = FLAG_NONE) {
       /* partial Unix attrs */
       memset(st, 0, sizeof(struct stat));
       st->st_dev = state.dev;
@@ -447,7 +447,7 @@ namespace rgw {
       switch (fh.fh_type) {
       case RGW_FS_TYPE_DIRECTORY:
        /* virtual directories are always invalid */
-       advance_mtime();
+       advance_mtime(flags);
        st->st_nlink = state.nlink;
        break;
       case RGW_FS_TYPE_FILE:
@@ -1070,7 +1070,7 @@ namespace rgw {
       fh_key fhk = parent->make_fhk(obj_name);
 
       lsubdout(get_context(), rgw, 10)
-       << __func__ << " lookup called on "
+       << __func__ << " called on "
        << parent->object_name() << " for " << key_name
        << " (" << obj_name << ")"
        << " -> " << fhk