Daniel Dawson <danielcdawson@xxxxxxxxx> writes: > On 11/28/23 10:15 PM, Daniel Dawson wrote: >> When a file is converted from inline to non-inline, it has stale flags until >> sync. > >> Why is this a problem? Because some code will fail under such a condition, for >> example, lseek(..., SEEK_HOLE) will result in ENOENT. > > > Just tested. Still happening on 6.8-rc1. FWIW, I've been looking into a similar issue related with inline-data and delayed allocation. It may however be quite different because it seems to add small block sizes into the mix: https://bugzilla.kernel.org/show_bug.cgi?id=200681 Unfortunately, I'm still trying to find my way around all this code and I can't say I fully understand the whole flow using the reproducer provided in that bugzilla. Bellow, I'm inlining a patch that started as debug patch that I've used to try to understand what was going on. It seems to workaround that bug, but I know it's not a real fix -- I don't yet understand what's going on. Regarding your specific usecase, I can reproduce it and, unfortunately, I don't thing Ted's suggestion will fix it as I don't even see ext4_iomap_begin_report() being executed at all. Anyway, just my 2 cents... let's see if I can come up with something. Cheers, -- Luís diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index d5bd1e3a5d36..d0c3d6fd48de 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -528,7 +528,19 @@ int ext4_readpage_inline(struct inode *inode, struct folio *folio) if (!folio->index) ret = ext4_read_inline_folio(inode, folio); else if (!folio_test_uptodate(folio)) { - folio_zero_segment(folio, 0, folio_size(folio)); + struct buffer_head *bh, *head; + size_t start = 0; + + head = folio_buffers(folio); + if (head) { + bh = head; + do { + if (!buffer_uptodate(bh)) + break; + start += inode->i_sb->s_blocksize; + } while ((bh = bh->b_this_page) != head); + } + folio_zero_segment(folio, start, folio_size(folio)); folio_mark_uptodate(folio); }