Re: [PATCH v9 8/8] block: convert bio_map_user_iov to use iov_iter_extract_pages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 1/24/23 09:01, David Howells wrote:
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 visible to/affected by
the child process).

Signed-off-by: David Howells <dhowells@xxxxxxxxxx>
cc: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
cc: Jens Axboe <axboe@xxxxxxxxx>
cc: Jan Kara <jack@xxxxxxx>
cc: Christoph Hellwig <hch@xxxxxx>
cc: Matthew Wilcox <willy@xxxxxxxxxxxxx>
cc: Logan Gunthorpe <logang@xxxxxxxxxxxx>
cc: linux-block@xxxxxxxxxxxxxxx
---

Notes:
     ver #8)
      - Split the patch up a bit [hch].
      - We should only be using pinned/non-pinned pages and not ref'd pages,
        so adjust the comments appropriately.
ver #7)
      - Don't treat BIO_PAGE_REFFED/PINNED as being the same as FOLL_GET/PIN.
ver #5)
      - Transcribe the FOLL_* flags returned by iov_iter_extract_pages() to
        BIO_* flags and got rid of bi_cleanup_mode.
      - Replaced BIO_NO_PAGE_REF to BIO_PAGE_REFFED in the preceding patch.

  block/blk-map.c | 22 ++++++++++------------
  1 file changed, 10 insertions(+), 12 deletions(-)


Reviewed-by: John Hubbard <jhubbard@xxxxxxxxxx>

thanks,
--
John Hubbard
NVIDIA

diff --git a/block/blk-map.c b/block/blk-map.c
index 0e2b0a861ba3..4e22dccdbe9b 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -282,21 +282,19 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
  	if (blk_queue_pci_p2pdma(rq->q))
  		extraction_flags |= ITER_ALLOW_P2PDMA;
- bio_set_flag(bio, BIO_PAGE_REFFED);
+	bio_set_cleanup_mode(bio, iter);
  	while (iov_iter_count(iter)) {
-		struct page **pages, *stack_pages[UIO_FASTIOV];
+		struct page *stack_pages[UIO_FASTIOV];
+		struct page **pages = stack_pages;
  		ssize_t bytes;
  		size_t offs;
  		int npages;
- if (nr_vecs <= ARRAY_SIZE(stack_pages)) {
-			pages = stack_pages;
-			bytes = iov_iter_get_pages(iter, pages, LONG_MAX,
-						   nr_vecs, &offs, extraction_flags);
-		} else {
-			bytes = iov_iter_get_pages_alloc(iter, &pages,
-						LONG_MAX, &offs, extraction_flags);
-		}
+		if (nr_vecs > ARRAY_SIZE(stack_pages))
+			pages = NULL;
+
+		bytes = iov_iter_extract_pages(iter, &pages, LONG_MAX,
+					       nr_vecs, extraction_flags, &offs);
  		if (unlikely(bytes <= 0)) {
  			ret = bytes ? bytes : -EFAULT;
  			goto out_unmap;
@@ -318,7 +316,7 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
  				if (!bio_add_hw_page(rq->q, bio, page, n, offs,
  						     max_sectors, &same_page)) {
  					if (same_page)
-						put_page(page);
+						bio_release_page(bio, page);
  					break;
  				}
@@ -330,7 +328,7 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
  		 * release the pages we didn't map into the bio, if any
  		 */
  		while (j < npages)
-			put_page(pages[j++]);
+			bio_release_page(bio, pages[j++]);
  		if (pages != stack_pages)
  			kvfree(pages);
  		/* couldn't stuff something into bio? */





[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux