aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandan Rajendra <chandan@linux.vnet.ibm.com>2016-01-21 05:25:53 -0500
committerDavid Sterba <dsterba@suse.com>2016-02-01 13:23:47 -0500
commit2e78c927d79333f299a8ac81c2fd2952caeef335 (patch)
tree799c374c0275022c371b58e47309676069d71be4
parente410e34fad913dd568ec28d2a9949694324c14db (diff)
Btrfs: __btrfs_buffered_write: Reserve/release extents aligned to block size
Currently, the code reserves/releases extents in multiples of PAGE_CACHE_SIZE units. Fix this by doing reservation/releases in block size units. Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/file.c43
2 files changed, 33 insertions, 13 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index a9496644f47d..ffb3617fad98 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -2353,6 +2353,9 @@ struct btrfs_map_token {
2353 unsigned long offset; 2353 unsigned long offset;
2354}; 2354};
2355 2355
2356#define BTRFS_BYTES_TO_BLKS(fs_info, bytes) \
2357 ((bytes) >> (fs_info)->sb->s_blocksize_bits)
2358
2356static inline void btrfs_init_map_token (struct btrfs_map_token *token) 2359static inline void btrfs_init_map_token (struct btrfs_map_token *token)
2357{ 2360{
2358 token->kaddr = NULL; 2361 token->kaddr = NULL;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index af782fdd4fca..9809557213d4 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -498,7 +498,7 @@ int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
498 loff_t isize = i_size_read(inode); 498 loff_t isize = i_size_read(inode);
499 499
500 start_pos = pos & ~((u64)root->sectorsize - 1); 500 start_pos = pos & ~((u64)root->sectorsize - 1);
501 num_bytes = ALIGN(write_bytes + pos - start_pos, root->sectorsize); 501 num_bytes = round_up(write_bytes + pos - start_pos, root->sectorsize);
502 502
503 end_of_last_block = start_pos + num_bytes - 1; 503 end_of_last_block = start_pos + num_bytes - 1;
504 err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block, 504 err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
@@ -1379,16 +1379,19 @@ fail:
1379static noinline int 1379static noinline int
1380lock_and_cleanup_extent_if_need(struct inode *inode, struct page **pages, 1380lock_and_cleanup_extent_if_need(struct inode *inode, struct page **pages,
1381 size_t num_pages, loff_t pos, 1381 size_t num_pages, loff_t pos,
1382 size_t write_bytes,
1382 u64 *lockstart, u64 *lockend, 1383 u64 *lockstart, u64 *lockend,
1383 struct extent_state **cached_state) 1384 struct extent_state **cached_state)
1384{ 1385{
1386 struct btrfs_root *root = BTRFS_I(inode)->root;
1385 u64 start_pos; 1387 u64 start_pos;
1386 u64 last_pos; 1388 u64 last_pos;
1387 int i; 1389 int i;
1388 int ret = 0; 1390 int ret = 0;
1389 1391
1390 start_pos = pos & ~((u64)PAGE_CACHE_SIZE - 1); 1392 start_pos = round_down(pos, root->sectorsize);
1391 last_pos = start_pos + ((u64)num_pages << PAGE_CACHE_SHIFT) - 1; 1393 last_pos = start_pos
1394 + round_up(pos + write_bytes - start_pos, root->sectorsize) - 1;
1392 1395
1393 if (start_pos < inode->i_size) { 1396 if (start_pos < inode->i_size) {
1394 struct btrfs_ordered_extent *ordered; 1397 struct btrfs_ordered_extent *ordered;
@@ -1503,6 +1506,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
1503 1506
1504 while (iov_iter_count(i) > 0) { 1507 while (iov_iter_count(i) > 0) {
1505 size_t offset = pos & (PAGE_CACHE_SIZE - 1); 1508 size_t offset = pos & (PAGE_CACHE_SIZE - 1);
1509 size_t sector_offset;
1506 size_t write_bytes = min(iov_iter_count(i), 1510 size_t write_bytes = min(iov_iter_count(i),
1507 nrptrs * (size_t)PAGE_CACHE_SIZE - 1511 nrptrs * (size_t)PAGE_CACHE_SIZE -
1508 offset); 1512 offset);
@@ -1511,6 +1515,8 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
1511 size_t reserve_bytes; 1515 size_t reserve_bytes;
1512 size_t dirty_pages; 1516 size_t dirty_pages;
1513 size_t copied; 1517 size_t copied;
1518 size_t dirty_sectors;
1519 size_t num_sectors;
1514 1520
1515 WARN_ON(num_pages > nrptrs); 1521 WARN_ON(num_pages > nrptrs);
1516 1522
@@ -1523,7 +1529,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
1523 break; 1529 break;
1524 } 1530 }
1525 1531
1526 reserve_bytes = num_pages << PAGE_CACHE_SHIFT; 1532 sector_offset = pos & (root->sectorsize - 1);
1533 reserve_bytes = round_up(write_bytes + sector_offset,
1534 root->sectorsize);
1527 1535
1528 if (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW | 1536 if (BTRFS_I(inode)->flags & (BTRFS_INODE_NODATACOW |
1529 BTRFS_INODE_PREALLOC)) { 1537 BTRFS_INODE_PREALLOC)) {
@@ -1542,7 +1550,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
1542 */ 1550 */
1543 num_pages = DIV_ROUND_UP(write_bytes + offset, 1551 num_pages = DIV_ROUND_UP(write_bytes + offset,
1544 PAGE_CACHE_SIZE); 1552 PAGE_CACHE_SIZE);
1545 reserve_bytes = num_pages << PAGE_CACHE_SHIFT; 1553 reserve_bytes = round_up(write_bytes
1554 + sector_offset,
1555 root->sectorsize);
1546 goto reserve_metadata; 1556 goto reserve_metadata;
1547 } 1557 }
1548 } 1558 }
@@ -1576,8 +1586,8 @@ again:
1576 break; 1586 break;
1577 1587
1578 ret = lock_and_cleanup_extent_if_need(inode, pages, num_pages, 1588 ret = lock_and_cleanup_extent_if_need(inode, pages, num_pages,
1579 pos, &lockstart, &lockend, 1589 pos, write_bytes, &lockstart,
1580 &cached_state); 1590 &lockend, &cached_state);
1581 if (ret < 0) { 1591 if (ret < 0) {
1582 if (ret == -EAGAIN) 1592 if (ret == -EAGAIN)
1583 goto again; 1593 goto again;
@@ -1612,9 +1622,16 @@ again:
1612 * we still have an outstanding extent for the chunk we actually 1622 * we still have an outstanding extent for the chunk we actually
1613 * managed to copy. 1623 * managed to copy.
1614 */ 1624 */
1615 if (num_pages > dirty_pages) { 1625 num_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
1616 release_bytes = (num_pages - dirty_pages) << 1626 reserve_bytes);
1617 PAGE_CACHE_SHIFT; 1627 dirty_sectors = round_up(copied + sector_offset,
1628 root->sectorsize);
1629 dirty_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info,
1630 dirty_sectors);
1631
1632 if (num_sectors > dirty_sectors) {
1633 release_bytes = (write_bytes - copied)
1634 & ~((u64)root->sectorsize - 1);
1618 if (copied > 0) { 1635 if (copied > 0) {
1619 spin_lock(&BTRFS_I(inode)->lock); 1636 spin_lock(&BTRFS_I(inode)->lock);
1620 BTRFS_I(inode)->outstanding_extents++; 1637 BTRFS_I(inode)->outstanding_extents++;
@@ -1633,7 +1650,8 @@ again:
1633 } 1650 }
1634 } 1651 }
1635 1652
1636 release_bytes = dirty_pages << PAGE_CACHE_SHIFT; 1653 release_bytes = round_up(copied + sector_offset,
1654 root->sectorsize);
1637 1655
1638 if (copied > 0) 1656 if (copied > 0)
1639 ret = btrfs_dirty_pages(root, inode, pages, 1657 ret = btrfs_dirty_pages(root, inode, pages,
@@ -1654,8 +1672,7 @@ again:
1654 1672
1655 if (only_release_metadata && copied > 0) { 1673 if (only_release_metadata && copied > 0) {
1656 lockstart = round_down(pos, root->sectorsize); 1674 lockstart = round_down(pos, root->sectorsize);
1657 lockend = lockstart + 1675 lockend = round_up(pos + copied, root->sectorsize) - 1;
1658 (dirty_pages << PAGE_CACHE_SHIFT) - 1;
1659 1676
1660 set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, 1677 set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
1661 lockend, EXTENT_NORESERVE, NULL, 1678 lockend, EXTENT_NORESERVE, NULL,