diff options
author | Chandan Rajendra <chandan@linux.vnet.ibm.com> | 2016-01-21 05:25:57 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-02-01 13:24:29 -0500 |
commit | d0b7da88f6409c740435712b092a8e2c7d2a8f74 (patch) | |
tree | e46c6e2d75f7290188e4bec6d9f37b119aaff554 /fs/btrfs/inode.c | |
parent | 9703fefe0b137bb4475187b5d82ec5823445616b (diff) |
Btrfs: btrfs_page_mkwrite: Reserve space in sectorsized units
In subpagesize-blocksize scenario, if i_size occurs in a block which is not
the last block in the page, then the space to be reserved should be calculated
appropriately.
Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0bfd7fb2e83c..ad27f5d1a4a1 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -8802,15 +8802,28 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
8802 | loff_t size; | 8802 | loff_t size; |
8803 | int ret; | 8803 | int ret; |
8804 | int reserved = 0; | 8804 | int reserved = 0; |
8805 | u64 reserved_space; | ||
8805 | u64 page_start; | 8806 | u64 page_start; |
8806 | u64 page_end; | 8807 | u64 page_end; |
8808 | u64 end; | ||
8809 | |||
8810 | reserved_space = PAGE_CACHE_SIZE; | ||
8807 | 8811 | ||
8808 | sb_start_pagefault(inode->i_sb); | 8812 | sb_start_pagefault(inode->i_sb); |
8809 | page_start = page_offset(page); | 8813 | page_start = page_offset(page); |
8810 | page_end = page_start + PAGE_CACHE_SIZE - 1; | 8814 | page_end = page_start + PAGE_CACHE_SIZE - 1; |
8815 | end = page_end; | ||
8811 | 8816 | ||
8817 | /* | ||
8818 | * Reserving delalloc space after obtaining the page lock can lead to | ||
8819 | * deadlock. For example, if a dirty page is locked by this function | ||
8820 | * and the call to btrfs_delalloc_reserve_space() ends up triggering | ||
8821 | * dirty page write out, then the btrfs_writepage() function could | ||
8822 | * end up waiting indefinitely to get a lock on the page currently | ||
8823 | * being processed by btrfs_page_mkwrite() function. | ||
8824 | */ | ||
8812 | ret = btrfs_delalloc_reserve_space(inode, page_start, | 8825 | ret = btrfs_delalloc_reserve_space(inode, page_start, |
8813 | PAGE_CACHE_SIZE); | 8826 | reserved_space); |
8814 | if (!ret) { | 8827 | if (!ret) { |
8815 | ret = file_update_time(vma->vm_file); | 8828 | ret = file_update_time(vma->vm_file); |
8816 | reserved = 1; | 8829 | reserved = 1; |
@@ -8844,7 +8857,7 @@ again: | |||
8844 | * we can't set the delalloc bits if there are pending ordered | 8857 | * we can't set the delalloc bits if there are pending ordered |
8845 | * extents. Drop our locks and wait for them to finish | 8858 | * extents. Drop our locks and wait for them to finish |
8846 | */ | 8859 | */ |
8847 | ordered = btrfs_lookup_ordered_extent(inode, page_start); | 8860 | ordered = btrfs_lookup_ordered_range(inode, page_start, page_end); |
8848 | if (ordered) { | 8861 | if (ordered) { |
8849 | unlock_extent_cached(io_tree, page_start, page_end, | 8862 | unlock_extent_cached(io_tree, page_start, page_end, |
8850 | &cached_state, GFP_NOFS); | 8863 | &cached_state, GFP_NOFS); |
@@ -8854,6 +8867,18 @@ again: | |||
8854 | goto again; | 8867 | goto again; |
8855 | } | 8868 | } |
8856 | 8869 | ||
8870 | if (page->index == ((size - 1) >> PAGE_CACHE_SHIFT)) { | ||
8871 | reserved_space = round_up(size - page_start, root->sectorsize); | ||
8872 | if (reserved_space < PAGE_CACHE_SIZE) { | ||
8873 | end = page_start + reserved_space - 1; | ||
8874 | spin_lock(&BTRFS_I(inode)->lock); | ||
8875 | BTRFS_I(inode)->outstanding_extents++; | ||
8876 | spin_unlock(&BTRFS_I(inode)->lock); | ||
8877 | btrfs_delalloc_release_space(inode, page_start, | ||
8878 | PAGE_CACHE_SIZE - reserved_space); | ||
8879 | } | ||
8880 | } | ||
8881 | |||
8857 | /* | 8882 | /* |
8858 | * XXX - page_mkwrite gets called every time the page is dirtied, even | 8883 | * XXX - page_mkwrite gets called every time the page is dirtied, even |
8859 | * if it was already dirty, so for space accounting reasons we need to | 8884 | * if it was already dirty, so for space accounting reasons we need to |
@@ -8861,12 +8886,12 @@ again: | |||
8861 | * is probably a better way to do this, but for now keep consistent with | 8886 | * is probably a better way to do this, but for now keep consistent with |
8862 | * prepare_pages in the normal write path. | 8887 | * prepare_pages in the normal write path. |
8863 | */ | 8888 | */ |
8864 | clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, page_end, | 8889 | clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start, end, |
8865 | EXTENT_DIRTY | EXTENT_DELALLOC | | 8890 | EXTENT_DIRTY | EXTENT_DELALLOC | |
8866 | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, | 8891 | EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, |
8867 | 0, 0, &cached_state, GFP_NOFS); | 8892 | 0, 0, &cached_state, GFP_NOFS); |
8868 | 8893 | ||
8869 | ret = btrfs_set_extent_delalloc(inode, page_start, page_end, | 8894 | ret = btrfs_set_extent_delalloc(inode, page_start, end, |
8870 | &cached_state); | 8895 | &cached_state); |
8871 | if (ret) { | 8896 | if (ret) { |
8872 | unlock_extent_cached(io_tree, page_start, page_end, | 8897 | unlock_extent_cached(io_tree, page_start, page_end, |
@@ -8905,7 +8930,7 @@ out_unlock: | |||
8905 | } | 8930 | } |
8906 | unlock_page(page); | 8931 | unlock_page(page); |
8907 | out: | 8932 | out: |
8908 | btrfs_delalloc_release_space(inode, page_start, PAGE_CACHE_SIZE); | 8933 | btrfs_delalloc_release_space(inode, page_start, reserved_space); |
8909 | out_noreserve: | 8934 | out_noreserve: |
8910 | sb_end_pagefault(inode->i_sb); | 8935 | sb_end_pagefault(inode->i_sb); |
8911 | return ret; | 8936 | return ret; |