Re: [PATCH 1/1] libceph: use RCU to protect monmap in ceph_compare_options()

Yong Wang <[email protected]> Sun, 12 Jul 2026 14:28:21 +0800
Newsgroups org.kernel.vger.ceph-devel
Message-ID <[email protected]>

在 2026/7/11 0:33, Viacheslav Dubeyko 写道:
> On Fri, 2026-07-10 at 10:16 +0800, Yong Wang wrote:
>>
>> 在 2026/7/9 6:43, Viacheslav Dubeyko 写道:
>>> On Wed, 2026-07-08 at 11:03 +0800, Ren Wei wrote:
>>>> From: Yong Wang <[email protected]>
>>>>
>>>> ceph_compare_options() checks whether a new mount shares any monitor
>>>> address with an existing client by walking client->monc.monmap via
>>>> ceph_monmap_contains().  That comparison can run under sb_lock or
>>>> rbd_client_list_lock, so it cannot take monc->mutex.
>>>>
>>>> Meanwhile, monmap update handling replaces monc->monmap under
>>>> monc->mutex and frees the old map immediately.  A concurrent shared-
>>>> mount comparison can therefore dereference a freed monmap and walk
>>>> stale mon_inst[] entries, triggering a use-after-free.
>>>>
>>>> Protect the compare path with RCU and publish/free monitor maps with
>>>> rcu_assign_pointer() and kfree_rcu().  Annotate monc->monmap as an
>>>> RCU pointer and use rcu_dereference_protected() in mutex-protected
>>>> paths to keep the accesses consistent with the new pointer contract.
>>>>
>>>> This keeps the existing non-blocking comparison semantics while
>>>> ensuring that replaced monmaps remain alive until readers are done.
>>>
>>> The approach makes sense to me. However, I have some concern. If the replaced
>>> monmap(s) could be in use with newly allocated one(s), then are we safe here?
>>
>> The new monmap is fully allocated and initialized before publication, then
>> installed with rcu_assign_pointer() under monc->mutex. Readers only dereference
>> an RCU snapshot and treat the monmap as immutable, while the replaced monmap is
>> freed with kfree_rcu(), which means the old map is not reclaimed immediately, 
>> but is delayed until all readers that are still accessing it have exited the 
>> read-side critical section.Readers only see either the old map or the new map.
>>
>> So it is safe to use.
>>
>>> Have you tried to run xfstests for the patch?
>>
>> I ran the ceph xfstests in QEMU on the patched kernel, and all ceph-
>> specific tests in the current tree passed: ceph/001-006.
>>
>>
> 
> The running only Ceph specific test-cases is not enough. The patch should
> survive the auto group of xfstests.
> 
I reran the tests on a baseline kernel before the RCU patch.

Excluding the notrun cases, the following tests failed both before and after the patch:

- generic/363: fsx reported READ BAD DATA
- generic/429: encrypted dentry/key revalidation behavior did not match expectations
- generic/440: encrypted name/key cache consistency behavior did not match expectations
- generic/580: encrypted files became inaccessible after key removal/re-addition
- generic/593: filesystem-level/provisioning-key encryption flow failed
- generic/595: encrypted file remained inaccessible after key eviction/re-addition
- generic/631: overlayfs-on-Ceph scratch mount path failed

generic/650 and generic/777 could not be completed reliably in my local environment because 
they caused the terminal to become unresponsive, so I do not have a meaningful 
before/after comparison for them.

So from this comparison, I do not have evidence that the above failures were introduced 
by the RCU patch.

Kernel(net) commit tested before the patch:
  6d27e29a90bc6a717b97c6ddcd866db7bd8e4adc

xfstests commit:
  ffc8bad17e5b2f56e48dbac43f7c5ae8ac368fe5

Best regards,
Yong
> Thanks,
> Slava.