diff options
| -rw-r--r-- | fs/ocfs2/aops.c | 7 | ||||
| -rw-r--r-- | fs/ocfs2/aops.h | 3 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 17 | ||||
| -rw-r--r-- | fs/ocfs2/mmap.c | 7 | ||||
| -rw-r--r-- | fs/ocfs2/refcounttree.c | 43 | ||||
| -rw-r--r-- | fs/ocfs2/refcounttree.h | 3 |
6 files changed, 63 insertions, 17 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index f477f18b35d5..5cfeee118158 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
| @@ -1642,7 +1642,8 @@ static int ocfs2_zero_tail(struct inode *inode, struct buffer_head *di_bh, | |||
| 1642 | return ret; | 1642 | return ret; |
| 1643 | } | 1643 | } |
| 1644 | 1644 | ||
| 1645 | int ocfs2_write_begin_nolock(struct address_space *mapping, | 1645 | int ocfs2_write_begin_nolock(struct file *filp, |
| 1646 | struct address_space *mapping, | ||
| 1646 | loff_t pos, unsigned len, unsigned flags, | 1647 | loff_t pos, unsigned len, unsigned flags, |
| 1647 | struct page **pagep, void **fsdata, | 1648 | struct page **pagep, void **fsdata, |
| 1648 | struct buffer_head *di_bh, struct page *mmap_page) | 1649 | struct buffer_head *di_bh, struct page *mmap_page) |
| @@ -1692,7 +1693,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, | |||
| 1692 | mlog_errno(ret); | 1693 | mlog_errno(ret); |
| 1693 | goto out; | 1694 | goto out; |
| 1694 | } else if (ret == 1) { | 1695 | } else if (ret == 1) { |
| 1695 | ret = ocfs2_refcount_cow(inode, di_bh, | 1696 | ret = ocfs2_refcount_cow(inode, filp, di_bh, |
| 1696 | wc->w_cpos, wc->w_clen, UINT_MAX); | 1697 | wc->w_cpos, wc->w_clen, UINT_MAX); |
| 1697 | if (ret) { | 1698 | if (ret) { |
| 1698 | mlog_errno(ret); | 1699 | mlog_errno(ret); |
| @@ -1854,7 +1855,7 @@ static int ocfs2_write_begin(struct file *file, struct address_space *mapping, | |||
| 1854 | */ | 1855 | */ |
| 1855 | down_write(&OCFS2_I(inode)->ip_alloc_sem); | 1856 | down_write(&OCFS2_I(inode)->ip_alloc_sem); |
| 1856 | 1857 | ||
| 1857 | ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep, | 1858 | ret = ocfs2_write_begin_nolock(file, mapping, pos, len, flags, pagep, |
| 1858 | fsdata, di_bh, NULL); | 1859 | fsdata, di_bh, NULL); |
| 1859 | if (ret) { | 1860 | if (ret) { |
| 1860 | mlog_errno(ret); | 1861 | mlog_errno(ret); |
diff --git a/fs/ocfs2/aops.h b/fs/ocfs2/aops.h index c48e93ffc513..7606f663da6d 100644 --- a/fs/ocfs2/aops.h +++ b/fs/ocfs2/aops.h | |||
| @@ -48,7 +48,8 @@ int ocfs2_write_end_nolock(struct address_space *mapping, | |||
| 48 | loff_t pos, unsigned len, unsigned copied, | 48 | loff_t pos, unsigned len, unsigned copied, |
| 49 | struct page *page, void *fsdata); | 49 | struct page *page, void *fsdata); |
| 50 | 50 | ||
| 51 | int ocfs2_write_begin_nolock(struct address_space *mapping, | 51 | int ocfs2_write_begin_nolock(struct file *filp, |
| 52 | struct address_space *mapping, | ||
| 52 | loff_t pos, unsigned len, unsigned flags, | 53 | loff_t pos, unsigned len, unsigned flags, |
| 53 | struct page **pagep, void **fsdata, | 54 | struct page **pagep, void **fsdata, |
| 54 | struct buffer_head *di_bh, struct page *mmap_page); | 55 | struct buffer_head *di_bh, struct page *mmap_page); |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index b03f6601fd71..9a74542e1a05 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -360,7 +360,7 @@ static int ocfs2_cow_file_pos(struct inode *inode, | |||
| 360 | if (!(ext_flags & OCFS2_EXT_REFCOUNTED)) | 360 | if (!(ext_flags & OCFS2_EXT_REFCOUNTED)) |
| 361 | goto out; | 361 | goto out; |
| 362 | 362 | ||
| 363 | return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1); | 363 | return ocfs2_refcount_cow(inode, NULL, fe_bh, cpos, 1, cpos+1); |
| 364 | 364 | ||
| 365 | out: | 365 | out: |
| 366 | return status; | 366 | return status; |
| @@ -903,8 +903,8 @@ static int ocfs2_zero_extend_get_range(struct inode *inode, | |||
| 903 | zero_clusters = last_cpos - zero_cpos; | 903 | zero_clusters = last_cpos - zero_cpos; |
| 904 | 904 | ||
| 905 | if (needs_cow) { | 905 | if (needs_cow) { |
| 906 | rc = ocfs2_refcount_cow(inode, di_bh, zero_cpos, zero_clusters, | 906 | rc = ocfs2_refcount_cow(inode, NULL, di_bh, zero_cpos, |
| 907 | UINT_MAX); | 907 | zero_clusters, UINT_MAX); |
| 908 | if (rc) { | 908 | if (rc) { |
| 909 | mlog_errno(rc); | 909 | mlog_errno(rc); |
| 910 | goto out; | 910 | goto out; |
| @@ -2052,6 +2052,7 @@ out: | |||
| 2052 | } | 2052 | } |
| 2053 | 2053 | ||
| 2054 | static int ocfs2_prepare_inode_for_refcount(struct inode *inode, | 2054 | static int ocfs2_prepare_inode_for_refcount(struct inode *inode, |
| 2055 | struct file *file, | ||
| 2055 | loff_t pos, size_t count, | 2056 | loff_t pos, size_t count, |
| 2056 | int *meta_level) | 2057 | int *meta_level) |
| 2057 | { | 2058 | { |
| @@ -2069,7 +2070,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode, | |||
| 2069 | 2070 | ||
| 2070 | *meta_level = 1; | 2071 | *meta_level = 1; |
| 2071 | 2072 | ||
| 2072 | ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX); | 2073 | ret = ocfs2_refcount_cow(inode, file, di_bh, cpos, clusters, UINT_MAX); |
| 2073 | if (ret) | 2074 | if (ret) |
| 2074 | mlog_errno(ret); | 2075 | mlog_errno(ret); |
| 2075 | out: | 2076 | out: |
| @@ -2077,7 +2078,7 @@ out: | |||
| 2077 | return ret; | 2078 | return ret; |
| 2078 | } | 2079 | } |
| 2079 | 2080 | ||
| 2080 | static int ocfs2_prepare_inode_for_write(struct dentry *dentry, | 2081 | static int ocfs2_prepare_inode_for_write(struct file *file, |
| 2081 | loff_t *ppos, | 2082 | loff_t *ppos, |
| 2082 | size_t count, | 2083 | size_t count, |
| 2083 | int appending, | 2084 | int appending, |
| @@ -2085,6 +2086,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, | |||
| 2085 | int *has_refcount) | 2086 | int *has_refcount) |
| 2086 | { | 2087 | { |
| 2087 | int ret = 0, meta_level = 0; | 2088 | int ret = 0, meta_level = 0; |
| 2089 | struct dentry *dentry = file->f_path.dentry; | ||
| 2088 | struct inode *inode = dentry->d_inode; | 2090 | struct inode *inode = dentry->d_inode; |
| 2089 | loff_t saved_pos, end; | 2091 | loff_t saved_pos, end; |
| 2090 | 2092 | ||
| @@ -2140,6 +2142,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, | |||
| 2140 | meta_level = -1; | 2142 | meta_level = -1; |
| 2141 | 2143 | ||
| 2142 | ret = ocfs2_prepare_inode_for_refcount(inode, | 2144 | ret = ocfs2_prepare_inode_for_refcount(inode, |
| 2145 | file, | ||
| 2143 | saved_pos, | 2146 | saved_pos, |
| 2144 | count, | 2147 | count, |
| 2145 | &meta_level); | 2148 | &meta_level); |
| @@ -2254,7 +2257,7 @@ relock: | |||
| 2254 | } | 2257 | } |
| 2255 | 2258 | ||
| 2256 | can_do_direct = direct_io; | 2259 | can_do_direct = direct_io; |
| 2257 | ret = ocfs2_prepare_inode_for_write(file->f_path.dentry, ppos, | 2260 | ret = ocfs2_prepare_inode_for_write(file, ppos, |
| 2258 | iocb->ki_left, appending, | 2261 | iocb->ki_left, appending, |
| 2259 | &can_do_direct, &has_refcount); | 2262 | &can_do_direct, &has_refcount); |
| 2260 | if (ret < 0) { | 2263 | if (ret < 0) { |
| @@ -2373,7 +2376,7 @@ static int ocfs2_splice_to_file(struct pipe_inode_info *pipe, | |||
| 2373 | { | 2376 | { |
| 2374 | int ret; | 2377 | int ret; |
| 2375 | 2378 | ||
| 2376 | ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos, | 2379 | ret = ocfs2_prepare_inode_for_write(out, &sd->pos, |
| 2377 | sd->total_len, 0, NULL, NULL); | 2380 | sd->total_len, 0, NULL, NULL); |
| 2378 | if (ret < 0) { | 2381 | if (ret < 0) { |
| 2379 | mlog_errno(ret); | 2382 | mlog_errno(ret); |
diff --git a/fs/ocfs2/mmap.c b/fs/ocfs2/mmap.c index 4c18f4ad93b4..7e32db9c2c99 100644 --- a/fs/ocfs2/mmap.c +++ b/fs/ocfs2/mmap.c | |||
| @@ -59,10 +59,11 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) | |||
| 59 | return ret; | 59 | return ret; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh, | 62 | static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh, |
| 63 | struct page *page) | 63 | struct page *page) |
| 64 | { | 64 | { |
| 65 | int ret; | 65 | int ret; |
| 66 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 66 | struct address_space *mapping = inode->i_mapping; | 67 | struct address_space *mapping = inode->i_mapping; |
| 67 | loff_t pos = page_offset(page); | 68 | loff_t pos = page_offset(page); |
| 68 | unsigned int len = PAGE_CACHE_SIZE; | 69 | unsigned int len = PAGE_CACHE_SIZE; |
| @@ -111,7 +112,7 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh, | |||
| 111 | if (page->index == last_index) | 112 | if (page->index == last_index) |
| 112 | len = ((size - 1) & ~PAGE_CACHE_MASK) + 1; | 113 | len = ((size - 1) & ~PAGE_CACHE_MASK) + 1; |
| 113 | 114 | ||
| 114 | ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page, | 115 | ret = ocfs2_write_begin_nolock(file, mapping, pos, len, 0, &locked_page, |
| 115 | &fsdata, di_bh, page); | 116 | &fsdata, di_bh, page); |
| 116 | if (ret) { | 117 | if (ret) { |
| 117 | if (ret != -ENOSPC) | 118 | if (ret != -ENOSPC) |
| @@ -159,7 +160,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 159 | */ | 160 | */ |
| 160 | down_write(&OCFS2_I(inode)->ip_alloc_sem); | 161 | down_write(&OCFS2_I(inode)->ip_alloc_sem); |
| 161 | 162 | ||
| 162 | ret = __ocfs2_page_mkwrite(inode, di_bh, page); | 163 | ret = __ocfs2_page_mkwrite(vma->vm_file, di_bh, page); |
| 163 | 164 | ||
| 164 | up_write(&OCFS2_I(inode)->ip_alloc_sem); | 165 | up_write(&OCFS2_I(inode)->ip_alloc_sem); |
| 165 | 166 | ||
diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c index 0afeda83120f..a120cfcf69bf 100644 --- a/fs/ocfs2/refcounttree.c +++ b/fs/ocfs2/refcounttree.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | 49 | ||
| 50 | struct ocfs2_cow_context { | 50 | struct ocfs2_cow_context { |
| 51 | struct inode *inode; | 51 | struct inode *inode; |
| 52 | struct file *file; | ||
| 52 | u32 cow_start; | 53 | u32 cow_start; |
| 53 | u32 cow_len; | 54 | u32 cow_len; |
| 54 | struct ocfs2_extent_tree data_et; | 55 | struct ocfs2_extent_tree data_et; |
| @@ -2932,13 +2933,16 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, | |||
| 2932 | u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); | 2933 | u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); |
| 2933 | struct page *page; | 2934 | struct page *page; |
| 2934 | pgoff_t page_index; | 2935 | pgoff_t page_index; |
| 2935 | unsigned int from, to; | 2936 | unsigned int from, to, readahead_pages; |
| 2936 | loff_t offset, end, map_end; | 2937 | loff_t offset, end, map_end; |
| 2937 | struct address_space *mapping = context->inode->i_mapping; | 2938 | struct address_space *mapping = context->inode->i_mapping; |
| 2938 | 2939 | ||
| 2939 | mlog(0, "old_cluster %u, new %u, len %u at offset %u\n", old_cluster, | 2940 | mlog(0, "old_cluster %u, new %u, len %u at offset %u\n", old_cluster, |
| 2940 | new_cluster, new_len, cpos); | 2941 | new_cluster, new_len, cpos); |
| 2941 | 2942 | ||
| 2943 | readahead_pages = | ||
| 2944 | (ocfs2_cow_contig_clusters(sb) << | ||
| 2945 | OCFS2_SB(sb)->s_clustersize_bits) >> PAGE_CACHE_SHIFT; | ||
| 2942 | offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits; | 2946 | offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits; |
| 2943 | end = offset + (new_len << OCFS2_SB(sb)->s_clustersize_bits); | 2947 | end = offset + (new_len << OCFS2_SB(sb)->s_clustersize_bits); |
| 2944 | /* | 2948 | /* |
| @@ -2969,6 +2973,14 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, | |||
| 2969 | if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize) | 2973 | if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize) |
| 2970 | BUG_ON(PageDirty(page)); | 2974 | BUG_ON(PageDirty(page)); |
| 2971 | 2975 | ||
| 2976 | if (PageReadahead(page) && context->file) { | ||
| 2977 | page_cache_async_readahead(mapping, | ||
| 2978 | &context->file->f_ra, | ||
| 2979 | context->file, | ||
| 2980 | page, page_index, | ||
| 2981 | readahead_pages); | ||
| 2982 | } | ||
| 2983 | |||
| 2972 | if (!PageUptodate(page)) { | 2984 | if (!PageUptodate(page)) { |
| 2973 | ret = block_read_full_page(page, ocfs2_get_block); | 2985 | ret = block_read_full_page(page, ocfs2_get_block); |
| 2974 | if (ret) { | 2986 | if (ret) { |
| @@ -3409,12 +3421,35 @@ static int ocfs2_replace_cow(struct ocfs2_cow_context *context) | |||
| 3409 | return ret; | 3421 | return ret; |
| 3410 | } | 3422 | } |
| 3411 | 3423 | ||
| 3424 | static void ocfs2_readahead_for_cow(struct inode *inode, | ||
| 3425 | struct file *file, | ||
| 3426 | u32 start, u32 len) | ||
| 3427 | { | ||
| 3428 | struct address_space *mapping; | ||
| 3429 | pgoff_t index; | ||
| 3430 | unsigned long num_pages; | ||
| 3431 | int cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits; | ||
| 3432 | |||
| 3433 | if (!file) | ||
| 3434 | return; | ||
| 3435 | |||
| 3436 | mapping = file->f_mapping; | ||
| 3437 | num_pages = (len << cs_bits) >> PAGE_CACHE_SHIFT; | ||
| 3438 | if (!num_pages) | ||
| 3439 | num_pages = 1; | ||
| 3440 | |||
| 3441 | index = ((loff_t)start << cs_bits) >> PAGE_CACHE_SHIFT; | ||
| 3442 | page_cache_sync_readahead(mapping, &file->f_ra, file, | ||
| 3443 | index, num_pages); | ||
| 3444 | } | ||
| 3445 | |||
| 3412 | /* | 3446 | /* |
| 3413 | * Starting at cpos, try to CoW write_len clusters. Don't CoW | 3447 | * Starting at cpos, try to CoW write_len clusters. Don't CoW |
| 3414 | * past max_cpos. This will stop when it runs into a hole or an | 3448 | * past max_cpos. This will stop when it runs into a hole or an |
| 3415 | * unrefcounted extent. | 3449 | * unrefcounted extent. |
| 3416 | */ | 3450 | */ |
| 3417 | static int ocfs2_refcount_cow_hunk(struct inode *inode, | 3451 | static int ocfs2_refcount_cow_hunk(struct inode *inode, |
| 3452 | struct file *file, | ||
| 3418 | struct buffer_head *di_bh, | 3453 | struct buffer_head *di_bh, |
| 3419 | u32 cpos, u32 write_len, u32 max_cpos) | 3454 | u32 cpos, u32 write_len, u32 max_cpos) |
| 3420 | { | 3455 | { |
| @@ -3443,6 +3478,8 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, | |||
| 3443 | 3478 | ||
| 3444 | BUG_ON(cow_len == 0); | 3479 | BUG_ON(cow_len == 0); |
| 3445 | 3480 | ||
| 3481 | ocfs2_readahead_for_cow(inode, file, cow_start, cow_len); | ||
| 3482 | |||
| 3446 | context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS); | 3483 | context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS); |
| 3447 | if (!context) { | 3484 | if (!context) { |
| 3448 | ret = -ENOMEM; | 3485 | ret = -ENOMEM; |
| @@ -3464,6 +3501,7 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, | |||
| 3464 | context->ref_root_bh = ref_root_bh; | 3501 | context->ref_root_bh = ref_root_bh; |
| 3465 | context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page; | 3502 | context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page; |
| 3466 | context->get_clusters = ocfs2_di_get_clusters; | 3503 | context->get_clusters = ocfs2_di_get_clusters; |
| 3504 | context->file = file; | ||
| 3467 | 3505 | ||
| 3468 | ocfs2_init_dinode_extent_tree(&context->data_et, | 3506 | ocfs2_init_dinode_extent_tree(&context->data_et, |
| 3469 | INODE_CACHE(inode), di_bh); | 3507 | INODE_CACHE(inode), di_bh); |
| @@ -3492,6 +3530,7 @@ out: | |||
| 3492 | * clusters between cpos and cpos+write_len are safe to modify. | 3530 | * clusters between cpos and cpos+write_len are safe to modify. |
| 3493 | */ | 3531 | */ |
| 3494 | int ocfs2_refcount_cow(struct inode *inode, | 3532 | int ocfs2_refcount_cow(struct inode *inode, |
| 3533 | struct file *file, | ||
| 3495 | struct buffer_head *di_bh, | 3534 | struct buffer_head *di_bh, |
| 3496 | u32 cpos, u32 write_len, u32 max_cpos) | 3535 | u32 cpos, u32 write_len, u32 max_cpos) |
| 3497 | { | 3536 | { |
| @@ -3511,7 +3550,7 @@ int ocfs2_refcount_cow(struct inode *inode, | |||
| 3511 | num_clusters = write_len; | 3550 | num_clusters = write_len; |
| 3512 | 3551 | ||
| 3513 | if (ext_flags & OCFS2_EXT_REFCOUNTED) { | 3552 | if (ext_flags & OCFS2_EXT_REFCOUNTED) { |
| 3514 | ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos, | 3553 | ret = ocfs2_refcount_cow_hunk(inode, file, di_bh, cpos, |
| 3515 | num_clusters, max_cpos); | 3554 | num_clusters, max_cpos); |
| 3516 | if (ret) { | 3555 | if (ret) { |
| 3517 | mlog_errno(ret); | 3556 | mlog_errno(ret); |
diff --git a/fs/ocfs2/refcounttree.h b/fs/ocfs2/refcounttree.h index f04892d6175d..c8ce46f7d8e3 100644 --- a/fs/ocfs2/refcounttree.h +++ b/fs/ocfs2/refcounttree.h | |||
| @@ -52,7 +52,8 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode, | |||
| 52 | u32 clusters, | 52 | u32 clusters, |
| 53 | int *credits, | 53 | int *credits, |
| 54 | int *ref_blocks); | 54 | int *ref_blocks); |
| 55 | int ocfs2_refcount_cow(struct inode *inode, struct buffer_head *di_bh, | 55 | int ocfs2_refcount_cow(struct inode *inode, |
| 56 | struct file *filep, struct buffer_head *di_bh, | ||
| 56 | u32 cpos, u32 write_len, u32 max_cpos); | 57 | u32 cpos, u32 write_len, u32 max_cpos); |
| 57 | 58 | ||
| 58 | typedef int (ocfs2_post_refcount_func)(struct inode *inode, | 59 | typedef int (ocfs2_post_refcount_func)(struct inode *inode, |
