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)
void Client::unlock_fh_pos(Fh *f)
{
+ ceph_assert(ceph_mutex_is_locked_by_me(client_lock));
+
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->notify_one();
+ }
}
int Client::uninline_data(Inode *in, Context *onfinish)