aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c10
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);
707out: 709out:
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
1690out_unlock: 1693out_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
1898fail: 1905fail:
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}