diff options
author | Chandan Rajendra <chandan@linux.vnet.ibm.com> | 2016-01-21 05:25:53 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-02-01 13:23:47 -0500 |
commit | 2e78c927d79333f299a8ac81c2fd2952caeef335 (patch) | |
tree | 799c374c0275022c371b58e47309676069d71be4 | |
parent | e410e34fad913dd568ec28d2a9949694324c14db (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.h | 3 | ||||
-rw-r--r-- | fs/btrfs/file.c | 43 |
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 | |||
2356 | static inline void btrfs_init_map_token (struct btrfs_map_token *token) | 2359 | static 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: | |||
1379 | static noinline int | 1379 | static noinline int |
1380 | lock_and_cleanup_extent_if_need(struct inode *inode, struct page **pages, | 1380 | lock_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, |