Skip to content

Commit 92b6cc5

Browse files
committed
netfs: Add iov_iters to (sub)requests to describe various buffers
Add three iov_iter structs: (1) Add an iov_iter (->iter) to the I/O request to describe the unencrypted-side buffer. (2) Add an iov_iter (->io_iter) to the I/O request to describe the encrypted-side I/O buffer. This may be a different size to the buffer in (1). (3) Add an iov_iter (->io_iter) to the I/O subrequest to describe the part of the I/O buffer for that subrequest. This will allow future patches to point to a bounce buffer instead for purposes of handling oversize writes, decryption (where we want to save the encrypted data to the cache) and decompression. These iov_iters persist for the lifetime of the (sub)request, and so can be accessed multiple times without worrying about them being deallocated upon return to the caller. The network filesystem must appropriately advance the iterator before terminating the request. Signed-off-by: David Howells <dhowells@redhat.com> cc: Jeff Layton <jlayton@kernel.org> cc: linux-cachefs@redhat.com cc: linux-fsdevel@vger.kernel.org cc: linux-mm@kvack.org
1 parent 46ed60d commit 92b6cc5

4 files changed

Lines changed: 67 additions & 24 deletions

File tree

fs/afs/file.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -323,11 +323,7 @@ static void afs_issue_read(struct netfs_io_subrequest *subreq)
323323
fsreq->len = subreq->len - subreq->transferred;
324324
fsreq->key = key_get(subreq->rreq->netfs_priv);
325325
fsreq->vnode = vnode;
326-
fsreq->iter = &fsreq->def_iter;
327-
328-
iov_iter_xarray(&fsreq->def_iter, ITER_DEST,
329-
&fsreq->vnode->netfs.inode.i_mapping->i_pages,
330-
fsreq->pos, fsreq->len);
326+
fsreq->iter = &subreq->io_iter;
331327

332328
afs_fetch_data(fsreq->vnode, fsreq);
333329
afs_put_read(fsreq);

fs/netfs/buffered_read.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ void netfs_readahead(struct readahead_control *ractl)
199199

200200
netfs_rreq_expand(rreq, ractl);
201201

202+
/* Set up the output buffer */
203+
iov_iter_xarray(&rreq->iter, ITER_DEST, &ractl->mapping->i_pages,
204+
rreq->start, rreq->len);
205+
202206
/* Drop the refs on the folios here rather than in the cache or
203207
* filesystem. The locks will be dropped in netfs_rreq_unlock().
204208
*/
@@ -251,6 +255,11 @@ int netfs_read_folio(struct file *file, struct folio *folio)
251255

252256
netfs_stat(&netfs_n_rh_readpage);
253257
trace_netfs_read(rreq, rreq->start, rreq->len, netfs_read_trace_readpage);
258+
259+
/* Set up the output buffer */
260+
iov_iter_xarray(&rreq->iter, ITER_DEST, &mapping->i_pages,
261+
rreq->start, rreq->len);
262+
254263
return netfs_begin_read(rreq, true);
255264

256265
discard:
@@ -408,6 +417,10 @@ int netfs_write_begin(struct netfs_inode *ctx,
408417
ractl._nr_pages = folio_nr_pages(folio);
409418
netfs_rreq_expand(rreq, &ractl);
410419

420+
/* Set up the output buffer */
421+
iov_iter_xarray(&rreq->iter, ITER_DEST, &mapping->i_pages,
422+
rreq->start, rreq->len);
423+
411424
/* We hold the folio locks, so we can drop the references */
412425
folio_get(folio);
413426
while (readahead_folio(&ractl))

fs/netfs/io.c

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,7 @@
2121
*/
2222
static void netfs_clear_unread(struct netfs_io_subrequest *subreq)
2323
{
24-
struct iov_iter iter;
25-
26-
iov_iter_xarray(&iter, ITER_DEST, &subreq->rreq->mapping->i_pages,
27-
subreq->start + subreq->transferred,
28-
subreq->len - subreq->transferred);
29-
iov_iter_zero(iov_iter_count(&iter), &iter);
24+
iov_iter_zero(iov_iter_count(&subreq->io_iter), &subreq->io_iter);
3025
}
3126

3227
static void netfs_cache_read_terminated(void *priv, ssize_t transferred_or_error,
@@ -46,14 +41,9 @@ static void netfs_read_from_cache(struct netfs_io_request *rreq,
4641
enum netfs_read_from_hole read_hole)
4742
{
4843
struct netfs_cache_resources *cres = &rreq->cache_resources;
49-
struct iov_iter iter;
5044

5145
netfs_stat(&netfs_n_rh_read);
52-
iov_iter_xarray(&iter, ITER_DEST, &rreq->mapping->i_pages,
53-
subreq->start + subreq->transferred,
54-
subreq->len - subreq->transferred);
55-
56-
cres->ops->read(cres, subreq->start, &iter, read_hole,
46+
cres->ops->read(cres, subreq->start, &subreq->io_iter, read_hole,
5747
netfs_cache_read_terminated, subreq);
5848
}
5949

@@ -88,6 +78,11 @@ static void netfs_read_from_server(struct netfs_io_request *rreq,
8878
struct netfs_io_subrequest *subreq)
8979
{
9080
netfs_stat(&netfs_n_rh_download);
81+
if (iov_iter_count(&subreq->io_iter) != subreq->len - subreq->transferred)
82+
pr_warn("R=%08x[%u] ITER PRE-MISMATCH %zx != %zx-%zx %lx\n",
83+
rreq->debug_id, subreq->debug_index,
84+
iov_iter_count(&subreq->io_iter), subreq->len,
85+
subreq->transferred, subreq->flags);
9186
rreq->netfs_ops->issue_read(subreq);
9287
}
9388

@@ -259,6 +254,30 @@ static void netfs_rreq_short_read(struct netfs_io_request *rreq,
259254
netfs_read_from_server(rreq, subreq);
260255
}
261256

257+
/*
258+
* Reset the subrequest iterator prior to resubmission.
259+
*/
260+
static void netfs_reset_subreq_iter(struct netfs_io_request *rreq,
261+
struct netfs_io_subrequest *subreq)
262+
{
263+
size_t remaining = subreq->len - subreq->transferred;
264+
size_t count = iov_iter_count(&subreq->io_iter);
265+
266+
if (count == remaining)
267+
return;
268+
269+
_debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x\n",
270+
rreq->debug_id, subreq->debug_index,
271+
iov_iter_count(&subreq->io_iter), subreq->transferred,
272+
subreq->len, rreq->i_size,
273+
subreq->io_iter.iter_type);
274+
275+
if (count < remaining)
276+
iov_iter_revert(&subreq->io_iter, remaining - count);
277+
else
278+
iov_iter_advance(&subreq->io_iter, count - remaining);
279+
}
280+
262281
/*
263282
* Resubmit any short or failed operations. Returns true if we got the rreq
264283
* ref back.
@@ -287,6 +306,7 @@ static bool netfs_rreq_perform_resubmissions(struct netfs_io_request *rreq)
287306
trace_netfs_sreq(subreq, netfs_sreq_trace_download_instead);
288307
netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit);
289308
atomic_inc(&rreq->nr_outstanding);
309+
netfs_reset_subreq_iter(rreq, subreq);
290310
netfs_read_from_server(rreq, subreq);
291311
} else if (test_bit(NETFS_SREQ_SHORT_IO, &subreq->flags)) {
292312
netfs_rreq_short_read(rreq, subreq);
@@ -399,9 +419,9 @@ void netfs_subreq_terminated(struct netfs_io_subrequest *subreq,
399419
struct netfs_io_request *rreq = subreq->rreq;
400420
int u;
401421

402-
_enter("[%u]{%llx,%lx},%zd",
403-
subreq->debug_index, subreq->start, subreq->flags,
404-
transferred_or_error);
422+
_enter("R=%x[%x]{%llx,%lx},%zd",
423+
rreq->debug_id, subreq->debug_index,
424+
subreq->start, subreq->flags, transferred_or_error);
405425

406426
switch (subreq->source) {
407427
case NETFS_READ_FROM_CACHE:
@@ -501,7 +521,8 @@ static enum netfs_io_source netfs_cache_prepare_read(struct netfs_io_subrequest
501521
*/
502522
static enum netfs_io_source
503523
netfs_rreq_prepare_read(struct netfs_io_request *rreq,
504-
struct netfs_io_subrequest *subreq)
524+
struct netfs_io_subrequest *subreq,
525+
struct iov_iter *io_iter)
505526
{
506527
enum netfs_io_source source;
507528

@@ -528,9 +549,14 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq,
528549
}
529550
}
530551

531-
if (WARN_ON(subreq->len == 0))
552+
if (WARN_ON(subreq->len == 0)) {
532553
source = NETFS_INVALID_READ;
554+
goto out;
555+
}
533556

557+
subreq->io_iter = *io_iter;
558+
iov_iter_truncate(&subreq->io_iter, subreq->len);
559+
iov_iter_advance(io_iter, subreq->len);
534560
out:
535561
subreq->source = source;
536562
trace_netfs_sreq(subreq, netfs_sreq_trace_prepare);
@@ -541,6 +567,7 @@ netfs_rreq_prepare_read(struct netfs_io_request *rreq,
541567
* Slice off a piece of a read request and submit an I/O request for it.
542568
*/
543569
static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq,
570+
struct iov_iter *io_iter,
544571
unsigned int *_debug_index)
545572
{
546573
struct netfs_io_subrequest *subreq;
@@ -565,7 +592,7 @@ static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq,
565592
* (the starts must coincide), in which case, we go around the loop
566593
* again and ask it to download the next piece.
567594
*/
568-
source = netfs_rreq_prepare_read(rreq, subreq);
595+
source = netfs_rreq_prepare_read(rreq, subreq, io_iter);
569596
if (source == NETFS_INVALID_READ)
570597
goto subreq_failed;
571598

@@ -603,6 +630,7 @@ static bool netfs_rreq_submit_slice(struct netfs_io_request *rreq,
603630
*/
604631
int netfs_begin_read(struct netfs_io_request *rreq, bool sync)
605632
{
633+
struct iov_iter io_iter;
606634
unsigned int debug_index = 0;
607635
int ret;
608636

@@ -615,6 +643,8 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync)
615643
return -EIO;
616644
}
617645

646+
rreq->io_iter = rreq->iter;
647+
618648
INIT_WORK(&rreq->work, netfs_rreq_work);
619649

620650
if (sync)
@@ -624,8 +654,9 @@ int netfs_begin_read(struct netfs_io_request *rreq, bool sync)
624654
* want and submit each one.
625655
*/
626656
atomic_set(&rreq->nr_outstanding, 1);
657+
io_iter = rreq->io_iter;
627658
do {
628-
if (!netfs_rreq_submit_slice(rreq, &debug_index))
659+
if (!netfs_rreq_submit_slice(rreq, &io_iter, &debug_index))
629660
break;
630661

631662
} while (rreq->submitted < rreq->len);

include/linux/netfs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ struct netfs_cache_resources {
150150
struct netfs_io_subrequest {
151151
struct netfs_io_request *rreq; /* Supervising I/O request */
152152
struct list_head rreq_link; /* Link in rreq->subrequests */
153+
struct iov_iter io_iter; /* Iterator for this subrequest */
153154
loff_t start; /* Where to start the I/O */
154155
size_t len; /* Size of the I/O */
155156
size_t transferred; /* Amount of data transferred */
@@ -186,6 +187,8 @@ struct netfs_io_request {
186187
struct netfs_cache_resources cache_resources;
187188
struct list_head proc_link; /* Link in netfs_iorequests */
188189
struct list_head subrequests; /* Contributory I/O operations */
190+
struct iov_iter iter; /* Unencrypted-side iterator */
191+
struct iov_iter io_iter; /* I/O (Encrypted-side) iterator */
189192
void *netfs_priv; /* Private data for the netfs */
190193
unsigned int debug_id;
191194
atomic_t nr_outstanding; /* Number of ops in progress */

0 commit comments

Comments
 (0)