]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
client: wake up the front pos waiter 40865/head
authorXiubo Li <xiubli@redhat.com>
Fri, 19 Feb 2021 14:05:23 +0000 (22:05 +0800)
committerXiubo Li <xiubli@redhat.com>
Mon, 19 Apr 2021 12:35:28 +0000 (20:35 +0800)
The old code was buggy, why it ran well without any problem is that
the big client_lock will make sure that the read/write won't run in
parallel, so it won't be any problem here.

But when introducing inode lock to break the client_lock, which will
allow the read/write to run parallelly, the pos waiters won't get any
chance to be woke up.

In unlock_fh_pos(), it will always wake up the frontest waiter.

Fixes: https://tracker.ceph.com/issues/49379
Signed-off-by: Xiubo Li <xiubli@redhat.com>
(cherry picked from commit 66bcb880abe56c08e04876e98d3d751e78f8fd2f)

Conflicts:
        switch cond->notify_one() to cond->SignalOne()

src/client/Client.cc

index 22bd81dbb4cc170fb40c61c040e99e3fe8985db4..f60f944a86e2492722321b87a86accc9600afac4 100755 (executable)
@@ -9055,8 +9055,15 @@ void Client::lock_fh_pos(Fh *f)
 
 void Client::unlock_fh_pos(Fh *f)
 {
+  ceph_assert(client_lock.is_locked_by_me());
+
   ldout(cct, 10) << __func__ << " " << f << dendl;
   f->pos_locked = false;
+  if (!f->pos_waiters.empty()) {
+    // only wake up the oldest waiter
+    auto cond = f->pos_waiters.front();
+    cond->SignalOne();
+  }
 }
 
 int Client::uninline_data(Inode *in, Context *onfinish)