Btrfs: fix regression in btrfs_page_mkwrite() from vm_fault_t conversion
PATCH v2 1/1 Btrfs: fix regression in btrfs_page_mkwrite() from vm_fault_t conversion
The vm_fault_t conversion commit introduced a ret2 variable for tracking the integer return values from internal btrfs functions. It was sometimes returning VM_FAULT_LOCKED for pages that were actually invalid and had been removed from the radix. Something like this:
ret2 = btrfs_delalloc_reserve_space() // returns zero on success
lock_page(page)
if (page->mapping != inode->i_mapping)
goto out_unlock;...
out_unlock:
if (!ret2) {
...
return VM_FAULT_LOCKED;
}This ends up triggering this WARNING in btrfs_destroy_inode()
WARN_ON(BTRFS_I(inode)->block_rsv.size);
xfstests generic/095 was able to reliably reproduce the errors.
Since out_unlock: is only used for errors, this fix moves it below the if (!ret2) check we use to return VM_FAULT_LOCKED for success.
---
Changes since v1: don't set the vmfault_t 'ret' to zero, just move our goto taret around around instead.
fs/btrfs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/btrfs/inode.c +2 -1
@@ -9036,13 +9036,14 @@ vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)unlock_extent_cached (io_tree, page_start, page_end, &cached_state); -out_unlock:if (!ret2) {btrfs_delalloc_release_extents (BTRFS_I (inode),PAGE_SIZE , true);sb_end_pagefault (inode->i_sb);extent_changeset_free (data_reserved);return VM_FAULT_LOCKED ; } + +out_unlock:unlock_page (page); out:btrfs_delalloc_release_extents (BTRFS_I (inode),PAGE_SIZE , (ret !=0 ));
Signature · 1 line
2.9.5
Quoted 22 lines · Chris Mason
The
vm_fault_tconversion commit introduced a ret2 variable for tracking the integer return values from internal btrfs functions. It was sometimes returningVM_FAULT_LOCKEDfor pages that were actually invalid and had been removed from the radix. Something like this:ret2 = btrfs_delalloc_reserve_space() // returns zero on success lock_page(page) if (page->mapping != inode->i_mapping) goto out_unlock;...
out_unlock:if (!ret2) { ... return VM_FAULT_LOCKED; }This ends up triggering this WARNING in
btrfs_destroy_inode()WARN_ON(BTRFS_I(inode)->block_rsv.size);
Quoted 7 lines
xfstests generic/095 was able to reliably reproduce the errors.
Since
out_unlock: is only used for errors, this fix moves it below the if (!ret2) check we use to returnVM_FAULT_LOCKEDfor success.Fixes a528a2415087 (btrfs: change return type of btrfs_page_mkwrite to vm_fault_t)Signed-off-by Chris Mason <[email protected]>
also passed the tests here standalone and with the fixup worker fixes.