aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2012-01-25 13:47:40 -0500
committerChris Mason <chris.mason@oracle.com>2012-01-27 10:44:44 -0500
commit9998eb703490589c3e8f1bf09b15203156776edb (patch)
tree5d01f0e7efae049b9be80292c93fe30f11eeefd1 /fs
parent9b23062840e7c685ef0a0b561285d6e3a3b6811b (diff)
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/inode.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5977987abdb..7405753ec5d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6401,18 +6401,23 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
6401 unsigned long zero_start; 6401 unsigned long zero_start;
6402 loff_t size; 6402 loff_t size;
6403 int ret; 6403 int ret;
6404 int reserved = 0;
6404 u64 page_start; 6405 u64 page_start;
6405 u64 page_end; 6406 u64 page_end;
6406 6407
6407 ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); 6408 ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
6408 if (!ret) 6409 if (!ret) {
6409 ret = btrfs_update_time(vma->vm_file); 6410 ret = btrfs_update_time(vma->vm_file);
6411 reserved = 1;
6412 }
6410 if (ret) { 6413 if (ret) {
6411 if (ret == -ENOMEM) 6414 if (ret == -ENOMEM)
6412 ret = VM_FAULT_OOM; 6415 ret = VM_FAULT_OOM;
6413 else /* -ENOSPC, -EIO, etc */ 6416 else /* -ENOSPC, -EIO, etc */
6414 ret = VM_FAULT_SIGBUS; 6417 ret = VM_FAULT_SIGBUS;
6415 goto out; 6418 if (reserved)
6419 goto out;
6420 goto out_noreserve;
6416 } 6421 }
6417 6422
6418 ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */ 6423 ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */
@@ -6495,6 +6500,7 @@ out_unlock:
6495 unlock_page(page); 6500 unlock_page(page);
6496out: 6501out:
6497 btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); 6502 btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE);
6503out_noreserve:
6498 return ret; 6504 return ret;
6499} 6505}
6500 6506