Commit 9998eb70 authored by Chris Mason's avatar Chris Mason

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: default avatarChris Mason <chris.mason@oracle.com>
parent 9b230628
...@@ -6401,18 +6401,23 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -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;
if (reserved)
goto out; 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 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -6495,6 +6500,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
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;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment