mirror of
https://github.com/torvalds/linux
synced 2024-10-14 23:39:09 +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)
|
if (same_page)
|
||||||
put_page(page);
|
bio_release_page(bio, page);
|
||||||
return 0;
|
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)
|
queue_max_zone_append_sectors(q), &same_page) != len)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (same_page)
|
if (same_page)
|
||||||
put_page(page);
|
bio_release_page(bio, page);
|
||||||
return 0;
|
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
|
* @bio: bio to add pages to
|
||||||
* @iter: iov iterator describing the region to be mapped
|
* @iter: iov iterator describing the region to be mapped
|
||||||
*
|
*
|
||||||
* Pins pages from *iter and appends them to @bio's bvec array. The
|
* Extracts pages from *iter and appends them to @bio's bvec array. The pages
|
||||||
* pages will have to be released using put_page() when done.
|
* will have to be cleaned up in the way indicated by the BIO_PAGE_PINNED flag.
|
||||||
* For multi-segment *iter, this function only adds pages from the
|
* For a multi-segment *iter, this function only adds pages from the next
|
||||||
* next non-empty segment of the iov iterator.
|
* non-empty segment of the iov iterator.
|
||||||
*/
|
*/
|
||||||
static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
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
|
* 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.
|
* the iov data will be picked up in the next bio iteration.
|
||||||
*/
|
*/
|
||||||
size = iov_iter_get_pages(iter, pages,
|
size = iov_iter_extract_pages(iter, &pages,
|
||||||
UINT_MAX - bio->bi_iter.bi_size,
|
UINT_MAX - bio->bi_iter.bi_size,
|
||||||
nr_pages, &offset, extraction_flags);
|
nr_pages, extraction_flags, &offset);
|
||||||
if (unlikely(size <= 0))
|
if (unlikely(size <= 0))
|
||||||
return size ? size : -EFAULT;
|
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);
|
iov_iter_revert(iter, left);
|
||||||
out:
|
out:
|
||||||
while (i < nr_pages)
|
while (i < nr_pages)
|
||||||
put_page(pages[i++]);
|
bio_release_page(bio, pages[i++]);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1335,7 +1335,8 @@ int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bio_set_flag(bio, BIO_PAGE_REFFED);
|
if (iov_iter_extract_will_pin(iter))
|
||||||
|
bio_set_flag(bio, BIO_PAGE_PINNED);
|
||||||
do {
|
do {
|
||||||
ret = __bio_iov_iter_get_pages(bio, iter);
|
ret = __bio_iov_iter_get_pages(bio, iter);
|
||||||
} while (!ret && iov_iter_count(iter) && !bio_full(bio, 0));
|
} while (!ret && iov_iter_count(iter) && !bio_full(bio, 0));
|
||||||
|
|
Loading…
Reference in a new issue