diff options
author | Chris Mason <chris.mason@oracle.com> | 2012-01-25 13:47:40 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2012-01-27 10:44:44 -0500 |
commit | 9998eb703490589c3e8f1bf09b15203156776edb (patch) | |
tree | 5d01f0e7efae049b9be80292c93fe30f11eeefd1 /fs | |
parent | 9b23062840e7c685ef0a0b561285d6e3a3b6811b (diff) | |
download | op-kernel-dev-9998eb703490589c3e8f1bf09b15203156776edb.zip op-kernel-dev-9998eb703490589c3e8f1bf09b15203156776edb.tar.gz |
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.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 5977987..7405753 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) unsigned long zero_start; loff_t size; int ret; + int reserved = 0; u64 page_start; u64 page_end; ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); - if (!ret) + if (!ret) { ret = btrfs_update_time(vma->vm_file); + reserved = 1; + } if (ret) { if (ret == -ENOMEM) ret = VM_FAULT_OOM; else /* -ENOSPC, -EIO, etc */ ret = VM_FAULT_SIGBUS; - goto out; + if (reserved) + goto out; + goto out_noreserve; } ret = VM_FAULT_NOPAGE; /* make the VM retry the fault */ @@ -6495,6 +6500,7 @@ out_unlock: unlock_page(page); out: btrfs_delalloc_release_space(inode, PAGE_CACHE_SIZE); +out_noreserve: return ret; } |