diff options
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r-- | fs/btrfs/file.c | 169 |
1 files changed, 162 insertions, 7 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index fa4ef18b66b1..59cbdb120ad0 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -1452,7 +1452,7 @@ int btrfs_release_file(struct inode *inode, struct file *filp) | |||
1452 | * important optimization for directories because holding the mutex prevents | 1452 | * important optimization for directories because holding the mutex prevents |
1453 | * new operations on the dir while we write to disk. | 1453 | * new operations on the dir while we write to disk. |
1454 | */ | 1454 | */ |
1455 | int btrfs_sync_file(struct file *file, int datasync) | 1455 | int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) |
1456 | { | 1456 | { |
1457 | struct dentry *dentry = file->f_path.dentry; | 1457 | struct dentry *dentry = file->f_path.dentry; |
1458 | struct inode *inode = dentry->d_inode; | 1458 | struct inode *inode = dentry->d_inode; |
@@ -1462,9 +1462,13 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1462 | 1462 | ||
1463 | trace_btrfs_sync_file(file, datasync); | 1463 | trace_btrfs_sync_file(file, datasync); |
1464 | 1464 | ||
1465 | ret = filemap_write_and_wait_range(inode->i_mapping, start, end); | ||
1466 | if (ret) | ||
1467 | return ret; | ||
1468 | mutex_lock(&inode->i_mutex); | ||
1469 | |||
1465 | /* we wait first, since the writeback may change the inode */ | 1470 | /* we wait first, since the writeback may change the inode */ |
1466 | root->log_batch++; | 1471 | root->log_batch++; |
1467 | /* the VFS called filemap_fdatawrite for us */ | ||
1468 | btrfs_wait_ordered_range(inode, 0, (u64)-1); | 1472 | btrfs_wait_ordered_range(inode, 0, (u64)-1); |
1469 | root->log_batch++; | 1473 | root->log_batch++; |
1470 | 1474 | ||
@@ -1472,8 +1476,10 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1472 | * check the transaction that last modified this inode | 1476 | * check the transaction that last modified this inode |
1473 | * and see if its already been committed | 1477 | * and see if its already been committed |
1474 | */ | 1478 | */ |
1475 | if (!BTRFS_I(inode)->last_trans) | 1479 | if (!BTRFS_I(inode)->last_trans) { |
1480 | mutex_unlock(&inode->i_mutex); | ||
1476 | goto out; | 1481 | goto out; |
1482 | } | ||
1477 | 1483 | ||
1478 | /* | 1484 | /* |
1479 | * if the last transaction that changed this file was before | 1485 | * if the last transaction that changed this file was before |
@@ -1484,6 +1490,7 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1484 | if (BTRFS_I(inode)->last_trans <= | 1490 | if (BTRFS_I(inode)->last_trans <= |
1485 | root->fs_info->last_trans_committed) { | 1491 | root->fs_info->last_trans_committed) { |
1486 | BTRFS_I(inode)->last_trans = 0; | 1492 | BTRFS_I(inode)->last_trans = 0; |
1493 | mutex_unlock(&inode->i_mutex); | ||
1487 | goto out; | 1494 | goto out; |
1488 | } | 1495 | } |
1489 | 1496 | ||
@@ -1496,12 +1503,15 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1496 | trans = btrfs_start_transaction(root, 0); | 1503 | trans = btrfs_start_transaction(root, 0); |
1497 | if (IS_ERR(trans)) { | 1504 | if (IS_ERR(trans)) { |
1498 | ret = PTR_ERR(trans); | 1505 | ret = PTR_ERR(trans); |
1506 | mutex_unlock(&inode->i_mutex); | ||
1499 | goto out; | 1507 | goto out; |
1500 | } | 1508 | } |
1501 | 1509 | ||
1502 | ret = btrfs_log_dentry_safe(trans, root, dentry); | 1510 | ret = btrfs_log_dentry_safe(trans, root, dentry); |
1503 | if (ret < 0) | 1511 | if (ret < 0) { |
1512 | mutex_unlock(&inode->i_mutex); | ||
1504 | goto out; | 1513 | goto out; |
1514 | } | ||
1505 | 1515 | ||
1506 | /* we've logged all the items and now have a consistent | 1516 | /* we've logged all the items and now have a consistent |
1507 | * version of the file in the log. It is possible that | 1517 | * version of the file in the log. It is possible that |
@@ -1513,7 +1523,7 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1513 | * file again, but that will end up using the synchronization | 1523 | * file again, but that will end up using the synchronization |
1514 | * inside btrfs_sync_log to keep things safe. | 1524 | * inside btrfs_sync_log to keep things safe. |
1515 | */ | 1525 | */ |
1516 | mutex_unlock(&dentry->d_inode->i_mutex); | 1526 | mutex_unlock(&inode->i_mutex); |
1517 | 1527 | ||
1518 | if (ret != BTRFS_NO_LOG_SYNC) { | 1528 | if (ret != BTRFS_NO_LOG_SYNC) { |
1519 | if (ret > 0) { | 1529 | if (ret > 0) { |
@@ -1528,7 +1538,6 @@ int btrfs_sync_file(struct file *file, int datasync) | |||
1528 | } else { | 1538 | } else { |
1529 | ret = btrfs_end_transaction(trans, root); | 1539 | ret = btrfs_end_transaction(trans, root); |
1530 | } | 1540 | } |
1531 | mutex_lock(&dentry->d_inode->i_mutex); | ||
1532 | out: | 1541 | out: |
1533 | return ret > 0 ? -EIO : ret; | 1542 | return ret > 0 ? -EIO : ret; |
1534 | } | 1543 | } |
@@ -1664,8 +1673,154 @@ out: | |||
1664 | return ret; | 1673 | return ret; |
1665 | } | 1674 | } |
1666 | 1675 | ||
1676 | static int find_desired_extent(struct inode *inode, loff_t *offset, int origin) | ||
1677 | { | ||
1678 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
1679 | struct extent_map *em; | ||
1680 | struct extent_state *cached_state = NULL; | ||
1681 | u64 lockstart = *offset; | ||
1682 | u64 lockend = i_size_read(inode); | ||
1683 | u64 start = *offset; | ||
1684 | u64 orig_start = *offset; | ||
1685 | u64 len = i_size_read(inode); | ||
1686 | u64 last_end = 0; | ||
1687 | int ret = 0; | ||
1688 | |||
1689 | lockend = max_t(u64, root->sectorsize, lockend); | ||
1690 | if (lockend <= lockstart) | ||
1691 | lockend = lockstart + root->sectorsize; | ||
1692 | |||
1693 | len = lockend - lockstart + 1; | ||
1694 | |||
1695 | len = max_t(u64, len, root->sectorsize); | ||
1696 | if (inode->i_size == 0) | ||
1697 | return -ENXIO; | ||
1698 | |||
1699 | lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0, | ||
1700 | &cached_state, GFP_NOFS); | ||
1701 | |||
1702 | /* | ||
1703 | * Delalloc is such a pain. If we have a hole and we have pending | ||
1704 | * delalloc for a portion of the hole we will get back a hole that | ||
1705 | * exists for the entire range since it hasn't been actually written | ||
1706 | * yet. So to take care of this case we need to look for an extent just | ||
1707 | * before the position we want in case there is outstanding delalloc | ||
1708 | * going on here. | ||
1709 | */ | ||
1710 | if (origin == SEEK_HOLE && start != 0) { | ||
1711 | if (start <= root->sectorsize) | ||
1712 | em = btrfs_get_extent_fiemap(inode, NULL, 0, 0, | ||
1713 | root->sectorsize, 0); | ||
1714 | else | ||
1715 | em = btrfs_get_extent_fiemap(inode, NULL, 0, | ||
1716 | start - root->sectorsize, | ||
1717 | root->sectorsize, 0); | ||
1718 | if (IS_ERR(em)) { | ||
1719 | ret = -ENXIO; | ||
1720 | goto out; | ||
1721 | } | ||
1722 | last_end = em->start + em->len; | ||
1723 | if (em->block_start == EXTENT_MAP_DELALLOC) | ||
1724 | last_end = min_t(u64, last_end, inode->i_size); | ||
1725 | free_extent_map(em); | ||
1726 | } | ||
1727 | |||
1728 | while (1) { | ||
1729 | em = btrfs_get_extent_fiemap(inode, NULL, 0, start, len, 0); | ||
1730 | if (IS_ERR(em)) { | ||
1731 | ret = -ENXIO; | ||
1732 | break; | ||
1733 | } | ||
1734 | |||
1735 | if (em->block_start == EXTENT_MAP_HOLE) { | ||
1736 | if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) { | ||
1737 | if (last_end <= orig_start) { | ||
1738 | free_extent_map(em); | ||
1739 | ret = -ENXIO; | ||
1740 | break; | ||
1741 | } | ||
1742 | } | ||
1743 | |||
1744 | if (origin == SEEK_HOLE) { | ||
1745 | *offset = start; | ||
1746 | free_extent_map(em); | ||
1747 | break; | ||
1748 | } | ||
1749 | } else { | ||
1750 | if (origin == SEEK_DATA) { | ||
1751 | if (em->block_start == EXTENT_MAP_DELALLOC) { | ||
1752 | if (start >= inode->i_size) { | ||
1753 | free_extent_map(em); | ||
1754 | ret = -ENXIO; | ||
1755 | break; | ||
1756 | } | ||
1757 | } | ||
1758 | |||
1759 | *offset = start; | ||
1760 | free_extent_map(em); | ||
1761 | break; | ||
1762 | } | ||
1763 | } | ||
1764 | |||
1765 | start = em->start + em->len; | ||
1766 | last_end = em->start + em->len; | ||
1767 | |||
1768 | if (em->block_start == EXTENT_MAP_DELALLOC) | ||
1769 | last_end = min_t(u64, last_end, inode->i_size); | ||
1770 | |||
1771 | if (test_bit(EXTENT_FLAG_VACANCY, &em->flags)) { | ||
1772 | free_extent_map(em); | ||
1773 | ret = -ENXIO; | ||
1774 | break; | ||
1775 | } | ||
1776 | free_extent_map(em); | ||
1777 | cond_resched(); | ||
1778 | } | ||
1779 | if (!ret) | ||
1780 | *offset = min(*offset, inode->i_size); | ||
1781 | out: | ||
1782 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend, | ||
1783 | &cached_state, GFP_NOFS); | ||
1784 | return ret; | ||
1785 | } | ||
1786 | |||
1787 | static loff_t btrfs_file_llseek(struct file *file, loff_t offset, int origin) | ||
1788 | { | ||
1789 | struct inode *inode = file->f_mapping->host; | ||
1790 | int ret; | ||
1791 | |||
1792 | mutex_lock(&inode->i_mutex); | ||
1793 | switch (origin) { | ||
1794 | case SEEK_END: | ||
1795 | case SEEK_CUR: | ||
1796 | offset = generic_file_llseek_unlocked(file, offset, origin); | ||
1797 | goto out; | ||
1798 | case SEEK_DATA: | ||
1799 | case SEEK_HOLE: | ||
1800 | ret = find_desired_extent(inode, &offset, origin); | ||
1801 | if (ret) { | ||
1802 | mutex_unlock(&inode->i_mutex); | ||
1803 | return ret; | ||
1804 | } | ||
1805 | } | ||
1806 | |||
1807 | if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET)) | ||
1808 | return -EINVAL; | ||
1809 | if (offset > inode->i_sb->s_maxbytes) | ||
1810 | return -EINVAL; | ||
1811 | |||
1812 | /* Special lock needed here? */ | ||
1813 | if (offset != file->f_pos) { | ||
1814 | file->f_pos = offset; | ||
1815 | file->f_version = 0; | ||
1816 | } | ||
1817 | out: | ||
1818 | mutex_unlock(&inode->i_mutex); | ||
1819 | return offset; | ||
1820 | } | ||
1821 | |||
1667 | const struct file_operations btrfs_file_operations = { | 1822 | const struct file_operations btrfs_file_operations = { |
1668 | .llseek = generic_file_llseek, | 1823 | .llseek = btrfs_file_llseek, |
1669 | .read = do_sync_read, | 1824 | .read = do_sync_read, |
1670 | .write = do_sync_write, | 1825 | .write = do_sync_write, |
1671 | .aio_read = generic_file_aio_read, | 1826 | .aio_read = generic_file_aio_read, |