This means `iomap_fiemap()` would fail when passed a zero length, which is exactly what was happening for empty ext2 files. **3. Impact Assessment:** - **User-visible impact**: Applications using fiemap on empty ext2 files would receive unexpected EINVAL errors - **Test failure**: The commit references an LTP (Linux Test Project) issue (#1246), indicating this breaks existing tests - **Functional impact**: fiemap is a commonly used interface for discovering file extent mappings, and it should work on empty files (they simply have no extents) **4. Fix Quality:** - **Minimal and contained**: The fix adds only 10 lines of code with a clear comment explaining the rationale - **Safe approach**: Setting i_size to 1 for the length calculation is safe because: - It only affects the length passed to iomap_fiemap - The comment explains this is specifically to avoid EINVAL from iomap_fiemap - The actual file size remains unchanged - **No architectural changes**: This is a simple boundary condition fix **5. Regression Risk:** - **Low risk**: The change only affects the fiemap path for empty files - **Well-tested path**: fiemap is a read-only operation - **Clear boundary**: Only affects files where i_size == 0 **6. Stable Tree Criteria:** This fix meets all the stable tree criteria: - Fixes a real bug that users/tests hit - Small, self-contained change - No new features or architectural changes - Clear fix for a specific problem - Low risk of introducing regressions **7. Similar Patterns:** The comment in the fix mentions that "ext2_get_blocks() iterates unmapped space block by block which is slow" - this suggests the min_t() optimization is important for performance on large sparse files, but shouldn't break functionality for empty files. The fix properly balances maintaining the performance optimization while ensuring correctness for the edge case of empty files. fs/ext2/inode.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 314b415ee518..6ff1f8f29a3c 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -895,9 +895,19 @@ int ext2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { int ret; + loff_t i_size; inode_lock(inode); - len = min_t(u64, len, i_size_read(inode)); + i_size = i_size_read(inode); + /* + * iomap_fiemap() returns EINVAL for 0 length. Make sure we don't trim + * length to 0 but still trim the range as much as possible since + * ext2_get_blocks() iterates unmapped space block by block which is + * slow. + */ + if (i_size == 0) + i_size = 1; + len = min_t(u64, len, i_size); ret = iomap_fiemap(inode, fieinfo, start, len, &ext2_iomap_ops); inode_unlock(inode); -- 2.39.5