// SPDX-License-Identifier: GPL-2.0-or-later /* Network filesystem high-level read support. * * Copyright (C) 2021 Red Hat, Inc. All Rights Reserved. * Written by David Howells ([email protected]) */ #include <linux/module.h> #include <linux/export.h> #include <linux/fs.h> #include <linux/mm.h> #include <linux/pagemap.h> #include <linux/slab.h> #include <linux/uio.h> #include <linux/sched/mm.h> #include <linux/task_io_accounting_ops.h> #include "internal.h" /* * Clear the unread part of an I/O request. */ static void netfs_clear_unread(struct netfs_io_subrequest *subreq) { … } static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or_error, bool was_async) { … } /* * Issue a read against the cache. * - Eats the caller's ref on subreq. */ static void netfs_read_from_cache(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq, enum netfs_read_from_hole read_hole) { … } /* * Fill a subrequest region with zeroes. */ static void netfs_fill_with_zeroes(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq) { … } /* * Ask the netfs to issue a read request to the server for us. * * The netfs is expected to read from subreq->pos + subreq->transferred to * subreq->pos + subreq->len - 1. It may not backtrack and write data into the * buffer prior to the transferred point as it might clobber dirty data * obtained from the cache. * * Alternatively, the netfs is allowed to indicate one of two things: * * - NETFS_SREQ_SHORT_READ: A short read - it will get called again to try and * make progress. * * - NETFS_SREQ_CLEAR_TAIL: A short read - the rest of the buffer will be * cleared. */ static void netfs_read_from_server(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq) { … } /* * Release those waiting. */ static void netfs_rreq_completed(struct netfs_io_request *rreq, bool was_async) { … } /* * Handle a short read. */ static void netfs_rreq_short_read(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq) { … } /* * Reset the subrequest iterator prior to resubmission. */ static void netfs_reset_subreq_iter(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq) { … } /* * Resubmit any short or failed operations. Returns true if we got the rreq * ref back. */ static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq) { … } /* * Check to see if the data read is still valid. */ static void netfs_rreq_is_still_valid(struct netfs_io_request *rreq) { … } /* * Determine how much we can admit to having read from a DIO read. */ static void netfs_rreq_assess_dio(struct netfs_io_request *rreq) { … } /* * Assess the state of a read request and decide what to do next. * * Note that we could be in an ordinary kernel thread, on a workqueue or in * softirq context at this point. We inherit a ref from the caller. */ static void netfs_rreq_assess(struct netfs_io_request *rreq, bool was_async) { … } static void netfs_rreq_work(struct work_struct *work) { … } /* * Handle the completion of all outstanding I/O operations on a read request. * We inherit a ref from the caller. */ static void netfs_rreq_terminated(struct netfs_io_request *rreq, bool was_async) { … } /** * netfs_subreq_terminated - Note the termination of an I/O operation. * @subreq: The I/O request that has terminated. * @transferred_or_error: The amount of data transferred or an error code. * @was_async: The termination was asynchronous * * 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 in @transferred_or_error the outcome of the operation, * supplying a positive value to indicate the number of bytes transferred, 0 to * indicate a failure to transfer anything that should be retried or a negative * error code. The helper will look after reissuing I/O operations as * appropriate and writing downloaded data to the cache. * * If @was_async is true, the caller might be running in softirq or interrupt * context and we can't sleep. */ void netfs_subreq_terminated(struct netfs_io_subrequest *subreq, ssize_t transferred_or_error, bool was_async) { … } EXPORT_SYMBOL(…); static enum netfs_io_source netfs_cache_prepare_read(struct netfs_io_subrequest *subreq, loff_t i_size) { … } /* * Work out what sort of subrequest the next one will be. */ static enum netfs_io_source netfs_rreq_prepare_read(struct netfs_io_request *rreq, struct netfs_io_subrequest *subreq, struct iov_iter *io_iter) { … } /* * Slice off a piece of a read request and submit an I/O request for it. */ static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq, struct iov_iter *io_iter) { … } /* * Begin the process of reading in a chunk of data, where that data may be * stitched together from multiple sources, including multiple servers and the * local cache. */ int netfs_begin_read(struct netfs_io_request *rreq, bool sync) { … }