Skip to content

Commit 7ff5062

Browse files
committed
iov_iter: Add ITER_XARRAY
Add an iterator, ITER_XARRAY, that walks through a set of pages attached to an xarray, starting at a given page and offset and walking for the specified amount of bytes. The iterator supports transparent huge pages. The iterate_xarray() macro calls the helper function with rcu_access() helped. I think that this is only a problem for iov_iter_for_each_range() - and that returns an error for ITER_XARRAY (also, this function does not appear to be called). The caller must guarantee that the pages are all present and they must be locked using PG_locked, PG_writeback or PG_fscache to prevent them from going away or being migrated whilst they're being accessed. This is useful for copying data from socket buffers to inodes in network filesystems and for transferring data between those inodes and the cache using direct I/O. Whilst it is true that ITER_BVEC could be used instead, that would require a bio_vec array to be allocated to refer to all the pages - which should be redundant if inode->i_pages also points to all these pages. Note that older versions of this patch implemented an ITER_MAPPING instead, which was almost the same. Changes: v7: - Rename iter_xarray_copy_pages() to iter_xarray_populate_pages()[1]. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-and-tested-by: Jeff Layton <jlayton@kernel.org> Tested-by: Dave Wysochanski <dwysocha@redhat.com> Tested-By: Marc Dionne <marc.dionne@auristor.com> cc: Alexander Viro <viro@zeniv.linux.org.uk> cc: Matthew Wilcox (Oracle) <willy@infradead.org> cc: Christoph Hellwig <hch@lst.de> cc: linux-mm@kvack.org cc: linux-cachefs@redhat.com cc: linux-afs@lists.infradead.org cc: linux-nfs@vger.kernel.org cc: linux-cifs@vger.kernel.org cc: ceph-devel@vger.kernel.org cc: v9fs-developer@lists.sourceforge.net cc: linux-fsdevel@vger.kernel.org Link: https://lore.kernel.org/r/3577430.1579705075@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/158861205740.340223.16592990225607814022.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/159465785214.1376674.6062549291411362531.stgit@warthog.procyon.org.uk/ Link: https://lore.kernel.org/r/160588477334.3465195.3608963255682568730.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/161118129703.1232039.17141248432017826976.stgit@warthog.procyon.org.uk/ # rfc Link: https://lore.kernel.org/r/161161026313.2537118.14676007075365418649.stgit@warthog.procyon.org.uk/ # v2 Link: https://lore.kernel.org/r/161340386671.1303470.10752208972482479840.stgit@warthog.procyon.org.uk/ # v3 Link: https://lore.kernel.org/r/161539527815.286939.14607323792547049341.stgit@warthog.procyon.org.uk/ # v4 Link: https://lore.kernel.org/r/161653786033.2770958.14154191921867463240.stgit@warthog.procyon.org.uk/ # v5 Link: https://lore.kernel.org/r/161789064740.6155.11932541175173658065.stgit@warthog.procyon.org.uk/ # v6 Link: https://lore.kernel.org/r/27c369a8f42bb8a617672b2dc0126a5c6df5a050.camel@kernel.org [1]
1 parent 4ee998b commit 7ff5062

2 files changed

Lines changed: 301 additions & 23 deletions

File tree

include/linux/uio.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <uapi/linux/uio.h>
1111

1212
struct page;
13+
struct address_space;
1314
struct pipe_inode_info;
1415

1516
struct kvec {
@@ -24,6 +25,7 @@ enum iter_type {
2425
ITER_BVEC = 16,
2526
ITER_PIPE = 32,
2627
ITER_DISCARD = 64,
28+
ITER_XARRAY = 128,
2729
};
2830

2931
struct iov_iter {
@@ -39,6 +41,7 @@ struct iov_iter {
3941
const struct iovec *iov;
4042
const struct kvec *kvec;
4143
const struct bio_vec *bvec;
44+
struct xarray *xarray;
4245
struct pipe_inode_info *pipe;
4346
};
4447
union {
@@ -47,6 +50,7 @@ struct iov_iter {
4750
unsigned int head;
4851
unsigned int start_head;
4952
};
53+
loff_t xarray_start;
5054
};
5155
};
5256

@@ -80,6 +84,11 @@ static inline bool iov_iter_is_discard(const struct iov_iter *i)
8084
return iov_iter_type(i) == ITER_DISCARD;
8185
}
8286

87+
static inline bool iov_iter_is_xarray(const struct iov_iter *i)
88+
{
89+
return iov_iter_type(i) == ITER_XARRAY;
90+
}
91+
8392
static inline unsigned char iov_iter_rw(const struct iov_iter *i)
8493
{
8594
return i->type & (READ | WRITE);
@@ -221,6 +230,8 @@ void iov_iter_bvec(struct iov_iter *i, unsigned int direction, const struct bio_
221230
void iov_iter_pipe(struct iov_iter *i, unsigned int direction, struct pipe_inode_info *pipe,
222231
size_t count);
223232
void iov_iter_discard(struct iov_iter *i, unsigned int direction, size_t count);
233+
void iov_iter_xarray(struct iov_iter *i, unsigned int direction, struct xarray *xarray,
234+
loff_t start, size_t count);
224235
ssize_t iov_iter_get_pages(struct iov_iter *i, struct page **pages,
225236
size_t maxsize, unsigned maxpages, size_t *start);
226237
ssize_t iov_iter_get_pages_alloc(struct iov_iter *i, struct page ***pages,

0 commit comments

Comments
 (0)