Commit 2932f3ec authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Btrfs: when forced to cow for file_write, get the page uptodate first

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 79b2cb1f
...@@ -1268,6 +1268,8 @@ static int prepare_pages(struct btrfs_trans_handle *trans, ...@@ -1268,6 +1268,8 @@ static int prepare_pages(struct btrfs_trans_handle *trans,
struct page **pages, struct page **pages,
size_t num_pages, size_t num_pages,
loff_t pos, loff_t pos,
unsigned long first_index,
unsigned long last_index,
size_t write_bytes) size_t write_bytes)
{ {
int i; int i;
...@@ -1289,6 +1291,13 @@ static int prepare_pages(struct btrfs_trans_handle *trans, ...@@ -1289,6 +1291,13 @@ static int prepare_pages(struct btrfs_trans_handle *trans,
} }
offset = pos & (PAGE_CACHE_SIZE -1); offset = pos & (PAGE_CACHE_SIZE -1);
this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); this_write = min(PAGE_CACHE_SIZE - offset, write_bytes);
if (!PageUptodate(pages[i]) &&
(pages[i]->index == first_index ||
pages[i]->index == last_index) && pos < isize) {
ret = mpage_readpage(pages[i], btrfs_get_block);
BUG_ON(ret);
lock_page(pages[i]);
}
ret = nobh_prepare_write(pages[i], offset, ret = nobh_prepare_write(pages[i], offset,
offset + this_write, offset + this_write,
btrfs_get_block); btrfs_get_block);
...@@ -1323,6 +1332,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, ...@@ -1323,6 +1332,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct page *pages[1]; struct page *pages[1];
unsigned long first_index;
unsigned long last_index;
if (file->f_flags & O_DIRECT) if (file->f_flags & O_DIRECT)
return -EINVAL; return -EINVAL;
...@@ -1340,13 +1351,15 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, ...@@ -1340,13 +1351,15 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
goto out; goto out;
file_update_time(file); file_update_time(file);
mutex_lock(&inode->i_mutex); mutex_lock(&inode->i_mutex);
first_index = pos >> PAGE_CACHE_SHIFT;
last_index = (pos + count) >> PAGE_CACHE_SHIFT;
while(count > 0) { while(count > 0) {
size_t offset = pos & (PAGE_CACHE_SIZE - 1); size_t offset = pos & (PAGE_CACHE_SIZE - 1);
size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset);
size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >>
PAGE_CACHE_SHIFT; PAGE_CACHE_SHIFT;
ret = prepare_pages(NULL, root, file, pages, num_pages, ret = prepare_pages(NULL, root, file, pages, num_pages,
pos, write_bytes); pos, first_index, last_index, write_bytes);
BUG_ON(ret); BUG_ON(ret);
ret = btrfs_copy_from_user(pos, num_pages, ret = btrfs_copy_from_user(pos, num_pages,
write_bytes, pages, buf); write_bytes, pages, buf);
......
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