In preparation for moving DAX pages to be 0-based rather than 1-based for the idle refcount, the fsdax core wants to have all mappings in a "zapped" state before truncate. For typical pages this happens naturally via unmap_mapping_range(), for DAX pages some help is needed to record this state in the 'struct address_space' of the inode(s) where the page is mapped. That "zapped" state is recorded in DAX entries as a side effect of ext4_break_layouts(). Arrange for it to be called before all truncation events which already happens for truncate() and PUNCH_HOLE, but not truncate_inode_pages_final(). Arrange for ext4_break_layouts() before truncate_inode_pages_final(). Cc: Matthew Wilcox <willy@xxxxxxxxxxxxx> Cc: Jan Kara <jack@xxxxxxx> Cc: "Darrick J. Wong" <djwong@xxxxxxxxxx> Cc: Jason Gunthorpe <jgg@xxxxxxxxxx> Cc: Christoph Hellwig <hch@xxxxxx> Cc: John Hubbard <jhubbard@xxxxxxxxxx> Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx> --- fs/ext4/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 478ec6bc0935..326269ad3961 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -207,7 +207,11 @@ void ext4_evict_inode(struct inode *inode) jbd2_complete_transaction(journal, commit_tid); filemap_write_and_wait(&inode->i_data); } + + filemap_invalidate_lock(inode->i_mapping); + ext4_break_layouts(inode); truncate_inode_pages_final(&inode->i_data); + filemap_invalidate_unlock(inode->i_mapping); goto no_delete; } @@ -218,7 +222,11 @@ void ext4_evict_inode(struct inode *inode) if (ext4_should_order_data(inode)) ext4_begin_ordered_truncate(inode, 0); + + filemap_invalidate_lock(inode->i_mapping); + ext4_break_layouts(inode); truncate_inode_pages_final(&inode->i_data); + filemap_invalidate_unlock(inode->i_mapping); /* * For inodes with journalled data, transaction commit could have