- Remove usless condition page_has_buffers(). We already checked that previously. - The goal of ext4_find_unwritten_pgoff() is to distinguish uninitialized data from initialized or delayed ones so check (buffer_uptodate() || buffer_unwritten() is not correct. Data is delayed if bh_uptodate && (bh_delayed || bh_async_write) - Rename ext4_find_unwritten_pgoff -> ext4_find_delayed_pgoff - Fix seek_data/seek_hole for case blk_sz != pg_sz. tested on following configurations xfstest-blk conf: ext3, ext3-1k, ext3-1k-da, 1k, 4k test: generic/285 Signed-off-by: Dmitry Monakhov <dmonakhov@xxxxxxxxxx> --- fs/ext4/file.c | 58 ++++++++++++++++++++++++++++--------------------------- 1 files changed, 30 insertions(+), 28 deletions(-) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 513c12c..8ec48a4 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -273,19 +273,19 @@ static int ext4_file_open(struct inode * inode, struct file * filp) * we determine this extent as a data or a hole according to whether the * page cache has data or not. */ -static int ext4_find_unwritten_pgoff(struct inode *inode, int whence, - loff_t endoff, loff_t *offset) +static int ext4_find_delayed_pgoff(struct inode *inode, int whence, + loff_t endoff, loff_t *offset) { struct pagevec pvec; pgoff_t index; pgoff_t end; loff_t startoff; loff_t lastoff; + loff_t last_data; int found = 0; startoff = *offset; - lastoff = startoff; - + last_data = lastoff = startoff; index = startoff >> PAGE_CACHE_SHIFT; end = endoff >> PAGE_CACHE_SHIFT; @@ -350,30 +350,32 @@ static int ext4_find_unwritten_pgoff(struct inode *inode, int whence, unlock_page(page); continue; } - - if (page_has_buffers(page)) { - lastoff = page_offset(page); - bh = head = page_buffers(page); - do { - if (buffer_uptodate(bh) || - buffer_unwritten(bh)) { - if (whence == SEEK_DATA) - found = 1; - } else { - if (whence == SEEK_HOLE) - found = 1; + lastoff = page_offset(page); + bh = head = page_buffers(page); + do { + if (buffer_uptodate(bh) && + (buffer_dirty(bh) || + buffer_async_write(bh))) { + last_data = lastoff + bh->b_size; + if (whence == SEEK_DATA && + lastoff + bh->b_size > startoff) + found = 1; + } else { + if (whence == SEEK_HOLE && + lastoff + bh->b_size > startoff) { + lastoff = last_data; + found = 1; } - if (found) { - *offset = max_t(loff_t, + } + if (found) { + *offset = max_t(loff_t, startoff, lastoff); - unlock_page(page); - goto out; - } - lastoff += bh->b_size; - bh = bh->b_this_page; - } while (bh != head); - } - + unlock_page(page); + goto out; + } + lastoff += bh->b_size; + bh = bh->b_this_page; + } while (bh != head); lastoff = page_offset(page) + PAGE_SIZE; unlock_page(page); } @@ -450,7 +452,7 @@ static loff_t ext4_seek_data(struct file *file, loff_t offset, loff_t maxsize) * it will be as a data or a hole according to page * cache that has data or not. */ - if (ext4_find_unwritten_pgoff(inode, SEEK_DATA, + if (ext4_find_delayed_pgoff(inode, SEEK_DATA, next, &offset)) goto out; @@ -524,7 +526,7 @@ static loff_t ext4_seek_hole(struct file *file, loff_t offset, loff_t maxsize) * it will be as a data or a hole according to page * cache that has data or not. */ - if (ext4_find_unwritten_pgoff(inode, SEEK_HOLE, + if (ext4_find_delayed_pgoff(inode, SEEK_HOLE, next, &offset)) goto out; -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html