afs: Fix RCU handling of symlinks in RCU pathwalk
The afs filesystem in the kernel doesn't handle RCU pathwalk of symlinks
correctly. The problem is twofold: firstly, it doesn't treat the buffer
pointers as RCU pointers with the appropriate barriering; and secondly, it
can race with another thread updating the contents of the symlink because a
third party updated it on the server.
Fix this by the following means:
(1) Keep a separate copy of the symlink contents with an rcu_head. This
is always going to be a lot smaller than a page, so it can be
kmalloc'd and save quite a bit of memory. It also needs a refcount
for non-RCU pathwalk.
(2) Split the symlink read and write-to-cache routines in afs from those
for directories.
(3) Discard the I/O buffer as soon as the write-to-cache completes as this
is a full page (plus a folio_queue).
(4) If there's no cache, discard the I/O buffer immediately after reading
and copying if there is no cache.
Fixes: 6698c02d64b2 ("afs: Locally initialise the contents of a new symlink on creation")
Closes: https://sashiko.dev/#/patchset/20260326104544.509518-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
7 files changed