All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ext4: fix off-by-one on max nr_pages in ext4_find_unwritten_pgoff()
@ 2017-05-21  8:00 Eryu Guan
  2017-05-23  8:34 ` Jan Kara
  0 siblings, 1 reply; 4+ messages in thread
From: Eryu Guan @ 2017-05-21  8:00 UTC (permalink / raw)
  To: linux-ext4; +Cc: Eryu Guan

ext4_find_unwritten_pgoff() is used to search for offset of hole or
data in page range [index, end] (both inclusive), and the max number
of pages to search should be at least one, if end == index.
Otherwise the only page is missed and no hole or data is found,
which is not correct.

When block size is smaller than page size, this can be demonstrated
by preallocating a file with size smaller than page size and writing
data to the last block. E.g. run this xfs_io command on a 1k block
size ext4 on x86_64 host.

  # xfs_io -fc "falloc 0 3k" -c "pwrite 2k 1k" \
  	    -c "seek -d 0" /mnt/ext4/testfile
  wrote 1024/1024 bytes at offset 2048
  1 KiB, 1 ops; 0.0000 sec (42.459 MiB/sec and 43478.2609 ops/sec)
  Whence  Result
  DATA    EOF

Data at offset 2k was missed, and lseek(2) returned ENXIO.

This is unconvered by generic/285 subtest 07 and 08 on ppc64 host,
where pagesize is 64k. Because a recent change to generic/285
reduced the preallocated file size to smaller than 64k.

Cc: stable@vger.kernel.org # v3.7+
Signed-off-by: Eryu Guan <eguan@redhat.com>
---
 fs/ext4/file.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 831fd6b..7b206e5 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -481,7 +481,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode,
 		int i, num;
 		unsigned long nr_pages;
 
-		num = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
+		num = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
 		nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
 					  (pgoff_t)num);
 		if (nr_pages == 0) {
-- 
2.9.4

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

* Re: [PATCH] ext4: fix off-by-one on max nr_pages in ext4_find_unwritten_pgoff()
  2017-05-21  8:00 [PATCH] ext4: fix off-by-one on max nr_pages in ext4_find_unwritten_pgoff() Eryu Guan
@ 2017-05-23  8:34 ` Jan Kara
  2017-05-24 22:03   ` Theodore Ts'o
  0 siblings, 1 reply; 4+ messages in thread
From: Jan Kara @ 2017-05-23  8:34 UTC (permalink / raw)
  To: Eryu Guan; +Cc: linux-ext4

On Sun 21-05-17 16:00:26, Eryu Guan wrote:
> ext4_find_unwritten_pgoff() is used to search for offset of hole or
> data in page range [index, end] (both inclusive), and the max number
> of pages to search should be at least one, if end == index.
> Otherwise the only page is missed and no hole or data is found,
> which is not correct.
> 
> When block size is smaller than page size, this can be demonstrated
> by preallocating a file with size smaller than page size and writing
> data to the last block. E.g. run this xfs_io command on a 1k block
> size ext4 on x86_64 host.
> 
>   # xfs_io -fc "falloc 0 3k" -c "pwrite 2k 1k" \
>   	    -c "seek -d 0" /mnt/ext4/testfile
>   wrote 1024/1024 bytes at offset 2048
>   1 KiB, 1 ops; 0.0000 sec (42.459 MiB/sec and 43478.2609 ops/sec)
>   Whence  Result
>   DATA    EOF
> 
> Data at offset 2k was missed, and lseek(2) returned ENXIO.
> 
> This is unconvered by generic/285 subtest 07 and 08 on ppc64 host,
> where pagesize is 64k. Because a recent change to generic/285
> reduced the preallocated file size to smaller than 64k.
> 
> Cc: stable@vger.kernel.org # v3.7+
> Signed-off-by: Eryu Guan <eguan@redhat.com>

Yeah, thanks for fixing this! Actually this is a bug introduced by my
recent fixes. Previously, 'end' used to be "one block after the end" and so
the math worked out correctly :-|. You can add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/ext4/file.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/fs/ext4/file.c b/fs/ext4/file.c
> index 831fd6b..7b206e5 100644
> --- a/fs/ext4/file.c
> +++ b/fs/ext4/file.c
> @@ -481,7 +481,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode,
>  		int i, num;
>  		unsigned long nr_pages;
>  
> -		num = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
> +		num = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
>  		nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
>  					  (pgoff_t)num);
>  		if (nr_pages == 0) {
> -- 
> 2.9.4
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

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

* Re: [PATCH] ext4: fix off-by-one on max nr_pages in ext4_find_unwritten_pgoff()
  2017-05-23  8:34 ` Jan Kara
@ 2017-05-24 22:03   ` Theodore Ts'o
  2017-05-27  6:06     ` Eryu Guan
  0 siblings, 1 reply; 4+ messages in thread
From: Theodore Ts'o @ 2017-05-24 22:03 UTC (permalink / raw)
  To: Jan Kara; +Cc: Eryu Guan, linux-ext4

On Tue, May 23, 2017 at 10:34:32AM +0200, Jan Kara wrote:
> > Cc: stable@vger.kernel.org # v3.7+
> > Signed-off-by: Eryu Guan <eguan@redhat.com>
> 
> Yeah, thanks for fixing this! Actually this is a bug introduced by my
> recent fixes. Previously, 'end' used to be "one block after the end" and so
> the math worked out correctly :-|. You can add:
> 
> Reviewed-by: Jan Kara <jack@suse.cz>

Thanks, applied.  (And I've dropped the Cc: stable)

		       	    	    	    - Ted

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

* Re: [PATCH] ext4: fix off-by-one on max nr_pages in ext4_find_unwritten_pgoff()
  2017-05-24 22:03   ` Theodore Ts'o
@ 2017-05-27  6:06     ` Eryu Guan
  0 siblings, 0 replies; 4+ messages in thread
From: Eryu Guan @ 2017-05-27  6:06 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: Jan Kara, Eryu Guan, linux-ext4

Hi Ted,

On Wed, May 24, 2017 at 06:03:40PM -0400, Theodore Ts'o wrote:
> On Tue, May 23, 2017 at 10:34:32AM +0200, Jan Kara wrote:
> > > Cc: stable@vger.kernel.org # v3.7+
> > > Signed-off-by: Eryu Guan <eguan@redhat.com>
> > 
> > Yeah, thanks for fixing this! Actually this is a bug introduced by my
> > recent fixes. Previously, 'end' used to be "one block after the end" and so
> > the math worked out correctly :-|. You can add:
> > 
> > Reviewed-by: Jan Kara <jack@suse.cz>
> 
> Thanks, applied.  (And I've dropped the Cc: stable)

(Sorry for the late response, not sure why my redhat account didn't get
this email, and my gmail account just got this mail today..)

Actually this is an old bug and can be reproduced without Jan's
patchset. So I think "Cc: stable" is still needed.

Thanks,
Eryu

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

end of thread, other threads:[~2017-05-27  6:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-21  8:00 [PATCH] ext4: fix off-by-one on max nr_pages in ext4_find_unwritten_pgoff() Eryu Guan
2017-05-23  8:34 ` Jan Kara
2017-05-24 22:03   ` Theodore Ts'o
2017-05-27  6:06     ` Eryu Guan

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.