aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-04-10 14:22:02 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-04-10 14:22:02 -0400
commit2932f3ec94ff0212313b8187064f93bcb76ce411 (patch)
tree4cebf7d921162046b5920efc4666261de7832ebe /fs/btrfs/super.c
parent79b2cb1fa6430501907cb1384abbddf074833e45 (diff)
Btrfs: when forced to cow for file_write, get the page uptodate first
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r--fs/btrfs/super.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index a3183972f310..b93d790e7484 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1268,6 +1268,8 @@ static int prepare_pages(struct btrfs_trans_handle *trans,
1268 struct page **pages, 1268 struct page **pages,
1269 size_t num_pages, 1269 size_t num_pages,
1270 loff_t pos, 1270 loff_t pos,
1271 unsigned long first_index,
1272 unsigned long last_index,
1271 size_t write_bytes) 1273 size_t write_bytes)
1272{ 1274{
1273 int i; 1275 int i;
@@ -1289,6 +1291,13 @@ static int prepare_pages(struct btrfs_trans_handle *trans,
1289 } 1291 }
1290 offset = pos & (PAGE_CACHE_SIZE -1); 1292 offset = pos & (PAGE_CACHE_SIZE -1);
1291 this_write = min(PAGE_CACHE_SIZE - offset, write_bytes); 1293 this_write = min(PAGE_CACHE_SIZE - offset, write_bytes);
1294 if (!PageUptodate(pages[i]) &&
1295 (pages[i]->index == first_index ||
1296 pages[i]->index == last_index) && pos < isize) {
1297 ret = mpage_readpage(pages[i], btrfs_get_block);
1298 BUG_ON(ret);
1299 lock_page(pages[i]);
1300 }
1292 ret = nobh_prepare_write(pages[i], offset, 1301 ret = nobh_prepare_write(pages[i], offset,
1293 offset + this_write, 1302 offset + this_write,
1294 btrfs_get_block); 1303 btrfs_get_block);
@@ -1323,6 +1332,8 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1323 struct inode *inode = file->f_path.dentry->d_inode; 1332 struct inode *inode = file->f_path.dentry->d_inode;
1324 struct btrfs_root *root = BTRFS_I(inode)->root; 1333 struct btrfs_root *root = BTRFS_I(inode)->root;
1325 struct page *pages[1]; 1334 struct page *pages[1];
1335 unsigned long first_index;
1336 unsigned long last_index;
1326 1337
1327 if (file->f_flags & O_DIRECT) 1338 if (file->f_flags & O_DIRECT)
1328 return -EINVAL; 1339 return -EINVAL;
@@ -1340,13 +1351,15 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
1340 goto out; 1351 goto out;
1341 file_update_time(file); 1352 file_update_time(file);
1342 mutex_lock(&inode->i_mutex); 1353 mutex_lock(&inode->i_mutex);
1354 first_index = pos >> PAGE_CACHE_SHIFT;
1355 last_index = (pos + count) >> PAGE_CACHE_SHIFT;
1343 while(count > 0) { 1356 while(count > 0) {
1344 size_t offset = pos & (PAGE_CACHE_SIZE - 1); 1357 size_t offset = pos & (PAGE_CACHE_SIZE - 1);
1345 size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset); 1358 size_t write_bytes = min(count, PAGE_CACHE_SIZE - offset);
1346 size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >> 1359 size_t num_pages = (write_bytes + PAGE_CACHE_SIZE - 1) >>
1347 PAGE_CACHE_SHIFT; 1360 PAGE_CACHE_SHIFT;
1348 ret = prepare_pages(NULL, root, file, pages, num_pages, 1361 ret = prepare_pages(NULL, root, file, pages, num_pages,
1349 pos, write_bytes); 1362 pos, first_index, last_index, write_bytes);
1350 BUG_ON(ret); 1363 BUG_ON(ret);
1351 ret = btrfs_copy_from_user(pos, num_pages, 1364 ret = btrfs_copy_from_user(pos, num_pages,
1352 write_bytes, pages, buf); 1365 write_bytes, pages, buf);