]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
netfs: Drop the error arg from netfs_read_subreq_terminated()
authorDavid Howells <dhowells@redhat.com>
Mon, 16 Dec 2024 20:40:58 +0000 (20:40 +0000)
committerChristian Brauner <brauner@kernel.org>
Fri, 20 Dec 2024 21:34:03 +0000 (22:34 +0100)
Drop the error argument from netfs_read_subreq_terminated() in favour of
passing the value in subreq->error.

Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/r/20241216204124.3752367-9-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>
12 files changed:
fs/9p/vfs_addr.c
fs/afs/file.c
fs/ceph/addr.c
fs/netfs/buffered_read.c
fs/netfs/objects.c
fs/netfs/read_collect.c
fs/nfs/fscache.c
fs/nfs/fscache.h
fs/smb/client/cifssmb.c
fs/smb/client/file.c
fs/smb/client/smb2pdu.c
include/linux/netfs.h

index 3bc9ce6c575e502208f88f5f982077feca17e571..40f5acd7b4527ef7cbe97a14d7b58ca353c140f6 100644 (file)
@@ -87,7 +87,8 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq)
                __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
        }
 
-       netfs_read_subreq_terminated(subreq, err, false);
+       subreq->error = err;
+       netfs_read_subreq_terminated(subreq, false);
 }
 
 /**
index 6762eff9751722c3950f1a90df1de515887b0fb4..56248a078bcaa61ffd39f920368969ff431833e1 100644 (file)
@@ -246,7 +246,8 @@ static void afs_fetch_data_notify(struct afs_operation *op)
                subreq->rreq->i_size = req->file_size;
                if (req->pos + req->actual_len >= req->file_size)
                        __set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags);
-               netfs_read_subreq_terminated(subreq, error, false);
+               subreq->error = error;
+               netfs_read_subreq_terminated(subreq, false);
                req->subreq = NULL;
        } else if (req->done) {
                req->done(req);
@@ -301,8 +302,10 @@ int afs_fetch_data(struct afs_vnode *vnode, struct afs_read *req)
 
        op = afs_alloc_operation(req->key, vnode->volume);
        if (IS_ERR(op)) {
-               if (req->subreq)
-                       netfs_read_subreq_terminated(req->subreq, PTR_ERR(op), false);
+               if (req->subreq) {
+                       req->subreq->error = PTR_ERR(op);
+                       netfs_read_subreq_terminated(req->subreq, false);
+               }
                return PTR_ERR(op);
        }
 
@@ -320,8 +323,10 @@ static void afs_read_worker(struct work_struct *work)
        struct afs_read *fsreq;
 
        fsreq = afs_alloc_read(GFP_NOFS);
-       if (!fsreq)
-               return netfs_read_subreq_terminated(subreq, -ENOMEM, false);
+       if (!fsreq) {
+               subreq->error = -ENOMEM;
+               return netfs_read_subreq_terminated(subreq, false);
+       }
 
        fsreq->subreq   = subreq;
        fsreq->pos      = subreq->start + subreq->transferred;
index 85936f6d2bf705d6585535462d94fceb57786273..b1b47af94deb04bfe01b54d316c028e8b7b0bf2d 100644 (file)
@@ -253,8 +253,9 @@ static void finish_netfs_read(struct ceph_osd_request *req)
                subreq->transferred = err;
                err = 0;
        }
+       subreq->error = err;
        trace_netfs_sreq(subreq, netfs_sreq_trace_io_progress);
-       netfs_read_subreq_terminated(subreq, err, false);
+       netfs_read_subreq_terminated(subreq, false);
        iput(req->r_inode);
        ceph_dec_osd_stopping_blocker(fsc->mdsc);
 }
@@ -314,7 +315,9 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq)
 
        ceph_mdsc_put_request(req);
 out:
-       netfs_read_subreq_terminated(subreq, err, false);
+       subreq->error = err;
+       trace_netfs_sreq(subreq, netfs_sreq_trace_io_progress);
+       netfs_read_subreq_terminated(subreq, false);
        return true;
 }
 
@@ -426,8 +429,10 @@ static void ceph_netfs_issue_read(struct netfs_io_subrequest *subreq)
        ceph_osdc_start_request(req->r_osdc, req);
 out:
        ceph_osdc_put_request(req);
-       if (err)
-               netfs_read_subreq_terminated(subreq, err, false);
+       if (err) {
+               subreq->error = err;
+               netfs_read_subreq_terminated(subreq, false);
+       }
        doutc(cl, "%llx.%llx result %d\n", ceph_vinop(inode), err);
 }
 
index db874fea87946bdc2a72371f616b7a8f42a3a13d..d420d623711c8ae01c29bda93675ba97f6b917fb 100644 (file)
@@ -148,14 +148,13 @@ static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or_error
 {
        struct netfs_io_subrequest *subreq = priv;
 
-       if (transferred_or_error < 0) {
-               netfs_read_subreq_terminated(subreq, transferred_or_error, was_async);
-               return;
-       }
-
-       if (transferred_or_error > 0)
+       if (transferred_or_error > 0) {
                subreq->transferred += transferred_or_error;
-       netfs_read_subreq_terminated(subreq, 0, was_async);
+               subreq->error = 0;
+       } else {
+               subreq->error = transferred_or_error;
+       }
+       netfs_read_subreq_terminated(subreq, was_async);
 }
 
 /*
@@ -255,7 +254,8 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
                        if (slice < 0)
                                goto prep_iter_failed;
                        __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
-                       netfs_read_subreq_terminated(subreq, 0, false);
+                       subreq->error = 0;
+                       netfs_read_subreq_terminated(subreq, false);
                        goto done;
                }
 
index 5cdddaf1f97884ab9b8527ac312a335e70f931e4..f10fd56efa1779c4dea5b53d5fc0d0953e8c1847 100644 (file)
@@ -191,7 +191,20 @@ struct netfs_io_subrequest *netfs_alloc_subrequest(struct netfs_io_request *rreq
        }
 
        memset(subreq, 0, kmem_cache_size(cache));
-       INIT_WORK(&subreq->work, NULL);
+
+       switch (rreq->origin) {
+       case NETFS_READAHEAD:
+       case NETFS_READPAGE:
+       case NETFS_READ_GAPS:
+       case NETFS_READ_FOR_WRITE:
+       case NETFS_DIO_READ:
+               INIT_WORK(&subreq->work, netfs_read_subreq_termination_worker);
+               break;
+       default:
+               INIT_WORK(&subreq->work, NULL);
+               break;
+       }
+
        INIT_LIST_HEAD(&subreq->rreq_link);
        refcount_set(&subreq->ref, 2);
        subreq->rreq = rreq;
index f7a5cb29dd12668d66098a860b013bd5850e63aa..16770a317b2244b291b2c3d2122d858396524369 100644 (file)
@@ -452,28 +452,26 @@ 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.
- * @error: Error code indicating type of completion.
- * @was_async: The termination was asynchronous
+ * @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.
  *
- * The caller indicates the outcome of the operation through @error, supplying
- * 0 to indicate a successful or retryable transfer (if NETFS_SREQ_NEED_RETRY
- * is set) or a negative error code.  The helper will look after reissuing I/O
- * operations as appropriate and writing downloaded data to the cache.
+ * The caller indicates the outcome of the operation through @subreq->error,
+ * supplying 0 to indicate a successful or retryable transfer (if
+ * NETFS_SREQ_NEED_RETRY is set) or a negative error code.  The helper will
+ * look after reissuing I/O operations as appropriate and writing downloaded
+ * data to the cache.
  *
  * 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_terminated(struct netfs_io_subrequest *subreq,
-                                 int error, bool was_async)
+void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, bool was_async)
 {
        struct netfs_io_request *rreq = subreq->rreq;
 
+       might_sleep();
+
        switch (subreq->source) {
        case NETFS_READ_FROM_CACHE:
                netfs_stat(&netfs_n_rh_read_done);
@@ -491,7 +489,7 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq,
                 * If the read completed validly short, then we can clear the
                 * tail before going on to unlock the folios.
                 */
-               if (error == 0 && subreq->transferred < subreq->len &&
+               if (subreq->error == 0 && subreq->transferred < subreq->len &&
                    (test_bit(NETFS_SREQ_HIT_EOF, &subreq->flags) ||
                     test_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags))) {
                        netfs_clear_unread(subreq);
@@ -511,7 +509,7 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq,
        /* Deal with retry requests, short reads and errors.  If we retry
         * but don't make progress, we abandon the attempt.
         */
-       if (!error && subreq->transferred < subreq->len) {
+       if (!subreq->error && subreq->transferred < subreq->len) {
                if (test_bit(NETFS_SREQ_HIT_EOF, &subreq->flags)) {
                        trace_netfs_sreq(subreq, netfs_sreq_trace_hit_eof);
                } else {
@@ -528,16 +526,15 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq,
                                set_bit(NETFS_RREQ_NEED_RETRY, &rreq->flags);
                        } else {
                                __set_bit(NETFS_SREQ_FAILED, &subreq->flags);
-                               error = -ENODATA;
+                               subreq->error = -ENODATA;
                        }
                }
        }
 
-       subreq->error = error;
        trace_netfs_sreq(subreq, netfs_sreq_trace_terminated);
 
-       if (unlikely(error < 0)) {
-               trace_netfs_failure(rreq, subreq, error, netfs_fail_read);
+       if (unlikely(subreq->error < 0)) {
+               trace_netfs_failure(rreq, subreq, subreq->error, netfs_fail_read);
                if (subreq->source == NETFS_READ_FROM_CACHE) {
                        netfs_stat(&netfs_n_rh_read_failed);
                } else {
@@ -553,3 +550,19 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq,
        netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated);
 }
 EXPORT_SYMBOL(netfs_read_subreq_terminated);
+
+/**
+ * netfs_read_subreq_termination_worker - Workqueue helper for read termination
+ * @work: The subreq->work in the I/O request that has been terminated.
+ *
+ * Helper function to jump to netfs_read_subreq_terminated() from the
+ * subrequest work item.
+ */
+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);
+}
+EXPORT_SYMBOL(netfs_read_subreq_termination_worker);
index d49e4ce279994f6b46cba98ae2e38e76a561458c..be14d30608f6d57545c4ac41d8911ed21dd9f3b8 100644 (file)
@@ -314,8 +314,10 @@ static void nfs_netfs_issue_read(struct netfs_io_subrequest *sreq)
                             &nfs_async_read_completion_ops);
 
        netfs = nfs_netfs_alloc(sreq);
-       if (!netfs)
-               return netfs_read_subreq_terminated(sreq, -ENOMEM, false);
+       if (!netfs) {
+               sreq->error = -ENOMEM;
+               return netfs_read_subreq_terminated(sreq, false);
+       }
 
        pgio.pg_netfs = netfs; /* used in completion */
 
index 772d485e96d35a11e6a05cb7341213cc725a8bcc..1d86f7cc719507d37607810cb8bc3e13585e5acc 100644 (file)
@@ -74,7 +74,8 @@ 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_read_subreq_terminated(netfs->sreq, netfs->error, false);
+       netfs->sreq->error = netfs->error;
+       netfs_read_subreq_terminated(netfs->sreq, false);
        kfree(netfs);
 }
 static inline void nfs_netfs_inode_init(struct nfs_inode *nfsi)
index 6cb1e81993f89bf695f034bb8d7d4928bd6f4fc3..7c9cc6945d182974e610bca40478b6772ee5a977 100644 (file)
@@ -1258,14 +1258,6 @@ openRetry:
        return rc;
 }
 
-static void cifs_readv_worker(struct work_struct *work)
-{
-       struct cifs_io_subrequest *rdata =
-               container_of(work, struct cifs_io_subrequest, subreq.work);
-
-       netfs_read_subreq_terminated(&rdata->subreq, rdata->result, false);
-}
-
 static void
 cifs_readv_callback(struct mid_q_entry *mid)
 {
@@ -1333,8 +1325,8 @@ cifs_readv_callback(struct mid_q_entry *mid)
        }
 
        rdata->credits.value = 0;
+       rdata->subreq.error = rdata->result;
        rdata->subreq.transferred += rdata->got_bytes;
-       INIT_WORK(&rdata->subreq.work, cifs_readv_worker);
        queue_work(cifsiod_wq, &rdata->subreq.work);
        release_mid(mid);
        add_credits(server, &credits, 0);
index a58a3333ecc300ab1974c9ea85ab637af81d64e1..10dd440f8178ab0dfba9762f79de4f6c5ebcc8e8 100644 (file)
@@ -227,7 +227,8 @@ static void cifs_issue_read(struct netfs_io_subrequest *subreq)
        return;
 
 failed:
-       netfs_read_subreq_terminated(subreq, rc, false);
+       subreq->error = rc;
+       netfs_read_subreq_terminated(subreq, false);
 }
 
 /*
index 458b53d1f9cb8d46aec9b68ca7f487e2942e38e2..ce57d8697c7ce16371ff86c33aa902af4f3277f4 100644 (file)
@@ -4500,14 +4500,6 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
        return rc;
 }
 
-static void smb2_readv_worker(struct work_struct *work)
-{
-       struct cifs_io_subrequest *rdata =
-               container_of(work, struct cifs_io_subrequest, subreq.work);
-
-       netfs_read_subreq_terminated(&rdata->subreq, rdata->result, false);
-}
-
 static void
 smb2_readv_callback(struct mid_q_entry *mid)
 {
@@ -4621,9 +4613,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
                              server->credits, server->in_flight,
                              0, cifs_trace_rw_credits_read_response_clear);
        rdata->credits.value = 0;
+       rdata->subreq.error = rdata->result;
        rdata->subreq.transferred += rdata->got_bytes;
        trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress);
-       INIT_WORK(&rdata->subreq.work, smb2_readv_worker);
        queue_work(cifsiod_wq, &rdata->subreq.work);
        release_mid(mid);
        trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0,
index bd922f0936e34881047550bfa4e66867665594ab..a882921460a93e0b6d76a0b5c3485c7f8bf335a1 100644 (file)
@@ -427,10 +427,9 @@ 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,
-                                 int error, bool was_async);
+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_termination_worker(struct work_struct *work);
 void netfs_get_subrequest(struct netfs_io_subrequest *subreq,
                          enum netfs_sreq_ref_trace what);
 void netfs_put_subrequest(struct netfs_io_subrequest *subreq,