mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-01 18:52:02 +00:00
block: Convert bio_iov_iter_get_pages to use iov_iter_extract_pages
This will pin pages or leave them unaltered rather than getting a ref on them as appropriate to the iterator. The pages need to be pinned for DIO rather than having refs taken on them to prevent VM copy-on-write from malfunctioning during a concurrent fork() (the result of the I/O could otherwise end up being affected by/visible to the child process). Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: John Hubbard <jhubbard@nvidia.com> cc: Al Viro <viro@zeniv.linux.org.uk> cc: Jens Axboe <axboe@kernel.dk> cc: Jan Kara <jack@suse.cz> cc: Matthew Wilcox <willy@infradead.org> cc: Logan Gunthorpe <logang@deltatee.com> cc: linux-block@vger.kernel.org Reviewed-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20230522205744.2825689-6-dhowells@redhat.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
fd363244e8
commit
a7e689dd1c
23
block/bio.c
23
block/bio.c
@ -1205,7 +1205,7 @@ static int bio_iov_add_page(struct bio *bio, struct page *page,
|
||||
}
|
||||
|
||||
if (same_page)
|
||||
put_page(page);
|
||||
bio_release_page(bio, page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1219,7 +1219,7 @@ static int bio_iov_add_zone_append_page(struct bio *bio, struct page *page,
|
||||
queue_max_zone_append_sectors(q), &same_page) != len)
|
||||
return -EINVAL;
|
||||
if (same_page)
|
||||
put_page(page);
|
||||
bio_release_page(bio, page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1230,10 +1230,10 @@ static int bio_iov_add_zone_append_page(struct bio *bio, struct page *page,
|
||||
* @bio: bio to add pages to
|
||||
* @iter: iov iterator describing the region to be mapped
|
||||
*
|
||||
* Pins pages from *iter and appends them to @bio's bvec array. The
|
||||
* pages will have to be released using put_page() when done.
|
||||
* For multi-segment *iter, this function only adds pages from the
|
||||
* next non-empty segment of the iov iterator.
|
||||
* Extracts pages from *iter and appends them to @bio's bvec array. The pages
|
||||
* will have to be cleaned up in the way indicated by the BIO_PAGE_PINNED flag.
|
||||
* For a multi-segment *iter, this function only adds pages from the next
|
||||
* non-empty segment of the iov iterator.
|
||||
*/
|
||||
static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
||||
{
|
||||
@ -1265,9 +1265,9 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
||||
* result to ensure the bio's total size is correct. The remainder of
|
||||
* the iov data will be picked up in the next bio iteration.
|
||||
*/
|
||||
size = iov_iter_get_pages(iter, pages,
|
||||
UINT_MAX - bio->bi_iter.bi_size,
|
||||
nr_pages, &offset, extraction_flags);
|
||||
size = iov_iter_extract_pages(iter, &pages,
|
||||
UINT_MAX - bio->bi_iter.bi_size,
|
||||
nr_pages, extraction_flags, &offset);
|
||||
if (unlikely(size <= 0))
|
||||
return size ? size : -EFAULT;
|
||||
|
||||
@ -1300,7 +1300,7 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
||||
iov_iter_revert(iter, left);
|
||||
out:
|
||||
while (i < nr_pages)
|
||||
put_page(pages[i++]);
|
||||
bio_release_page(bio, pages[i++]);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1335,7 +1335,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bio_set_flag(bio, BIO_PAGE_REFFED);
|
||||
if (iov_iter_extract_will_pin(iter))
|
||||
bio_set_flag(bio, BIO_PAGE_PINNED);
|
||||
do {
|
||||
ret = __bio_iov_iter_get_pages(bio, iter);
|
||||
} while (!ret && iov_iter_count(iter) && !bio_full(bio, 0));
|
||||
|
Loading…
Reference in New Issue
Block a user