netfs: Miscellaneous fixes
Subsystems (8)
David Howells
maintainercover netfs: Miscellaneous fixes
Hi Christian,
Here are some miscellaneous fixes and changes for netfslib, if you could pull them:
(1) Fix the collection of results during a pause in transmission.
(2) Call ->invalidate_cache() only if provided.
(3) Fix the rolling buffer to not hammer atomic bit clears when loading from readahead.
(4) Fix netfs_unbuffered_read() to return ssize_t.
The patches can also be found here:
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=netfs-fixes
Thanks,
David
David Howells (3):
netfs: Fix collection of results during pause when collection
offloaded
netfs: Fix rolling_buffer_load_from_ra() to not clear mark bits
netfs: Fix netfs_unbuffered_read() to return ssize_t rather than int
Max Kellermann (1):
netfs: Call invalidate_cache only if implemented
fs/netfs/direct_read.c | 6 +++--- fs/netfs/read_collect.c | 18 ++++++++++-------- fs/netfs/rolling_buffer.c | 4 ---- fs/netfs/write_collect.c | 3 ++- 4 files changed, 15 insertions(+), 16 deletions(-)
David Howells
maintainerPATCH 1/4 netfs: Fix collection of results during pause when collection offloaded
A netfs read request can run in one of two modes: for synchronous reads writes, the app thread does the collection of results and for asynchronous reads, this is offloaded to a worker thread. This is controlled by the NETFS_RREQ_OFFLOAD_COLLECTION flag.
Now, if a subrequest incurs an error, the NETFS_RREQ_PAUSE flag is set to stop the issuing loop temporarily from issuing more subrequests until a retry is successful or the request is abandoned.
When the issuing loop sees NETFS_RREQ_PAUSE, it jumps to netfs_wait_for_pause() which will wait for the PAUSE flag to be cleared - and whilst it is waiting, it will call out to the collector as more results acrue... But this is the wrong thing to do if OFFLOAD_COLLECTION is set as we can then end up with both the app thread and the work item collecting results simultaneously.
This manifests itself occasionally when running the generic/323 xfstest against multichannel cifs as an oops that's a bit random but frequently involving io_submit() (the test does lots of simultaneous async DIO reads).
Fix this by only doing the collection in netfs_wait_for_pause() if the NETFS_RREQ_OFFLOAD_COLLECTION is not set.
--- fs/netfs/read_collect.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
fs/netfs/read_collect.c +10 -8
@@ -682,14 +682,16 @@ void netfs_wait_for_pause(struct netfs_io_request *rreq)trace_netfs_rreq (rreq, netfs_rreq_trace_wait_queue);prepare_to_wait (&rreq->waitq, &myself,TASK_UNINTERRUPTIBLE ); - subreq =list_first_entry_or_null (&stream->subrequests, - struct netfs_io_subrequest, rreq_link); -if (subreq && - (!test_bit (NETFS_SREQ_IN_PROGRESS , &subreq->flags) || -test_bit (NETFS_SREQ_MADE_PROGRESS , &subreq->flags))) { -__set_current_state (TASK_RUNNING ); -netfs_read_collection (rreq); -continue ; +if (!test_bit (NETFS_RREQ_OFFLOAD_COLLECTION , &rreq->flags)) { + subreq =list_first_entry_or_null (&stream->subrequests, + struct netfs_io_subrequest, rreq_link); +if (subreq && + (!test_bit (NETFS_SREQ_IN_PROGRESS , &subreq->flags) || +test_bit (NETFS_SREQ_MADE_PROGRESS , &subreq->flags))) { +__set_current_state (TASK_RUNNING ); +netfs_read_collection (rreq); +continue ; + } } if (!test_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags) ||
David Howells
maintainerPATCH 2/4 netfs: Call `invalidate_cache` only if implemented
In reply to David HowellsFrom: Max Kellermann <[email protected]>
Many filesystems such as NFS and Ceph do not implement the invalidate_cache method. On those filesystems, if writing to the cache (NETFS_WRITE_TO_CACHE) fails for some reason, the kernel crashes like this:
BUG: kernel NULL pointer dereference, address: 0000000000000000 #PF: supervisor instruction fetch in kernel mode #PF: error_code(0x0010) - not-present page PGD 0 P4D 0 Oops: Oops: 0010 [#1] SMP PTI CPU: 9 UID: 0 PID: 3380 Comm: kworker/u193:11 Not tainted 6.13.3-cm4all1-hp #437 Hardware name: HP ProLiant DL380 Gen9/ProLiant DL380 Gen9, BIOS P89 10/17/2018 Workqueue: events_unbound netfs_write_collection_worker RIP: 0010:0x0 Code: Unable to access opcode bytes at 0xffffffffffffffd6. RSP: 0018:ffff9b86e2ca7dc0 EFLAGS: 00010202 RAX: 0000000000000000 RBX: 0000000000000000 RCX: 7fffffffffffffff RDX: 0000000000000001 RSI: ffff89259d576a18 RDI: ffff89259d576900 RBP: ffff89259d5769b0 R08: ffff9b86e2ca7d28 R09: 0000000000000002 R10: ffff89258ceaca80 R11: 0000000000000001 R12: 0000000000000020 R13: ffff893d158b9338 R14: ffff89259d576900 R15: ffff89259d5769b0 FS: 0000000000000000(0000) GS:ffff893c9fa40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffffffffd6 CR3: 000000054442e003 CR4: 00000000001706f0 Call Trace: <TASK> ? __die+0x1f/0x60 ? page_fault_oops+0x15c/0x460 ? try_to_wake_up+0x2d2/0x530 ? exc_page_fault+0x5e/0x100 ? asm_exc_page_fault+0x22/0x30 netfs_write_collection_worker+0xe9f/0x12b0 ? xs_poll_check_readable+0x3f/0x80 ? xs_stream_data_receive_workfn+0x8d/0x110 process_one_work+0x134/0x2d0 worker_thread+0x299/0x3a0 ? __pfx_worker_thread+0x10/0x10 kthread+0xba/0xe0 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x30/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 </TASK> Modules linked in: CR2: 0000000000000000
This patch adds the missing NULL check.
--- fs/netfs/write_collect.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/netfs/write_collect.c +2 -1
@@ -400,7 +400,8 @@ void netfs_write_collection_worker(struct work_struct *work)trace_netfs_rreq (wreq, netfs_rreq_trace_write_done);if (wreq->io_streams[1 ].active && - wreq->io_streams[1 ].failed) { + wreq->io_streams[1 ].failed && + ictx->ops->invalidate_cache) {/* Cache write failure doesn't prevent writeback completion * unless we're in disconnected mode. */
David Howells
maintainerPATCH 3/4 netfs: Fix rolling_buffer_load_from_ra() to not clear mark bits
In reply to David Howellsrolling_buffer_load_from_ra() looms large in the perf report because it loops around doing an atomic clear for each of the three mark bits per folio. However, this is both inefficient (it would be better to build a mask and atomically AND them out) and unnecessary as they shouldn't be set.
Fix this by removing the loop.
--- fs/netfs/rolling_buffer.c | 4 ---- 1 file changed, 4 deletions(-)
fs/netfs/rolling_buffer.c +0 -4
@@ -146,10 +146,6 @@ ssize_t rolling_buffer_load_from_ra(struct rolling_buffer *roll,/* Store the counter after setting the slot. */ smp_store_release (&roll->next_head_slot, to); - -for (; ix <folioq_nr_slots (fq); ix++) -folioq_clear (fq, ix); -return size; }
David Howells
maintainerPATCH 4/4 netfs: Fix netfs_unbuffered_read() to return ssize_t rather than int
In reply to David HowellsFix netfs_unbuffered_read() to return an ssize_t rather than an int as netfs_wait_for_read() returns ssize_t and this gets implicitly truncated.
--- fs/netfs/direct_read.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
fs/netfs/direct_read.c +3 -3
@@ -125,9 +125,9 @@ static int netfs_dispatch_unbuffered_reads(struct netfs_io_request *rreq)* Perform a read to an application buffer, bypassing the pagecache and the * local disk cache. */ -static int netfs_unbuffered_read (struct netfs_io_request *rreq,bool sync) +static ssize_t netfs_unbuffered_read (struct netfs_io_request *rreq,bool sync) { -int ret; +ssize_t ret;_enter ("R=%x %llx-%llx" , rreq->debug_id, rreq->start, rreq->start + rreq->len -1 );
@@ -155,7 +155,7 @@ static int netfs_unbuffered_read(struct netfs_io_request *rreq, bool sync)else ret = -EIOCBQUEUED ; out: -_leave (" = %d" , ret); +_leave (" = %zd" , ret);return ret; }
Quoted 27 lines · David Howells
Hi Christian,
Here are some miscellaneous fixes and changes for netfslib, if you could pull them:
(1) Fix the collection of results during a pause in transmission.
(2) Call ->invalidate_cache() only if provided.
(3) Fix the rolling buffer to not hammer atomic bit clears when loading from readahead.
(4) Fix
netfs_unbuffered_read()to returnssize_t.The patches can also be found here:
https://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git/log/?h=netfs-fixes
Thanks,
DavidDavid Howells (3):
netfs: Fix collection of results during pause when collection
offloaded
netfs: Fixrolling_buffer_load_from_ra()to not clear mark bits
netfs: Fixnetfs_unbuffered_read()to returnssize_trather than int
Quoted 8 lines
Max Kellermann (1):
netfs: Callinvalidate_cacheonly if implementedfs/netfs/direct_read.c | 6 +++--- fs/netfs/read_collect.c | 18 ++++++++++-------- fs/netfs/rolling_buffer.c | 4 ---- fs/netfs/write_collect.c | 3 ++- 4 files changed, 15 insertions(+), 16 deletions(-)
Quoted 8 lines · David Howells
Here are some miscellaneous fixes and changes for netfslib, if you could pull them:
(1) Fix the collection of results during a pause in transmission.
(2) Call ->invalidate_cache() only if provided.
[...]
Applied to the vfs.fixes branch of the vfs/vfs.git tree. Patches in the vfs.fixes branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase, trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git branch: vfs.fixes
[1/4] netfs: Fix collection of results during pause when collection offloaded
https://git.kernel.org/vfs/vfs/c/f298e3765528 [2/4] netfs: Call `invalidate_cache` only if implemented https://git.kernel.org/vfs/vfs/c/344b7ef248f4 [3/4] netfs: Fix rolling_buffer_load_from_ra() to not clear mark bits https://git.kernel.org/vfs/vfs/c/15e9aaf9fc49 [4/4] netfs: Fix netfs_unbuffered_read() to return ssize_t rather than int https://git.kernel.org/vfs/vfs/c/07c574eb53d4