diff options
author | Andreas Gruenbacher <agruenba@redhat.com> | 2017-06-29 21:43:20 +0300 |
---|---|---|
committer | Darrick J. Wong <darrick.wong@oracle.com> | 2017-07-03 08:46:13 +0300 |
commit | 334fd34d76f237c0ee58dfc400d2c4e34d660544 (patch) | |
tree | 66f3e447de5bc9efc02a7366145ba7730ed49c62 /include/linux/buffer_head.h | |
parent | 7175a11214f02e6184690c17cf5366012b667531 (diff) | |
download | linux-334fd34d76f237c0ee58dfc400d2c4e34d660544.tar.xz |
vfs: Add page_cache_seek_hole_data helper
Both ext4 and xfs implement seeking for the next hole or piece of data
in unwritten extents by scanning the page cache, and both versions share
the same bug when iterating the buffers of a page: the start offset into
the page isn't taken into account, so when a page fits more than two
filesystem blocks, things will go wrong. For example, on a filesystem
with a block size of 1k, the following command will fail:
xfs_io -f -c "falloc 0 4k" \
-c "pwrite 1k 1k" \
-c "pwrite 3k 1k" \
-c "seek -a -r 0" foo
In this example, neither lseek(fd, 1024, SEEK_HOLE) nor lseek(fd, 2048,
SEEK_DATA) will return the correct result.
Introduce a generic vfs helper for seeking in the page cache that gets
this right. The next commits will replace the filesystem specific
implementations.
Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
[hch: dropped the export]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Diffstat (limited to 'include/linux/buffer_head.h')
-rw-r--r-- | include/linux/buffer_head.h | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index bd029e52ef5e..ad4e024ce17e 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -201,6 +201,8 @@ void write_boundary_block(struct block_device *bdev, sector_t bblock, unsigned blocksize); int bh_uptodate_or_lock(struct buffer_head *bh); int bh_submit_read(struct buffer_head *bh); +loff_t page_cache_seek_hole_data(struct inode *inode, loff_t offset, + loff_t length, int whence); extern int buffer_heads_over_limit; |