From d188b13462d56b49504d8e521c346eb313167f6b Mon Sep 17 00:00:00 2001 From: Venky Shankar Date: Wed, 15 Oct 2025 13:40:35 +0000 Subject: [PATCH] client: signal waitfor_commit waiters for write delegation enabled inode Signed-off-by: Venky Shankar --- src/client/Client.cc | 12 +++++------- src/client/Inode.cc | 17 ++++++++++++++++- src/client/Inode.h | 1 + 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index 11429b7eb35..8f00e820518 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -3797,7 +3797,9 @@ void Client::put_cap_ref(Inode *in, int cap) p.second.dirty_data = 0; signal_context_list(in->waitfor_commit); ldout(cct, 5) << __func__ << " dropped last FILE_BUFFER ref on " << *in << dendl; - ++put_nref; + if (!in->is_write_delegated()) { + ++put_nref; + } if (!in->cap_snaps.empty()) { flush_snaps(in); @@ -12456,13 +12458,9 @@ int Client::_fsync(Inode *in, bool syncdataonly) ldout(cct, 15) << "got " << r << " from flush writeback" << dendl; } else { // FIXME: this can starve - int nr_refs = 0; - if (in->is_write_delegated()) { - ++nr_refs; - } - while (in->cap_refs[CEPH_CAP_FILE_BUFFER] > nr_refs) { + while (!in->is_last_cap_ref(CEPH_CAP_FILE_BUFFER)) { ldout(cct, 10) << "ino " << in->ino << " has " << in->cap_refs[CEPH_CAP_FILE_BUFFER] - << " uncommitted (nrefs: " << nr_refs << "), waiting" << dendl; + << " uncommitted, waiting" << dendl; wait_on_context_list(in->waitfor_commit); } } diff --git a/src/client/Inode.cc b/src/client/Inode.cc index f0d2dfcdbec..854f0a296bb 100644 --- a/src/client/Inode.cc +++ b/src/client/Inode.cc @@ -198,6 +198,20 @@ void Inode::get_cap_ref(int cap) } } +bool Inode::is_last_cap_ref(int c) +{ + if (c != CEPH_CAP_FILE_BUFFER) { + return cap_refs[c] == 0; + } + + int nref = 0; + if (is_write_delegated()) { + ++nref; + } + + return cap_refs[c] == nref; +} + int Inode::put_cap_ref(int cap) { int last = 0; @@ -209,7 +223,8 @@ int Inode::put_cap_ref(int cap) lderr(client->cct) << "put_cap_ref " << ccap_string(c) << " went negative on " << *this << dendl; ceph_assert(cap_refs[c] > 0); } - if (--cap_refs[c] == 0) + --cap_refs[c]; + if (is_last_cap_ref(c)) last |= c; //cout << "inode " << *this << " put " << cap_string(c) << " " << (cap_refs[c]+1) << " -> " << cap_refs[c] << std::endl; } diff --git a/src/client/Inode.h b/src/client/Inode.h index 90fbc6e254c..d128c24d8c2 100644 --- a/src/client/Inode.h +++ b/src/client/Inode.h @@ -316,6 +316,7 @@ struct Inode : RefCountedObject { void get_cap_ref(int cap); int put_cap_ref(int cap); + bool is_last_cap_ref(int c); bool is_any_caps(); bool cap_is_valid(const Cap &cap) const; int caps_issued(int *implemented = 0) const; -- 2.39.5