summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorMax Kellermann <max.kellermann@ionos.com>2026-08-18 20:40:05 +0200
committerIlya Dryomov <idryomov@gmail.com>2026-08-26 19:57:29 +0200
commit8fdf946445732c2bcd685abc8bd0e509d2ebc158 (patch)
tree2c0dd4b62599d422e0b134579d01e60931c19545 /include
parent3cde4a8302301679937474a5f7a851394cc1bd11 (diff)
downloadlinux-8fdf946445732c2bcd685abc8bd0e509d2ebc158.tar.gz
linux-8fdf946445732c2bcd685abc8bd0e509d2ebc158.zip
ceph: force a cap message when a deferred revoke can't be acked immediately
When the MDS revokes capabilities, handle_cap_grant() normally guarantees a response by setting `CHECK_CAPS_FLUSH_FORCE` (see commit 31634d7597d8 ("ceph: force sending a cap update msg back to MDS for revoke op")), so ceph_check_caps() sends a cap message even if the client would otherwise decide it has nothing to do. That guarantee is skipped whenever the revoke has to be deferred (via revoke_wait): revoking Fb while dirty data is still buffered (writeback is queued first) or revoking Fc while pages are cached (async invalidation is queued first). In those cases, the ack is left to the deferred completion (ceph_put_wrbuffer_cap_refs() after writeback, or the invalidate worker after invalidation); both of which call ceph_check_caps(ci,0) i.e. without `CHECK_CAPS_FLUSH_FORCE`. Nothing gets sent under one of the following conditions: - the inode is retaining caps because the file was used recently (file_wanted != 0; retain |= CEPH_CAP_ANY) - the revoked cap is still used because the page was re-cached (e.g. a file being re-read) - the MDS has meanwhile re-granted, so `issued==implemented` and the client sees nothing being revoked The client then never emits the cap message which the MDS is waiting for. The MDS blocks on the revoke indefinitely and logs, for minutes or hours: client.NNN isn't responding to mclientcaps(revoke), ino 0x... pending pAsxLsXsxFsxcrwb issued pAsxLsXsxFsxcrwb, sent 964.899182 seconds ago The client-side state at that point shows the full cap set still issued, nothing in the revoking/flushing sets. Thus nothing gets sent. This patch fixes it by remembering that a forced response is expected. When a revoke is deferred, set `CEPH_I_FLUSH_FORCE` on the inode. ceph_check_caps() replays it as `CHECK_CAPS_FLUSH_FORCE`, so whichever path re-checks the inode next (the writeback/invalidate completion, the delayed worker, or any other caller) is guaranteed to send a cap message to the MDS. __prep_cap() clears the flag once a message is actually built. This is the deferred-path counterpart of the existing `CHECK_CAPS_FLUSH_FORCE` handling; a normal (non-deferred) revoke still forces the response inline as before. Cc: stable@vger.kernel.org Fixes: 31634d7597d8 ("ceph: force sending a cap update msg back to MDS for revoke op") Fixes: 257e6172ab36 ("ceph: don't let check_caps skip sending responses for revoke msgs") Signed-off-by: Max Kellermann <max.kellermann@ionos.com> Reviewed-by: Alex Markuze <amarkuze@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Diffstat (limited to 'include')
0 files changed, 0 insertions, 0 deletions