All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2 v2] iomap: Cleanup of iomap_dio_rw()
@ 2019-11-25 11:18 Jan Kara
  2019-11-25 11:18 ` [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor() Jan Kara
  0 siblings, 1 reply; 8+ messages in thread
From: Jan Kara @ 2019-11-25 11:18 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: Christoph Hellwig, linux-fsdevel, Eric Biggers,
	Matthew Bobrowski, Jan Kara

Hello,

here is the second version of the series. Since Darrick has already picked up
the patch fixing pipe page leakage, I'm resending only the updated cleanup
patch.

Changes since v1:
* Dropped fix patch as it is already in Darrick's tree
* Rebased cleanup patch on top of iomap tree (Christoph)
* Changed code in iomap_dio_rw() to reexpand the iter only in one place and
  jump there from elsewhere (Christoph)
* Expanded comment and moved 'orig_count' initialization (Christoph)

								Honza
Previous versions:
Link: http://lore.kernel.org/r/20191121161144.30802-1-jack@suse.cz

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor()
  2019-11-25 11:18 [PATCH 0/2 v2] iomap: Cleanup of iomap_dio_rw() Jan Kara
@ 2019-11-25 11:18 ` Jan Kara
  2019-11-25 17:53   ` Christoph Hellwig
                     ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Jan Kara @ 2019-11-25 11:18 UTC (permalink / raw)
  To: Darrick J. Wong
  Cc: Christoph Hellwig, linux-fsdevel, Eric Biggers,
	Matthew Bobrowski, Jan Kara

iomap_dio_bio_actor() copies iter to a local variable and then limits it
to a file extent we have mapped. When IO is submitted,
iomap_dio_bio_actor() advances the original iter while the copied iter
is advanced inside bio_iov_iter_get_pages(). This logic is non-obvious
especially because both iters still point to same shared structures
(such as pipe info) so if iov_iter_advance() changes anything in the
shared structure, this scheme breaks. Let's just truncate and reexpand
the original iter as needed instead of playing games with copying iters
and keeping them in sync.

Signed-off-by: Jan Kara <jack@suse.cz>
---
 fs/iomap/direct-io.c | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
index 420c0c82f0ac..b75cd0b0609b 100644
--- a/fs/iomap/direct-io.c
+++ b/fs/iomap/direct-io.c
@@ -201,12 +201,12 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 	unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev));
 	unsigned int fs_block_size = i_blocksize(inode), pad;
 	unsigned int align = iov_iter_alignment(dio->submit.iter);
-	struct iov_iter iter;
 	struct bio *bio;
 	bool need_zeroout = false;
 	bool use_fua = false;
 	int nr_pages, ret = 0;
 	size_t copied = 0;
+	size_t orig_count;
 
 	if ((pos | length | align) & ((1 << blkbits) - 1))
 		return -EINVAL;
@@ -236,15 +236,18 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 	}
 
 	/*
-	 * Operate on a partial iter trimmed to the extent we were called for.
-	 * We'll update the iter in the dio once we're done with this extent.
+	 * Save the original count and trim the iter to just the extent we
+	 * are operating on right now.  The iter will be re-expanded once
+	 * we are done.
 	 */
-	iter = *dio->submit.iter;
-	iov_iter_truncate(&iter, length);
+	orig_count = iov_iter_count(dio->submit.iter);
+	iov_iter_truncate(dio->submit.iter, length);
 
-	nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
-	if (nr_pages <= 0)
-		return nr_pages;
+	nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
+	if (nr_pages <= 0) {
+		ret = nr_pages;
+		goto out;
+	}
 
 	if (need_zeroout) {
 		/* zero out from the start of the block to the write offset */
@@ -257,7 +260,8 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 		size_t n;
 		if (dio->error) {
 			iov_iter_revert(dio->submit.iter, copied);
-			return 0;
+			copied = ret = 0;
+			goto out;
 		}
 
 		bio = bio_alloc(GFP_KERNEL, nr_pages);
@@ -268,7 +272,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 		bio->bi_private = dio;
 		bio->bi_end_io = iomap_dio_bio_end_io;
 
-		ret = bio_iov_iter_get_pages(bio, &iter);
+		ret = bio_iov_iter_get_pages(bio, dio->submit.iter);
 		if (unlikely(ret)) {
 			/*
 			 * We have to stop part way through an IO. We must fall
@@ -294,13 +298,11 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 				bio_set_pages_dirty(bio);
 		}
 
-		iov_iter_advance(dio->submit.iter, n);
-
 		dio->size += n;
 		pos += n;
 		copied += n;
 
-		nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
+		nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
 		iomap_dio_submit_bio(dio, iomap, bio);
 	} while (nr_pages);
 
@@ -318,6 +320,9 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
 		if (pad)
 			iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
 	}
+out:
+	/* Undo iter limitation to current extent */
+	iov_iter_reexpand(dio->submit.iter, orig_count - copied);
 	if (copied)
 		return copied;
 	return ret;
-- 
2.16.4


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor()
  2019-11-25 11:18 ` [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor() Jan Kara
@ 2019-11-25 17:53   ` Christoph Hellwig
  2019-11-25 21:11   ` Matthew Bobrowski
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2019-11-25 17:53 UTC (permalink / raw)
  To: Jan Kara
  Cc: Darrick J. Wong, Christoph Hellwig, linux-fsdevel, Eric Biggers,
	Matthew Bobrowski

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor()
  2019-11-25 11:18 ` [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor() Jan Kara
  2019-11-25 17:53   ` Christoph Hellwig
@ 2019-11-25 21:11   ` Matthew Bobrowski
  2019-11-26 15:12     ` Matthew Wilcox
  2019-11-26 16:31   ` Christoph Hellwig
  2019-11-26 17:47   ` Darrick J. Wong
  3 siblings, 1 reply; 8+ messages in thread
From: Matthew Bobrowski @ 2019-11-25 21:11 UTC (permalink / raw)
  To: Jan Kara; +Cc: Darrick J. Wong, Christoph Hellwig, linux-fsdevel, Eric Biggers

On Mon, Nov 25, 2019 at 12:18:57PM +0100, Jan Kara wrote:
> iomap_dio_bio_actor() copies iter to a local variable and then limits it
> to a file extent we have mapped. When IO is submitted,
> iomap_dio_bio_actor() advances the original iter while the copied iter
> is advanced inside bio_iov_iter_get_pages(). This logic is non-obvious
> especially because both iters still point to same shared structures
> (such as pipe info) so if iov_iter_advance() changes anything in the
> shared structure, this scheme breaks. Let's just truncate and reexpand
> the original iter as needed instead of playing games with copying iters
> and keeping them in sync.

Looks good. Just one minor nit below which is eating me. I guess
Darrick can fix it up when applying it to his tree, if deemed
necessary to fix up.

Feel free to add:

Reviewed-by: Matthew Bobrowski <mbobrowski@mbobrowski.org>

>  	/*
> -	 * Operate on a partial iter trimmed to the extent we were called for.
> -	 * We'll update the iter in the dio once we're done with this extent.
> +	 * Save the original count and trim the iter to just the extent we
> +	 * are operating on right now.  The iter will be re-expanded once
  	       		    	      ^^
				      Extra whitespace here.

IMO, I think we can word the last sentence a little better too i.e.

/*                                                                               
 * Save the original count and trim the iter to the extent that we're            
 * currently operating on right now. The iter will then again be                 
 * expanded out once we're done.                                                 
 */

/M

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor()
  2019-11-25 21:11   ` Matthew Bobrowski
@ 2019-11-26 15:12     ` Matthew Wilcox
  2019-11-26 21:47       ` Matthew Bobrowski
  0 siblings, 1 reply; 8+ messages in thread
From: Matthew Wilcox @ 2019-11-26 15:12 UTC (permalink / raw)
  To: Matthew Bobrowski
  Cc: Jan Kara, Darrick J. Wong, Christoph Hellwig, linux-fsdevel,
	Eric Biggers

On Tue, Nov 26, 2019 at 08:11:50AM +1100, Matthew Bobrowski wrote:
> > +	 * are operating on right now.  The iter will be re-expanded once
>   	       		    	      ^^
> 				      Extra whitespace here.

That's controversial, not wrong.  We don't normally enforce a style there.
https://www.theatlantic.com/science/archive/2018/05/two-spaces-after-a-period/559304/
(for example.  you can find many many many pieces extolling one or
two spaces).

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor()
  2019-11-25 11:18 ` [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor() Jan Kara
  2019-11-25 17:53   ` Christoph Hellwig
  2019-11-25 21:11   ` Matthew Bobrowski
@ 2019-11-26 16:31   ` Christoph Hellwig
  2019-11-26 17:47   ` Darrick J. Wong
  3 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2019-11-26 16:31 UTC (permalink / raw)
  To: Jan Kara
  Cc: Darrick J. Wong, Christoph Hellwig, linux-fsdevel, Eric Biggers,
	Matthew Bobrowski

Looks good:

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor()
  2019-11-25 11:18 ` [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor() Jan Kara
                     ` (2 preceding siblings ...)
  2019-11-26 16:31   ` Christoph Hellwig
@ 2019-11-26 17:47   ` Darrick J. Wong
  3 siblings, 0 replies; 8+ messages in thread
From: Darrick J. Wong @ 2019-11-26 17:47 UTC (permalink / raw)
  To: Jan Kara
  Cc: Christoph Hellwig, linux-fsdevel, Eric Biggers, Matthew Bobrowski

 n Mon, Nov 25, 2019 at 12:18:57PM +0100, Jan Kara wrote:
> iomap_dio_bio_actor() copies iter to a local variable and then limits it
> to a file extent we have mapped. When IO is submitted,
> iomap_dio_bio_actor() advances the original iter while the copied iter
> is advanced inside bio_iov_iter_get_pages(). This logic is non-obvious
> especially because both iters still point to same shared structures
> (such as pipe info) so if iov_iter_advance() changes anything in the
> shared structure, this scheme breaks. Let's just truncate and reexpand
> the original iter as needed instead of playing games with copying iters
> and keeping them in sync.
> 
> Signed-off-by: Jan Kara <jack@suse.cz>

Looks ok, seems to test ok too
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>

--D

> ---
>  fs/iomap/direct-io.c | 31 ++++++++++++++++++-------------
>  1 file changed, 18 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
> index 420c0c82f0ac..b75cd0b0609b 100644
> --- a/fs/iomap/direct-io.c
> +++ b/fs/iomap/direct-io.c
> @@ -201,12 +201,12 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
>  	unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev));
>  	unsigned int fs_block_size = i_blocksize(inode), pad;
>  	unsigned int align = iov_iter_alignment(dio->submit.iter);
> -	struct iov_iter iter;
>  	struct bio *bio;
>  	bool need_zeroout = false;
>  	bool use_fua = false;
>  	int nr_pages, ret = 0;
>  	size_t copied = 0;
> +	size_t orig_count;
>  
>  	if ((pos | length | align) & ((1 << blkbits) - 1))
>  		return -EINVAL;
> @@ -236,15 +236,18 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
>  	}
>  
>  	/*
> -	 * Operate on a partial iter trimmed to the extent we were called for.
> -	 * We'll update the iter in the dio once we're done with this extent.
> +	 * Save the original count and trim the iter to just the extent we
> +	 * are operating on right now.  The iter will be re-expanded once
> +	 * we are done.
>  	 */
> -	iter = *dio->submit.iter;
> -	iov_iter_truncate(&iter, length);
> +	orig_count = iov_iter_count(dio->submit.iter);
> +	iov_iter_truncate(dio->submit.iter, length);
>  
> -	nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
> -	if (nr_pages <= 0)
> -		return nr_pages;
> +	nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
> +	if (nr_pages <= 0) {
> +		ret = nr_pages;
> +		goto out;
> +	}
>  
>  	if (need_zeroout) {
>  		/* zero out from the start of the block to the write offset */
> @@ -257,7 +260,8 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
>  		size_t n;
>  		if (dio->error) {
>  			iov_iter_revert(dio->submit.iter, copied);
> -			return 0;
> +			copied = ret = 0;
> +			goto out;
>  		}
>  
>  		bio = bio_alloc(GFP_KERNEL, nr_pages);
> @@ -268,7 +272,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
>  		bio->bi_private = dio;
>  		bio->bi_end_io = iomap_dio_bio_end_io;
>  
> -		ret = bio_iov_iter_get_pages(bio, &iter);
> +		ret = bio_iov_iter_get_pages(bio, dio->submit.iter);
>  		if (unlikely(ret)) {
>  			/*
>  			 * We have to stop part way through an IO. We must fall
> @@ -294,13 +298,11 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
>  				bio_set_pages_dirty(bio);
>  		}
>  
> -		iov_iter_advance(dio->submit.iter, n);
> -
>  		dio->size += n;
>  		pos += n;
>  		copied += n;
>  
> -		nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
> +		nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
>  		iomap_dio_submit_bio(dio, iomap, bio);
>  	} while (nr_pages);
>  
> @@ -318,6 +320,9 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
>  		if (pad)
>  			iomap_dio_zero(dio, iomap, pos, fs_block_size - pad);
>  	}
> +out:
> +	/* Undo iter limitation to current extent */
> +	iov_iter_reexpand(dio->submit.iter, orig_count - copied);
>  	if (copied)
>  		return copied;
>  	return ret;
> -- 
> 2.16.4
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor()
  2019-11-26 15:12     ` Matthew Wilcox
@ 2019-11-26 21:47       ` Matthew Bobrowski
  0 siblings, 0 replies; 8+ messages in thread
From: Matthew Bobrowski @ 2019-11-26 21:47 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Jan Kara, Darrick J. Wong, Christoph Hellwig, linux-fsdevel,
	Eric Biggers

On Tue, Nov 26, 2019 at 07:12:16AM -0800, Matthew Wilcox wrote:
> On Tue, Nov 26, 2019 at 08:11:50AM +1100, Matthew Bobrowski wrote:
> > > +	 * are operating on right now.  The iter will be re-expanded once
> >   	       		    	      ^^
> > 				      Extra whitespace here.
> 
> That's controversial, not wrong.  We don't normally enforce a style there.
> https://www.theatlantic.com/science/archive/2018/05/two-spaces-after-a-period/559304/
> (for example.  you can find many many many pieces extolling one or
> two spaces).

Indeed controversial, a good read, and thank you for sharing. I guess
that I haven't been brought up with two spaces after a period being a
"thing", so it makes my wires trip when glancing over a snippet of
text.

At least I'll know this for next time. :)

/M

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2019-11-26 21:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-25 11:18 [PATCH 0/2 v2] iomap: Cleanup of iomap_dio_rw() Jan Kara
2019-11-25 11:18 ` [PATCH] iomap: Do not create fake iter in iomap_dio_bio_actor() Jan Kara
2019-11-25 17:53   ` Christoph Hellwig
2019-11-25 21:11   ` Matthew Bobrowski
2019-11-26 15:12     ` Matthew Wilcox
2019-11-26 21:47       ` Matthew Bobrowski
2019-11-26 16:31   ` Christoph Hellwig
2019-11-26 17:47   ` Darrick J. Wong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.