diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 6b3e4404dc6a..1ace6d11e097 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -686,6 +686,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | |||
686 | if ((offset & (blocksize - 1)) == 0) | 686 | if ((offset & (blocksize - 1)) == 0) |
687 | goto out; | 687 | goto out; |
688 | 688 | ||
689 | down_read(&BTRFS_I(inode)->root->snap_sem); | ||
689 | ret = -ENOMEM; | 690 | ret = -ENOMEM; |
690 | page = grab_cache_page(mapping, index); | 691 | page = grab_cache_page(mapping, index); |
691 | if (!page) | 692 | if (!page) |
@@ -704,6 +705,7 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | |||
704 | 705 | ||
705 | unlock_page(page); | 706 | unlock_page(page); |
706 | page_cache_release(page); | 707 | page_cache_release(page); |
708 | up_read(&BTRFS_I(inode)->root->snap_sem); | ||
707 | out: | 709 | out: |
708 | return ret; | 710 | return ret; |
709 | } | 711 | } |
@@ -1668,6 +1670,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
1668 | int ret = -EINVAL; | 1670 | int ret = -EINVAL; |
1669 | u64 page_start; | 1671 | u64 page_start; |
1670 | 1672 | ||
1673 | down_read(&BTRFS_I(inode)->root->snap_sem); | ||
1671 | lock_page(page); | 1674 | lock_page(page); |
1672 | wait_on_page_writeback(page); | 1675 | wait_on_page_writeback(page); |
1673 | size = i_size_read(inode); | 1676 | size = i_size_read(inode); |
@@ -1688,6 +1691,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct page *page) | |||
1688 | ret = btrfs_cow_one_page(inode, page, end); | 1691 | ret = btrfs_cow_one_page(inode, page, end); |
1689 | 1692 | ||
1690 | out_unlock: | 1693 | out_unlock: |
1694 | up_read(&BTRFS_I(inode)->root->snap_sem); | ||
1691 | unlock_page(page); | 1695 | unlock_page(page); |
1692 | return ret; | 1696 | return ret; |
1693 | } | 1697 | } |
@@ -1851,6 +1855,10 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
1851 | if (!root->ref_cows) | 1855 | if (!root->ref_cows) |
1852 | return -EINVAL; | 1856 | return -EINVAL; |
1853 | 1857 | ||
1858 | down_write(&root->snap_sem); | ||
1859 | freeze_bdev(root->fs_info->sb->s_bdev); | ||
1860 | thaw_bdev(root->fs_info->sb->s_bdev, root->fs_info->sb); | ||
1861 | |||
1854 | mutex_lock(&root->fs_info->fs_mutex); | 1862 | mutex_lock(&root->fs_info->fs_mutex); |
1855 | trans = btrfs_start_transaction(root, 1); | 1863 | trans = btrfs_start_transaction(root, 1); |
1856 | BUG_ON(!trans); | 1864 | BUG_ON(!trans); |
@@ -1894,12 +1902,12 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen) | |||
1894 | ret = btrfs_inc_root_ref(trans, root); | 1902 | ret = btrfs_inc_root_ref(trans, root); |
1895 | if (ret) | 1903 | if (ret) |
1896 | goto fail; | 1904 | goto fail; |
1897 | |||
1898 | fail: | 1905 | fail: |
1899 | err = btrfs_commit_transaction(trans, root); | 1906 | err = btrfs_commit_transaction(trans, root); |
1900 | if (err && !ret) | 1907 | if (err && !ret) |
1901 | ret = err; | 1908 | ret = err; |
1902 | mutex_unlock(&root->fs_info->fs_mutex); | 1909 | mutex_unlock(&root->fs_info->fs_mutex); |
1910 | up_write(&root->snap_sem); | ||
1903 | btrfs_btree_balance_dirty(root); | 1911 | btrfs_btree_balance_dirty(root); |
1904 | return ret; | 1912 | return ret; |
1905 | } | 1913 | } |