add patch fix-off-by-one-when-writing-back-pages-before-dio-read
[ext4-patch-queue.git] / fix-off-by-one-on-max-nr_pages-inext4_find_unwritten_pgoff
blobde537744cc6bba1ce29540bed1053e49ad514734
1 ext4: fix off-by-one on max nr_pages in ext4_find_unwritten_pgoff()
3 From: Eryu Guan <eguan@redhat.com>
5 ext4_find_unwritten_pgoff() is used to search for offset of hole or
6 data in page range [index, end] (both inclusive), and the max number
7 of pages to search should be at least one, if end == index.
8 Otherwise the only page is missed and no hole or data is found,
9 which is not correct.
11 When block size is smaller than page size, this can be demonstrated
12 by preallocating a file with size smaller than page size and writing
13 data to the last block. E.g. run this xfs_io command on a 1k block
14 size ext4 on x86_64 host.
16   # xfs_io -fc "falloc 0 3k" -c "pwrite 2k 1k" \
17             -c "seek -d 0" /mnt/ext4/testfile
18   wrote 1024/1024 bytes at offset 2048
19   1 KiB, 1 ops; 0.0000 sec (42.459 MiB/sec and 43478.2609 ops/sec)
20   Whence  Result
21   DATA    EOF
23 Data at offset 2k was missed, and lseek(2) returned ENXIO.
25 This is unconvered by generic/285 subtest 07 and 08 on ppc64 host,
26 where pagesize is 64k. Because a recent change to generic/285
27 reduced the preallocated file size to smaller than 64k.
29 Signed-off-by: Eryu Guan <eguan@redhat.com>
30 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
31 Reviewed-by: Jan Kara <jack@suse.cz>
32 ---
33  fs/ext4/file.c | 2 +-
34  1 file changed, 1 insertion(+), 1 deletion(-)
36 diff --git a/fs/ext4/file.c b/fs/ext4/file.c
37 index 831fd6b..7b206e5 100644
38 --- a/fs/ext4/file.c
39 +++ b/fs/ext4/file.c
40 @@ -481,7 +481,7 @@ static int ext4_find_unwritten_pgoff(struct inode *inode,
41                 int i, num;
42                 unsigned long nr_pages;
44 -               num = min_t(pgoff_t, end - index, PAGEVEC_SIZE);
45 +               num = min_t(pgoff_t, end - index, PAGEVEC_SIZE - 1) + 1;
46                 nr_pages = pagevec_lookup(&pvec, inode->i_mapping, index,
47                                           (pgoff_t)num);
48                 if (nr_pages == 0) {
49 -- 
50 2.9.4