]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
client: -EIO on filelock operations if inode has lost filelocks
authorYan, Zheng <zyan@redhat.com>
Tue, 5 Nov 2019 03:42:58 +0000 (11:42 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 30 Mar 2020 02:24:47 +0000 (10:24 +0800)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/client/Client.cc
src/client/Inode.h

index b8a67c1ce18a7f805825a7dfd6dd070ad6ff6e31..5294759ef99c550be5039ed94f61145691724706 100644 (file)
@@ -4133,6 +4133,8 @@ void Client::remove_session_caps(MetaSession *s, int err)
       dirty_caps = in->dirty_caps | in->flushing_caps;
       in->wanted_max_size = 0;
       in->requested_max_size = 0;
+      if (in->has_any_filelocks())
+       in->flags |= I_ERROR_FILELOCK;
     }
     auto caps = cap->implemented;
     if (cap->wanted | cap->issued)
@@ -10112,6 +10114,9 @@ int Client::_do_filelock(Inode *in, Fh *fh, int lock_type, int op, int sleep,
                 << " type " << fl->l_type << " owner " << owner
                 << " " << fl->l_start << "~" << fl->l_len << dendl;
 
+  if (in->flags & I_ERROR_FILELOCK)
+    return -EIO;
+
   int lock_cmd;
   if (F_RDLCK == fl->l_type)
     lock_cmd = CEPH_LOCK_SHARED;
@@ -10285,30 +10290,39 @@ void Client::_release_filelocks(Fh *fh)
   Inode *in = fh->inode.get();
   ldout(cct, 10) << __func__ << " " << fh << " ino " << in->ino << dendl;
 
+  list<ceph_filelock> activated_locks;
+
   list<pair<int, ceph_filelock> > to_release;
 
   if (fh->fcntl_locks) {
     auto &lock_state = fh->fcntl_locks;
-    for(multimap<uint64_t, ceph_filelock>::iterator p = lock_state->held_locks.begin();
-       p != lock_state->held_locks.end();
-       ++p)
-      to_release.push_back(pair<int, ceph_filelock>(CEPH_LOCK_FCNTL, p->second));
+    for(auto p = lock_state->held_locks.begin(); p != lock_state->held_locks.end(); ) {
+      auto q = p++;
+      if (in->flags & I_ERROR_FILELOCK) {
+       lock_state->remove_lock(q->second, activated_locks);
+      } else {
+       to_release.push_back(pair<int, ceph_filelock>(CEPH_LOCK_FCNTL, q->second));
+      }
+    }
     lock_state.reset();
   }
   if (fh->flock_locks) {
     auto &lock_state = fh->flock_locks;
-    for(multimap<uint64_t, ceph_filelock>::iterator p = lock_state->held_locks.begin();
-       p != lock_state->held_locks.end();
-       ++p)
-      to_release.push_back(pair<int, ceph_filelock>(CEPH_LOCK_FLOCK, p->second));
+    for(auto p = lock_state->held_locks.begin(); p != lock_state->held_locks.end(); ) {
+      auto q = p++;
+      if (in->flags & I_ERROR_FILELOCK) {
+       lock_state->remove_lock(q->second, activated_locks);
+      } else {
+       to_release.push_back(pair<int, ceph_filelock>(CEPH_LOCK_FLOCK, q->second));
+      }
+    }
     lock_state.reset();
   }
 
-  if (to_release.empty())
-    return;
+  if ((in->flags & I_ERROR_FILELOCK) && !in->has_any_filelocks())
+    in->flags &= ~I_ERROR_FILELOCK;
 
-  // mds has already released filelocks if session was closed.
-  if (in->caps.empty())
+  if (to_release.empty())
     return;
 
   struct flock fl;
index 42dbddc97ec856ef8becf209c22efb25e443c77e..afaf64e0515ce36811abdf72cd068d11b9a1982e 100644 (file)
@@ -109,11 +109,12 @@ struct CapSnap {
 };
 
 // inode flags
-#define I_COMPLETE     1
-#define I_DIR_ORDERED  2
-#define I_CAP_DROPPED  4
-#define I_SNAPDIR_OPEN 8
-#define I_KICK_FLUSH   16
+#define I_COMPLETE             (1 << 0)
+#define I_DIR_ORDERED          (1 << 1)
+#define I_SNAPDIR_OPEN         (1 << 2)
+#define I_KICK_FLUSH           (1 << 3)
+#define I_CAP_DROPPED          (1 << 4)
+#define I_ERROR_FILELOCK       (1 << 5)
 
 struct Inode {
   Client *client;
@@ -258,6 +259,12 @@ struct Inode {
   std::unique_ptr<ceph_lock_state_t> fcntl_locks;
   std::unique_ptr<ceph_lock_state_t> flock_locks;
 
+  bool has_any_filelocks() {
+    return
+      (fcntl_locks && !fcntl_locks->empty()) ||
+      (flock_locks && !flock_locks->empty());
+  }
+
   list<Delegation> delegations;
 
   xlist<MetaRequest*> unsafe_ops;