forked from Minki/linux
Btrfs: fix reservations in btrfs_page_mkwrite
Josef fixed btrfs_page_mkwrite to properly release reserved extents if there was an error. But if we fail to get a reservation and we fail to dirty the inode (for ENOSPC reasons), we'll end up trying to release a reservation we never had. This makes sure we only release if we were able to reserve. Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
9b23062840
commit
9998eb7034
@ -6401,18 +6401,23 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|||||||
unsigned long zero_start;
|
unsigned long zero_start;
|
||||||
loff_t size;
|
loff_t size;
|
||||||
int ret;
|
int ret;
|
||||||
|
int reserved = 0;
|
||||||
u64 page_start;
|
u64 page_start;
|
||||||
u64 page_end;
|
u64 page_end;
|
||||||
|
|
||||||
ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
|
ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
ret = btrfs_update_time(vma->vm_file);
|
ret = btrfs_update_time(vma->vm_file);
|
||||||
|
reserved = 1;
|
||||||
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret == -ENOMEM)
|
if (ret == -ENOMEM)
|
||||||
ret = VM_FAULT_OOM;
|
ret = VM_FAULT_OOM;
|
||||||
else /* -ENOSPC, -EIO, etc */
|
else /* -ENOSPC, -EIO, etc */
|
||||||
ret = VM_FAULT_SIGBUS;
|
ret = VM_FAULT_SIGBUS;
|
||||||
goto out;
|
if (reserved)
|
||||||
|
goto out;
|
||||||
|
goto out_noreserve;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
|
ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
|
||||||
@ -6495,6 +6500,7 @@ out_unlock:
|
|||||||
unlock_page(page);
|
unlock_page(page);
|
||||||
out:
|
out:
|
||||||
btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
|
btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
|
||||||
|
out_noreserve:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user