diff options
author | Joel Becker <joel.becker@oracle.com> | 2010-09-10 11:41:04 -0400 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-09-10 11:41:04 -0400 |
commit | 729963a1ff8d069d05dab6a024bfd59805ac622c (patch) | |
tree | 5489aae570960d1908d738913ea581cc1689fbbb /fs | |
parent | 17ae521158d6fe89cfdd00a9990aa40d02e81391 (diff) | |
parent | 6ea4843f53282465f2bdbe5eedde7d8c3081dfdf (diff) |
Merge branch 'cow_readahead' of git://oss.oracle.com/git/tma/linux-2.6 into merge-2
Diffstat (limited to 'fs')
-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, |