Commit 729963a1 authored by Joel Becker's avatar Joel Becker

Merge branch 'cow_readahead' of git://oss.oracle.com/git/tma/linux-2.6 into merge-2

parents 17ae5211 6ea4843f
...@@ -1642,7 +1642,8 @@ static int ocfs2_zero_tail(struct inode *inode, struct buffer_head *di_bh, ...@@ -1642,7 +1642,8 @@ static int ocfs2_zero_tail(struct inode *inode, struct buffer_head *di_bh,
return ret; return ret;
} }
int ocfs2_write_begin_nolock(struct address_space *mapping, int ocfs2_write_begin_nolock(struct file *filp,
struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags, loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata, struct page **pagep, void **fsdata,
struct buffer_head *di_bh, struct page *mmap_page) struct buffer_head *di_bh, struct page *mmap_page)
...@@ -1692,7 +1693,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping, ...@@ -1692,7 +1693,7 @@ int ocfs2_write_begin_nolock(struct address_space *mapping,
mlog_errno(ret); mlog_errno(ret);
goto out; goto out;
} else if (ret == 1) { } else if (ret == 1) {
ret = ocfs2_refcount_cow(inode, di_bh, ret = ocfs2_refcount_cow(inode, filp, di_bh,
wc->w_cpos, wc->w_clen, UINT_MAX); wc->w_cpos, wc->w_clen, UINT_MAX);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
...@@ -1854,7 +1855,7 @@ static int ocfs2_write_begin(struct file *file, struct address_space *mapping, ...@@ -1854,7 +1855,7 @@ static int ocfs2_write_begin(struct file *file, struct address_space *mapping,
*/ */
down_write(&OCFS2_I(inode)->ip_alloc_sem); down_write(&OCFS2_I(inode)->ip_alloc_sem);
ret = ocfs2_write_begin_nolock(mapping, pos, len, flags, pagep, ret = ocfs2_write_begin_nolock(file, mapping, pos, len, flags, pagep,
fsdata, di_bh, NULL); fsdata, di_bh, NULL);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
......
...@@ -48,7 +48,8 @@ int ocfs2_write_end_nolock(struct address_space *mapping, ...@@ -48,7 +48,8 @@ int ocfs2_write_end_nolock(struct address_space *mapping,
loff_t pos, unsigned len, unsigned copied, loff_t pos, unsigned len, unsigned copied,
struct page *page, void *fsdata); struct page *page, void *fsdata);
int ocfs2_write_begin_nolock(struct address_space *mapping, int ocfs2_write_begin_nolock(struct file *filp,
struct address_space *mapping,
loff_t pos, unsigned len, unsigned flags, loff_t pos, unsigned len, unsigned flags,
struct page **pagep, void **fsdata, struct page **pagep, void **fsdata,
struct buffer_head *di_bh, struct page *mmap_page); struct buffer_head *di_bh, struct page *mmap_page);
......
...@@ -360,7 +360,7 @@ static int ocfs2_cow_file_pos(struct inode *inode, ...@@ -360,7 +360,7 @@ static int ocfs2_cow_file_pos(struct inode *inode,
if (!(ext_flags & OCFS2_EXT_REFCOUNTED)) if (!(ext_flags & OCFS2_EXT_REFCOUNTED))
goto out; goto out;
return ocfs2_refcount_cow(inode, fe_bh, cpos, 1, cpos+1); return ocfs2_refcount_cow(inode, NULL, fe_bh, cpos, 1, cpos+1);
out: out:
return status; return status;
...@@ -903,8 +903,8 @@ static int ocfs2_zero_extend_get_range(struct inode *inode, ...@@ -903,8 +903,8 @@ static int ocfs2_zero_extend_get_range(struct inode *inode,
zero_clusters = last_cpos - zero_cpos; zero_clusters = last_cpos - zero_cpos;
if (needs_cow) { if (needs_cow) {
rc = ocfs2_refcount_cow(inode, di_bh, zero_cpos, zero_clusters, rc = ocfs2_refcount_cow(inode, NULL, di_bh, zero_cpos,
UINT_MAX); zero_clusters, UINT_MAX);
if (rc) { if (rc) {
mlog_errno(rc); mlog_errno(rc);
goto out; goto out;
...@@ -2052,6 +2052,7 @@ int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos, ...@@ -2052,6 +2052,7 @@ int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
} }
static int ocfs2_prepare_inode_for_refcount(struct inode *inode, static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
struct file *file,
loff_t pos, size_t count, loff_t pos, size_t count,
int *meta_level) int *meta_level)
{ {
...@@ -2069,7 +2070,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode, ...@@ -2069,7 +2070,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
*meta_level = 1; *meta_level = 1;
ret = ocfs2_refcount_cow(inode, di_bh, cpos, clusters, UINT_MAX); ret = ocfs2_refcount_cow(inode, file, di_bh, cpos, clusters, UINT_MAX);
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
out: out:
...@@ -2077,7 +2078,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode, ...@@ -2077,7 +2078,7 @@ static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
return ret; return ret;
} }
static int ocfs2_prepare_inode_for_write(struct dentry *dentry, static int ocfs2_prepare_inode_for_write(struct file *file,
loff_t *ppos, loff_t *ppos,
size_t count, size_t count,
int appending, int appending,
...@@ -2085,6 +2086,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ...@@ -2085,6 +2086,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
int *has_refcount) int *has_refcount)
{ {
int ret = 0, meta_level = 0; int ret = 0, meta_level = 0;
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode; struct inode *inode = dentry->d_inode;
loff_t saved_pos, end; loff_t saved_pos, end;
...@@ -2140,6 +2142,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry, ...@@ -2140,6 +2142,7 @@ static int ocfs2_prepare_inode_for_write(struct dentry *dentry,
meta_level = -1; meta_level = -1;
ret = ocfs2_prepare_inode_for_refcount(inode, ret = ocfs2_prepare_inode_for_refcount(inode,
file,
saved_pos, saved_pos,
count, count,
&meta_level); &meta_level);
...@@ -2254,7 +2257,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, ...@@ -2254,7 +2257,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
} }
can_do_direct = direct_io; can_do_direct = direct_io;
ret = ocfs2_prepare_inode_for_write(file->f_path.dentry, ppos, ret = ocfs2_prepare_inode_for_write(file, ppos,
iocb->ki_left, appending, iocb->ki_left, appending,
&can_do_direct, &has_refcount); &can_do_direct, &has_refcount);
if (ret < 0) { if (ret < 0) {
...@@ -2373,7 +2376,7 @@ static int ocfs2_splice_to_file(struct pipe_inode_info *pipe, ...@@ -2373,7 +2376,7 @@ static int ocfs2_splice_to_file(struct pipe_inode_info *pipe,
{ {
int ret; int ret;
ret = ocfs2_prepare_inode_for_write(out->f_path.dentry, &sd->pos, ret = ocfs2_prepare_inode_for_write(out, &sd->pos,
sd->total_len, 0, NULL, NULL); sd->total_len, 0, NULL, NULL);
if (ret < 0) { if (ret < 0) {
mlog_errno(ret); mlog_errno(ret);
......
...@@ -59,10 +59,11 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf) ...@@ -59,10 +59,11 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
return ret; return ret;
} }
static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh, static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
struct page *page) struct page *page)
{ {
int ret; int ret;
struct inode *inode = file->f_path.dentry->d_inode;
struct address_space *mapping = inode->i_mapping; struct address_space *mapping = inode->i_mapping;
loff_t pos = page_offset(page); loff_t pos = page_offset(page);
unsigned int len = PAGE_CACHE_SIZE; unsigned int len = PAGE_CACHE_SIZE;
...@@ -111,7 +112,7 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh, ...@@ -111,7 +112,7 @@ static int __ocfs2_page_mkwrite(struct inode *inode, struct buffer_head *di_bh,
if (page->index == last_index) if (page->index == last_index)
len = ((size - 1) & ~PAGE_CACHE_MASK) + 1; len = ((size - 1) & ~PAGE_CACHE_MASK) + 1;
ret = ocfs2_write_begin_nolock(mapping, pos, len, 0, &locked_page, ret = ocfs2_write_begin_nolock(file, mapping, pos, len, 0, &locked_page,
&fsdata, di_bh, page); &fsdata, di_bh, page);
if (ret) { if (ret) {
if (ret != -ENOSPC) if (ret != -ENOSPC)
...@@ -159,7 +160,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -159,7 +160,7 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
*/ */
down_write(&OCFS2_I(inode)->ip_alloc_sem); down_write(&OCFS2_I(inode)->ip_alloc_sem);
ret = __ocfs2_page_mkwrite(inode, di_bh, page); ret = __ocfs2_page_mkwrite(vma->vm_file, di_bh, page);
up_write(&OCFS2_I(inode)->ip_alloc_sem); up_write(&OCFS2_I(inode)->ip_alloc_sem);
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
struct ocfs2_cow_context { struct ocfs2_cow_context {
struct inode *inode; struct inode *inode;
struct file *file;
u32 cow_start; u32 cow_start;
u32 cow_len; u32 cow_len;
struct ocfs2_extent_tree data_et; struct ocfs2_extent_tree data_et;
...@@ -2932,13 +2933,16 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, ...@@ -2932,13 +2933,16 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle,
u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster); u64 new_block = ocfs2_clusters_to_blocks(sb, new_cluster);
struct page *page; struct page *page;
pgoff_t page_index; pgoff_t page_index;
unsigned int from, to; unsigned int from, to, readahead_pages;
loff_t offset, end, map_end; loff_t offset, end, map_end;
struct address_space *mapping = context->inode->i_mapping; struct address_space *mapping = context->inode->i_mapping;
mlog(0, "old_cluster %u, new %u, len %u at offset %u\n", old_cluster, mlog(0, "old_cluster %u, new %u, len %u at offset %u\n", old_cluster,
new_cluster, new_len, cpos); new_cluster, new_len, cpos);
readahead_pages =
(ocfs2_cow_contig_clusters(sb) <<
OCFS2_SB(sb)->s_clustersize_bits) >> PAGE_CACHE_SHIFT;
offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits; offset = ((loff_t)cpos) << OCFS2_SB(sb)->s_clustersize_bits;
end = offset + (new_len << OCFS2_SB(sb)->s_clustersize_bits); end = offset + (new_len << OCFS2_SB(sb)->s_clustersize_bits);
/* /*
...@@ -2969,6 +2973,14 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle, ...@@ -2969,6 +2973,14 @@ static int ocfs2_duplicate_clusters_by_page(handle_t *handle,
if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize) if (PAGE_CACHE_SIZE <= OCFS2_SB(sb)->s_clustersize)
BUG_ON(PageDirty(page)); BUG_ON(PageDirty(page));
if (PageReadahead(page) && context->file) {
page_cache_async_readahead(mapping,
&context->file->f_ra,
context->file,
page, page_index,
readahead_pages);
}
if (!PageUptodate(page)) { if (!PageUptodate(page)) {
ret = block_read_full_page(page, ocfs2_get_block); ret = block_read_full_page(page, ocfs2_get_block);
if (ret) { if (ret) {
...@@ -3409,12 +3421,35 @@ static int ocfs2_replace_cow(struct ocfs2_cow_context *context) ...@@ -3409,12 +3421,35 @@ static int ocfs2_replace_cow(struct ocfs2_cow_context *context)
return ret; return ret;
} }
static void ocfs2_readahead_for_cow(struct inode *inode,
struct file *file,
u32 start, u32 len)
{
struct address_space *mapping;
pgoff_t index;
unsigned long num_pages;
int cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits;
if (!file)
return;
mapping = file->f_mapping;
num_pages = (len << cs_bits) >> PAGE_CACHE_SHIFT;
if (!num_pages)
num_pages = 1;
index = ((loff_t)start << cs_bits) >> PAGE_CACHE_SHIFT;
page_cache_sync_readahead(mapping, &file->f_ra, file,
index, num_pages);
}
/* /*
* Starting at cpos, try to CoW write_len clusters. Don't CoW * Starting at cpos, try to CoW write_len clusters. Don't CoW
* past max_cpos. This will stop when it runs into a hole or an * past max_cpos. This will stop when it runs into a hole or an
* unrefcounted extent. * unrefcounted extent.
*/ */
static int ocfs2_refcount_cow_hunk(struct inode *inode, static int ocfs2_refcount_cow_hunk(struct inode *inode,
struct file *file,
struct buffer_head *di_bh, struct buffer_head *di_bh,
u32 cpos, u32 write_len, u32 max_cpos) u32 cpos, u32 write_len, u32 max_cpos)
{ {
...@@ -3443,6 +3478,8 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, ...@@ -3443,6 +3478,8 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
BUG_ON(cow_len == 0); BUG_ON(cow_len == 0);
ocfs2_readahead_for_cow(inode, file, cow_start, cow_len);
context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS); context = kzalloc(sizeof(struct ocfs2_cow_context), GFP_NOFS);
if (!context) { if (!context) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -3464,6 +3501,7 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, ...@@ -3464,6 +3501,7 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
context->ref_root_bh = ref_root_bh; context->ref_root_bh = ref_root_bh;
context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page; context->cow_duplicate_clusters = ocfs2_duplicate_clusters_by_page;
context->get_clusters = ocfs2_di_get_clusters; context->get_clusters = ocfs2_di_get_clusters;
context->file = file;
ocfs2_init_dinode_extent_tree(&context->data_et, ocfs2_init_dinode_extent_tree(&context->data_et,
INODE_CACHE(inode), di_bh); INODE_CACHE(inode), di_bh);
...@@ -3492,6 +3530,7 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode, ...@@ -3492,6 +3530,7 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
* clusters between cpos and cpos+write_len are safe to modify. * clusters between cpos and cpos+write_len are safe to modify.
*/ */
int ocfs2_refcount_cow(struct inode *inode, int ocfs2_refcount_cow(struct inode *inode,
struct file *file,
struct buffer_head *di_bh, struct buffer_head *di_bh,
u32 cpos, u32 write_len, u32 max_cpos) u32 cpos, u32 write_len, u32 max_cpos)
{ {
...@@ -3511,7 +3550,7 @@ int ocfs2_refcount_cow(struct inode *inode, ...@@ -3511,7 +3550,7 @@ int ocfs2_refcount_cow(struct inode *inode,
num_clusters = write_len; num_clusters = write_len;
if (ext_flags & OCFS2_EXT_REFCOUNTED) { if (ext_flags & OCFS2_EXT_REFCOUNTED) {
ret = ocfs2_refcount_cow_hunk(inode, di_bh, cpos, ret = ocfs2_refcount_cow_hunk(inode, file, di_bh, cpos,
num_clusters, max_cpos); num_clusters, max_cpos);
if (ret) { if (ret) {
mlog_errno(ret); mlog_errno(ret);
......
...@@ -52,7 +52,8 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode, ...@@ -52,7 +52,8 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
u32 clusters, u32 clusters,
int *credits, int *credits,
int *ref_blocks); int *ref_blocks);
int ocfs2_refcount_cow(struct inode *inode, struct buffer_head *di_bh, int ocfs2_refcount_cow(struct inode *inode,
struct file *filep, struct buffer_head *di_bh,
u32 cpos, u32 write_len, u32 max_cpos); u32 cpos, u32 write_len, u32 max_cpos);
typedef int (ocfs2_post_refcount_func)(struct inode *inode, typedef int (ocfs2_post_refcount_func)(struct inode *inode,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment