Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfs: Drop the error arg from netfs_read_subreq_terminated()

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>

authored by

David Howells and committed by
Christian Brauner
36015782 751e213f

+86 -62
+2 -1
fs/9p/vfs_addr.c
··· 87 87 __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); 88 88 } 89 89 90 - netfs_read_subreq_terminated(subreq, err, false); 90 + subreq->error = err; 91 + netfs_read_subreq_terminated(subreq, false); 91 92 } 92 93 93 94 /**
+10 -5
fs/afs/file.c
··· 246 246 subreq->rreq->i_size = req->file_size; 247 247 if (req->pos + req->actual_len >= req->file_size) 248 248 __set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags); 249 - netfs_read_subreq_terminated(subreq, error, false); 249 + subreq->error = error; 250 + netfs_read_subreq_terminated(subreq, false); 250 251 req->subreq = NULL; 251 252 } else if (req->done) { 252 253 req->done(req); ··· 302 301 303 302 op = afs_alloc_operation(req->key, vnode->volume); 304 303 if (IS_ERR(op)) { 305 - if (req->subreq) 306 - netfs_read_subreq_terminated(req->subreq, PTR_ERR(op), false); 304 + if (req->subreq) { 305 + req->subreq->error = PTR_ERR(op); 306 + netfs_read_subreq_terminated(req->subreq, false); 307 + } 307 308 return PTR_ERR(op); 308 309 } 309 310 ··· 323 320 struct afs_read *fsreq; 324 321 325 322 fsreq = afs_alloc_read(GFP_NOFS); 326 - if (!fsreq) 327 - return netfs_read_subreq_terminated(subreq, -ENOMEM, false); 323 + if (!fsreq) { 324 + subreq->error = -ENOMEM; 325 + return netfs_read_subreq_terminated(subreq, false); 326 + } 328 327 329 328 fsreq->subreq = subreq; 330 329 fsreq->pos = subreq->start + subreq->transferred;
+9 -4
fs/ceph/addr.c
··· 253 253 subreq->transferred = err; 254 254 err = 0; 255 255 } 256 + subreq->error = err; 256 257 trace_netfs_sreq(subreq, netfs_sreq_trace_io_progress); 257 - netfs_read_subreq_terminated(subreq, err, false); 258 + netfs_read_subreq_terminated(subreq, false); 258 259 iput(req->r_inode); 259 260 ceph_dec_osd_stopping_blocker(fsc->mdsc); 260 261 } ··· 315 314 316 315 ceph_mdsc_put_request(req); 317 316 out: 318 - netfs_read_subreq_terminated(subreq, err, false); 317 + subreq->error = err; 318 + trace_netfs_sreq(subreq, netfs_sreq_trace_io_progress); 319 + netfs_read_subreq_terminated(subreq, false); 319 320 return true; 320 321 } 321 322 ··· 429 426 ceph_osdc_start_request(req->r_osdc, req); 430 427 out: 431 428 ceph_osdc_put_request(req); 432 - if (err) 433 - netfs_read_subreq_terminated(subreq, err, false); 429 + if (err) { 430 + subreq->error = err; 431 + netfs_read_subreq_terminated(subreq, false); 432 + } 434 433 doutc(cl, "%llx.%llx result %d\n", ceph_vinop(inode), err); 435 434 } 436 435
+8 -8
fs/netfs/buffered_read.c
··· 148 148 { 149 149 struct netfs_io_subrequest *subreq = priv; 150 150 151 - if (transferred_or_error < 0) { 152 - netfs_read_subreq_terminated(subreq, transferred_or_error, was_async); 153 - return; 154 - } 155 - 156 - if (transferred_or_error > 0) 151 + if (transferred_or_error > 0) { 157 152 subreq->transferred += transferred_or_error; 158 - netfs_read_subreq_terminated(subreq, 0, was_async); 153 + subreq->error = 0; 154 + } else { 155 + subreq->error = transferred_or_error; 156 + } 157 + netfs_read_subreq_terminated(subreq, was_async); 159 158 } 160 159 161 160 /* ··· 254 255 if (slice < 0) 255 256 goto prep_iter_failed; 256 257 __set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags); 257 - netfs_read_subreq_terminated(subreq, 0, false); 258 + subreq->error = 0; 259 + netfs_read_subreq_terminated(subreq, false); 258 260 goto done; 259 261 } 260 262
+14 -1
fs/netfs/objects.c
··· 191 191 } 192 192 193 193 memset(subreq, 0, kmem_cache_size(cache)); 194 - INIT_WORK(&subreq->work, NULL); 194 + 195 + switch (rreq->origin) { 196 + case NETFS_READAHEAD: 197 + case NETFS_READPAGE: 198 + case NETFS_READ_GAPS: 199 + case NETFS_READ_FOR_WRITE: 200 + case NETFS_DIO_READ: 201 + INIT_WORK(&subreq->work, netfs_read_subreq_termination_worker); 202 + break; 203 + default: 204 + INIT_WORK(&subreq->work, NULL); 205 + break; 206 + } 207 + 195 208 INIT_LIST_HEAD(&subreq->rreq_link); 196 209 refcount_set(&subreq->ref, 2); 197 210 subreq->rreq = rreq;
+30 -17
fs/netfs/read_collect.c
··· 452 452 /** 453 453 * netfs_read_subreq_terminated - Note the termination of an I/O operation. 454 454 * @subreq: The I/O request that has terminated. 455 - * @error: Error code indicating type of completion. 456 - * @was_async: The termination was asynchronous 455 + * @was_async: True if we're in an asynchronous context. 457 456 * 458 457 * This tells the read helper that a contributory I/O operation has terminated, 459 458 * one way or another, and that it should integrate the results. 460 459 * 461 - * The caller indicates the outcome of the operation through @error, supplying 462 - * 0 to indicate a successful or retryable transfer (if NETFS_SREQ_NEED_RETRY 463 - * is set) or a negative error code. The helper will look after reissuing I/O 464 - * operations as appropriate and writing downloaded data to the cache. 460 + * The caller indicates the outcome of the operation through @subreq->error, 461 + * supplying 0 to indicate a successful or retryable transfer (if 462 + * NETFS_SREQ_NEED_RETRY is set) or a negative error code. The helper will 463 + * look after reissuing I/O operations as appropriate and writing downloaded 464 + * data to the cache. 465 465 * 466 466 * Before calling, the filesystem should update subreq->transferred to track 467 467 * the amount of data copied into the output buffer. 468 - * 469 - * If @was_async is true, the caller might be running in softirq or interrupt 470 - * context and we can't sleep. 471 468 */ 472 - void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, 473 - int error, bool was_async) 469 + void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, bool was_async) 474 470 { 475 471 struct netfs_io_request *rreq = subreq->rreq; 472 + 473 + might_sleep(); 476 474 477 475 switch (subreq->source) { 478 476 case NETFS_READ_FROM_CACHE: ··· 489 491 * If the read completed validly short, then we can clear the 490 492 * tail before going on to unlock the folios. 491 493 */ 492 - if (error == 0 && subreq->transferred < subreq->len && 494 + if (subreq->error == 0 && subreq->transferred < subreq->len && 493 495 (test_bit(NETFS_SREQ_HIT_EOF, &subreq->flags) || 494 496 test_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags))) { 495 497 netfs_clear_unread(subreq); ··· 509 511 /* Deal with retry requests, short reads and errors. If we retry 510 512 * but don't make progress, we abandon the attempt. 511 513 */ 512 - if (!error && subreq->transferred < subreq->len) { 514 + if (!subreq->error && subreq->transferred < subreq->len) { 513 515 if (test_bit(NETFS_SREQ_HIT_EOF, &subreq->flags)) { 514 516 trace_netfs_sreq(subreq, netfs_sreq_trace_hit_eof); 515 517 } else { ··· 526 528 set_bit(NETFS_RREQ_NEED_RETRY, &rreq->flags); 527 529 } else { 528 530 __set_bit(NETFS_SREQ_FAILED, &subreq->flags); 529 - error = -ENODATA; 531 + subreq->error = -ENODATA; 530 532 } 531 533 } 532 534 } 533 535 534 - subreq->error = error; 535 536 trace_netfs_sreq(subreq, netfs_sreq_trace_terminated); 536 537 537 - if (unlikely(error < 0)) { 538 - trace_netfs_failure(rreq, subreq, error, netfs_fail_read); 538 + if (unlikely(subreq->error < 0)) { 539 + trace_netfs_failure(rreq, subreq, subreq->error, netfs_fail_read); 539 540 if (subreq->source == NETFS_READ_FROM_CACHE) { 540 541 netfs_stat(&netfs_n_rh_read_failed); 541 542 } else { ··· 550 553 netfs_put_subrequest(subreq, was_async, netfs_sreq_trace_put_terminated); 551 554 } 552 555 EXPORT_SYMBOL(netfs_read_subreq_terminated); 556 + 557 + /** 558 + * netfs_read_subreq_termination_worker - Workqueue helper for read termination 559 + * @work: The subreq->work in the I/O request that has been terminated. 560 + * 561 + * Helper function to jump to netfs_read_subreq_terminated() from the 562 + * subrequest work item. 563 + */ 564 + void netfs_read_subreq_termination_worker(struct work_struct *work) 565 + { 566 + struct netfs_io_subrequest *subreq = 567 + container_of(work, struct netfs_io_subrequest, work); 568 + 569 + netfs_read_subreq_terminated(subreq, false); 570 + } 571 + EXPORT_SYMBOL(netfs_read_subreq_termination_worker);
+4 -2
fs/nfs/fscache.c
··· 314 314 &nfs_async_read_completion_ops); 315 315 316 316 netfs = nfs_netfs_alloc(sreq); 317 - if (!netfs) 318 - return netfs_read_subreq_terminated(sreq, -ENOMEM, false); 317 + if (!netfs) { 318 + sreq->error = -ENOMEM; 319 + return netfs_read_subreq_terminated(sreq, false); 320 + } 319 321 320 322 pgio.pg_netfs = netfs; /* used in completion */ 321 323
+2 -1
fs/nfs/fscache.h
··· 74 74 */ 75 75 netfs->sreq->transferred = min_t(s64, netfs->sreq->len, 76 76 atomic64_read(&netfs->transferred)); 77 - netfs_read_subreq_terminated(netfs->sreq, netfs->error, false); 77 + netfs->sreq->error = netfs->error; 78 + netfs_read_subreq_terminated(netfs->sreq, false); 78 79 kfree(netfs); 79 80 } 80 81 static inline void nfs_netfs_inode_init(struct nfs_inode *nfsi)
+1 -9
fs/smb/client/cifssmb.c
··· 1258 1258 return rc; 1259 1259 } 1260 1260 1261 - static void cifs_readv_worker(struct work_struct *work) 1262 - { 1263 - struct cifs_io_subrequest *rdata = 1264 - container_of(work, struct cifs_io_subrequest, subreq.work); 1265 - 1266 - netfs_read_subreq_terminated(&rdata->subreq, rdata->result, false); 1267 - } 1268 - 1269 1261 static void 1270 1262 cifs_readv_callback(struct mid_q_entry *mid) 1271 1263 { ··· 1325 1333 } 1326 1334 1327 1335 rdata->credits.value = 0; 1336 + rdata->subreq.error = rdata->result; 1328 1337 rdata->subreq.transferred += rdata->got_bytes; 1329 - INIT_WORK(&rdata->subreq.work, cifs_readv_worker); 1330 1338 queue_work(cifsiod_wq, &rdata->subreq.work); 1331 1339 release_mid(mid); 1332 1340 add_credits(server, &credits, 0);
+2 -1
fs/smb/client/file.c
··· 227 227 return; 228 228 229 229 failed: 230 - netfs_read_subreq_terminated(subreq, rc, false); 230 + subreq->error = rc; 231 + netfs_read_subreq_terminated(subreq, false); 231 232 } 232 233 233 234 /*
+1 -9
fs/smb/client/smb2pdu.c
··· 4500 4500 return rc; 4501 4501 } 4502 4502 4503 - static void smb2_readv_worker(struct work_struct *work) 4504 - { 4505 - struct cifs_io_subrequest *rdata = 4506 - container_of(work, struct cifs_io_subrequest, subreq.work); 4507 - 4508 - netfs_read_subreq_terminated(&rdata->subreq, rdata->result, false); 4509 - } 4510 - 4511 4503 static void 4512 4504 smb2_readv_callback(struct mid_q_entry *mid) 4513 4505 { ··· 4613 4621 server->credits, server->in_flight, 4614 4622 0, cifs_trace_rw_credits_read_response_clear); 4615 4623 rdata->credits.value = 0; 4624 + rdata->subreq.error = rdata->result; 4616 4625 rdata->subreq.transferred += rdata->got_bytes; 4617 4626 trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress); 4618 - INIT_WORK(&rdata->subreq.work, smb2_readv_worker); 4619 4627 queue_work(cifsiod_wq, &rdata->subreq.work); 4620 4628 release_mid(mid); 4621 4629 trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0,
+3 -4
include/linux/netfs.h
··· 427 427 vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group); 428 428 429 429 /* (Sub)request management API. */ 430 - void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq, 431 - bool was_async); 432 - void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, 433 - int error, bool was_async); 430 + void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq, bool was_async); 431 + void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq, bool was_async); 432 + void netfs_read_subreq_termination_worker(struct work_struct *work); 434 433 void netfs_get_subrequest(struct netfs_io_subrequest *subreq, 435 434 enum netfs_sreq_ref_trace what); 436 435 void netfs_put_subrequest(struct netfs_io_subrequest *subreq,