]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfs: Drop the was_async arg from netfs_read_subreq_terminated()
authorDavid Howells <dhowells@redhat.com>
Mon, 16 Dec 2024 20:40:59 +0000 (20:40 +0000)
committerChristian Brauner <brauner@kernel.org>
Fri, 20 Dec 2024 21:34:03 +0000 (22:34 +0100)
Drop the was_async argument from netfs_read_subreq_terminated().  Almost
every caller is either in process context and passes false.  Some
filesystems delegate the call to a workqueue to avoid doing the work in
their network message queue parsing thread.

The only exception is netfs_cache_read_terminated() which handles
completion in the cache - which is usually a callback from the backing
filesystem in softirq context, though it can be from process context if an
error occurred.  In this case, delegate to a workqueue.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/CAHk-=wiVC5Cgyz6QKXFu6fTaA6h4CjexDR-OV9kL6Vo5x9v8=A@mail.gmail.com/
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/r/20241216204124.3752367-10-dhowells@redhat.com
cc: Jeff Layton <jlayton@kernel.org>
cc: netfs@lists.linux.dev
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
15 files changed:
fs/9p/vfs_addr.c
fs/afs/file.c
fs/afs/fsclient.c
fs/afs/yfsclient.c
fs/ceph/addr.c
fs/netfs/buffered_read.c
fs/netfs/direct_read.c
fs/netfs/internal.h
fs/netfs/objects.c
fs/netfs/read_collect.c
fs/netfs/read_retry.c
fs/nfs/fscache.c
fs/nfs/fscache.h
fs/smb/client/file.c
include/linux/netfs.h

index 40f5acd7b4527ef7cbe97a14d7b58ca353c140f6..b38be6ff90bc16e53c27d5b2dfc3f0c1f2a682fa 100644 (file)
@@ -88,7 +88,7 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq)
        }
 
        subreq->error = err;
-       netfs_read_subreq_terminated(subreq, false);
+       netfs_read_subreq_terminated(subreq);
 }
 
 /**
index 56248a078bcaa61ffd39f920368969ff431833e1..f717168da4abb349136c183c2c2973cbdf571f09 100644 (file)
@@ -247,7 +247,7 @@ static void afs_fetch_data_notify(struct afs_operation *op)
                if (req->pos + req->actual_len >= req->file_size)
                        __set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags);
                subreq->error = error;
-               netfs_read_subreq_terminated(subreq, false);
+               netfs_read_subreq_terminated(subreq);
                req->subreq = NULL;
        } else if (req->done) {
                req->done(req);
@@ -304,7 +304,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct afs_read *req)
        if (IS_ERR(op)) {
                if (req->subreq) {
                        req->subreq->error = PTR_ERR(op);
-                       netfs_read_subreq_terminated(req->subreq, false);
+                       netfs_read_subreq_terminated(req->subreq);
                }
                return PTR_ERR(op);
        }
@@ -325,7 +325,7 @@ static void afs_read_worker(struct work_struct *work)
        fsreq = afs_alloc_read(GFP_NOFS);
        if (!fsreq) {
                subreq->error = -ENOMEM;
-               return netfs_read_subreq_terminated(subreq, false);
+               return netfs_read_subreq_terminated(subreq);
        }
 
        fsreq->subreq   = subreq;
index 098fa034a1ccb4514b07a4bf8586de7981f9c9a6..784f7daab112c4043bb4d378ade9106b389144aa 100644 (file)
@@ -352,7 +352,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                ret = afs_extract_data(call, true);
                if (req->subreq) {
                        req->subreq->transferred += count_before - call->iov_len;
-                       netfs_read_subreq_progress(req->subreq, false);
+                       netfs_read_subreq_progress(req->subreq);
                }
                if (ret < 0)
                        return ret;
index 024227aba4cd5f42a84df8297a2aae1b36089e8e..368cf277d80121f50306220d43a3683928b67e95 100644 (file)
@@ -398,7 +398,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call)
                ret = afs_extract_data(call, true);
                if (req->subreq) {
                        req->subreq->transferred += count_before - call->iov_len;
-                       netfs_read_subreq_progress(req->subreq, false);
+                       netfs_read_subreq_progress(req->subreq);
                }
                if (ret < 0)
                        return ret;
index b1b47af94deb04bfe01b54d316c028e8b7b0bf2d..4deb38fa470ebc8ee0036f8ee3c89cfae98d8164 100644 (file)
@@ -255,7 +255,7 @@ static void finish_netfs_read(struct ceph_osd_request *req)
        }
        subreq->error = err;
        trace_netfs_sreq(subreq, netfs_sreq_trace_io_progress);
-       netfs_read_subreq_terminated(subreq, false);
+       netfs_read_subreq_terminated(subreq);
        iput(req->r_inode);
        ceph_dec_osd_stopping_blocker(fsc->mdsc);
 }
@@ -317,7 +317,7 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq)
 out:
        subreq->error = err;
        trace_netfs_sreq(subreq, netfs_sreq_trace_io_progress);
-       netfs_read_subreq_terminated(subreq, false);
+       netfs_read_subreq_terminated(subreq);
        return true;
 }
 
@@ -431,7 +431,7 @@ out:
        ceph_osdc_put_request(req);
        if (err) {
                subreq->error = err;
-               netfs_read_subreq_terminated(subreq, false);
+               netfs_read_subreq_terminated(subreq);
        }
        doutc(cl, "%llx.%llx result %d\n", ceph_vinop(inode), err);
 }
index d420d623711c8ae01c29bda93675ba97f6b917fb..fa1013020ac91c0d3a8ebe6c138f7d2c3f9def7a 100644 (file)
@@ -154,7 +154,7 @@ static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or_error
        } else {
                subreq->error = transferred_or_error;
        }
-       netfs_read_subreq_terminated(subreq, was_async);
+       schedule_work(&subreq->work);
 }
 
 /*
@@ -255,7 +255,7 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
                                goto prep_iter_failed;
                        __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
                        subreq->error = 0;
-                       netfs_read_subreq_terminated(subreq, false);
+                       netfs_read_subreq_terminated(subreq);
                        goto done;
                }
 
@@ -287,7 +287,7 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
        } while (size > 0);
 
        if (atomic_dec_and_test(&rreq->nr_outstanding))
-               netfs_rreq_terminated(rreq, false);
+               netfs_rreq_terminated(rreq);
 
        /* Defer error return as we may need to wait for outstanding I/O. */
        cmpxchg(&rreq->error, 0, ret);
index a3f23adbae0f6f46e09fdd40c6013907ef34ec58..54027fd149040e33e24ff7988d64f66bce535ba3 100644 (file)
@@ -100,7 +100,7 @@ static int netfs_dispatch_unbuffered_reads(struct netfs_io_request *rreq)
        } while (size > 0);
 
        if (atomic_dec_and_test(&rreq->nr_outstanding))
-               netfs_rreq_terminated(rreq, false);
+               netfs_rreq_terminated(rreq);
        return ret;
 }
 
index 73887525e939a2b196905243b6af3fdced75ca76..ba32ca61063c0eceab40dfd891a560200a4d1aca 100644 (file)
@@ -85,7 +85,7 @@ static inline void netfs_see_request(struct netfs_io_request *rreq,
  * read_collect.c
  */
 void netfs_read_termination_worker(struct work_struct *work);
-void netfs_rreq_terminated(struct netfs_io_request *rreq, bool was_async);
+void netfs_rreq_terminated(struct netfs_io_request *rreq);
 
 /*
  * read_pgpriv2.c
index f10fd56efa1779c4dea5b53d5fc0d0953e8c1847..8c98b70eb3a4f5e38c7c4ec3fd7976446908e878 100644 (file)
@@ -56,7 +56,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping,
            origin == NETFS_READ_GAPS ||
            origin == NETFS_READ_FOR_WRITE ||
            origin == NETFS_DIO_READ)
-               INIT_WORK(&rreq->work, netfs_read_termination_worker);
+               INIT_WORK(&rreq->work, NULL);
        else
                INIT_WORK(&rreq->work, netfs_write_collection_worker);
 
index 16770a317b2244b291b2c3d2122d858396524369..454a5bbdd6f872dd8ec0018f1062a7ad18a33fae 100644 (file)
@@ -87,7 +87,7 @@ static void netfs_unlock_read_folio(struct netfs_io_subrequest *subreq,
  * Unlock any folios that are now completely read.  Returns true if the
  * subrequest is removed from the list.
  */
-static bool netfs_consume_read_data(struct netfs_io_subrequest *subreq, bool was_async)
+static bool netfs_consume_read_data(struct netfs_io_subrequest *subreq)
 {
        struct netfs_io_subrequest *prev, *next;
        struct netfs_io_request *rreq = subreq->rreq;
@@ -230,8 +230,7 @@ donation_changed:
                subreq->curr_folioq_slot = slot;
                if (folioq && folioq_folio(folioq, slot))
                        subreq->curr_folio_order = folioq->orders[slot];
-               if (!was_async)
-                       cond_resched();
+               cond_resched();
                goto next_folio;
        }
 
@@ -368,7 +367,7 @@ static void netfs_rreq_assess_dio(struct netfs_io_request *rreq)
  * Note that we're in normal kernel thread context at this point, possibly
  * running on a workqueue.
  */
-static void netfs_rreq_assess(struct netfs_io_request *rreq)
+void netfs_rreq_terminated(struct netfs_io_request *rreq)
 {
        trace_netfs_rreq(rreq, netfs_rreq_trace_assess);
 
@@ -394,56 +393,29 @@ static void netfs_rreq_assess(struct netfs_io_request *rreq)
                netfs_pgpriv2_write_to_the_cache(rreq);
 }
 
-void netfs_read_termination_worker(struct work_struct *work)
-{
-       struct netfs_io_request *rreq =
-               container_of(work, struct netfs_io_request, work);
-       netfs_see_request(rreq, netfs_rreq_trace_see_work);
-       netfs_rreq_assess(rreq);
-       netfs_put_request(rreq, false, netfs_rreq_trace_put_work_complete);
-}
-
-/*
- * Handle the completion of all outstanding I/O operations on a read request.
- * We inherit a ref from the caller.
- */
-void netfs_rreq_terminated(struct netfs_io_request *rreq, bool was_async)
-{
-       if (!was_async)
-               return netfs_rreq_assess(rreq);
-       if (!work_pending(&rreq->work)) {
-               netfs_get_request(rreq, netfs_rreq_trace_get_work);
-               if (!queue_work(system_unbound_wq, &rreq->work))
-                       netfs_put_request(rreq, was_async, netfs_rreq_trace_put_work_nq);
-       }
-}
-
 /**
  * netfs_read_subreq_progress - Note progress of a read operation.
  * @subreq: The read request that has terminated.
- * @was_async: True if we're in an asynchronous context.
  *
  * This tells the read side of netfs lib that a contributory I/O operation has
  * made some progress and that it may be possible to unlock some folios.
  *
  * Before calling, the filesystem should update subreq->transferred to track
  * the amount of data copied into the output buffer.
- *
- * If @was_async is true, the caller might be running in softirq or interrupt
- * context and we can't sleep.
  */
-void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq,
-                               bool was_async)
+void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq)
 {
        struct netfs_io_request *rreq = subreq->rreq;
 
+       might_sleep();
+
        trace_netfs_sreq(subreq, netfs_sreq_trace_progress);
 
        if (subreq->transferred > subreq->consumed &&
            (rreq->origin == NETFS_READAHEAD ||
             rreq->origin == NETFS_READPAGE ||
             rreq->origin == NETFS_READ_FOR_WRITE)) {
-               netfs_consume_read_data(subreq, was_async);
+               netfs_consume_read_data(subreq);
                __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
        }
 }
@@ -452,7 +424,6 @@ EXPORT_SYMBOL(netfs_read_subreq_progress);
 /**
  * netfs_read_subreq_terminated - Note the termination of an I/O operation.
  * @subreq: The I/O request that has terminated.
- * @was_async: True if we're in an asynchronous context.
  *
  * This tells the read helper that a contributory I/O operation has terminated,
  * one way or another, and that it should integrate the results.
@@ -466,7 +437,7 @@ EXPORT_SYMBOL(netfs_read_subreq_progress);
  * Before calling, the filesystem should update subreq->transferred to track
  * the amount of data copied into the output buffer.
  */
-void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, bool was_async)
+void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq)
 {
        struct netfs_io_request *rreq = subreq->rreq;
 
@@ -500,7 +471,7 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, bool was_a
                    (rreq->origin == NETFS_READAHEAD ||
                     rreq->origin == NETFS_READPAGE ||
                     rreq->origin == NETFS_READ_FOR_WRITE)) {
-                       netfs_consume_read_data(subreq, was_async);
+                       netfs_consume_read_data(subreq);
                        __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
                }
                rreq->transferred += subreq->transferred;
@@ -545,9 +516,9 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, bool was_a
        }
 
        if (atomic_dec_and_test(&rreq->nr_outstanding))
-               netfs_rreq_terminated(rreq, was_async);
+               netfs_rreq_terminated(rreq);
 
-       netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated);
+       netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_terminated);
 }
 EXPORT_SYMBOL(netfs_read_subreq_terminated);
 
@@ -563,6 +534,6 @@ void netfs_read_subreq_termination_worker(struct work_struct *work)
        struct netfs_io_subrequest *subreq =
                container_of(work, struct netfs_io_subrequest, work);
 
-       netfs_read_subreq_terminated(subreq, false);
+       netfs_read_subreq_terminated(subreq);
 }
 EXPORT_SYMBOL(netfs_read_subreq_termination_worker);
index 0983234c2183fc7dfa7b5141385e0a0657bd4740..a2021efa44c0fe21c6bdb344896f74148e514ae2 100644 (file)
@@ -234,7 +234,7 @@ void netfs_retry_reads(struct netfs_io_request *rreq)
        netfs_retry_read_subrequests(rreq);
 
        if (atomic_dec_and_test(&rreq->nr_outstanding))
-               netfs_rreq_terminated(rreq, false);
+               netfs_rreq_terminated(rreq);
 }
 
 /*
index be14d30608f6d57545c4ac41d8911ed21dd9f3b8..e278a1ad1ca3e8a0f7aacb505a272d6c2602bc7a 100644 (file)
@@ -316,7 +316,7 @@ static void nfs_netfs_issue_read(struct netfs_io_subrequest *sreq)
        netfs = nfs_netfs_alloc(sreq);
        if (!netfs) {
                sreq->error = -ENOMEM;
-               return netfs_read_subreq_terminated(sreq, false);
+               return netfs_read_subreq_terminated(sreq);
        }
 
        pgio.pg_netfs = netfs; /* used in completion */
index 1d86f7cc719507d37607810cb8bc3e13585e5acc..9d86868f49984e8cdc302e471d4203291bbfc259 100644 (file)
@@ -75,7 +75,7 @@ static inline void nfs_netfs_put(struct nfs_netfs_io_data *netfs)
        netfs->sreq->transferred = min_t(s64, netfs->sreq->len,
                                         atomic64_read(&netfs->transferred));
        netfs->sreq->error = netfs->error;
-       netfs_read_subreq_terminated(netfs->sreq, false);
+       netfs_read_subreq_terminated(netfs->sreq);
        kfree(netfs);
 }
 static inline void nfs_netfs_inode_init(struct nfs_inode *nfsi)
index 10dd440f8178ab0dfba9762f79de4f6c5ebcc8e8..27a1757a278e2916903eb67f19f54a53dc605532 100644 (file)
@@ -228,7 +228,7 @@ static void cifs_issue_read(struct netfs_io_subrequest *subreq)
 
 failed:
        subreq->error = rc;
-       netfs_read_subreq_terminated(subreq, false);
+       netfs_read_subreq_terminated(subreq);
 }
 
 /*
index a882921460a93e0b6d76a0b5c3485c7f8bf335a1..374e54beacbef818d815a82af4dd2b64cd1d291a 100644 (file)
@@ -427,8 +427,8 @@ bool netfs_release_folio(struct folio *folio, gfp_t gfp);
 vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group);
 
 /* (Sub)request management API. */
-void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq, bool was_async);
-void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, bool was_async);
+void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq);
+void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq);
 void netfs_read_subreq_termination_worker(struct work_struct *work);
 void netfs_get_subrequest(struct netfs_io_subrequest *subreq,
                          enum netfs_sreq_ref_trace what);