memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
        memset(&root->root_kobj, 0, sizeof(root->root_kobj));
        init_completion(&root->kobj_unregister);
+       init_rwsem(&root->snap_sem);
        root->defrag_running = 0;
        root->defrag_level = 0;
        root->root_key.objectid = objectid;
 
        num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >>
                        inode->i_blkbits;
 
+       down_read(&BTRFS_I(inode)->root->snap_sem);
        end_of_last_block = start_pos + (num_blocks << inode->i_blkbits) - 1;
        lock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS);
        mutex_lock(&root->fs_info->fs_mutex);
        mutex_unlock(&root->fs_info->fs_mutex);
        unlock_extent(em_tree, start_pos, end_of_last_block, GFP_NOFS);
        free_extent_map(em);
+       up_read(&BTRFS_I(inode)->root->snap_sem);
        return err;
 }
 
 
        if ((offset & (blocksize - 1)) == 0)
                goto out;
 
+       down_read(&BTRFS_I(inode)->root->snap_sem);
        ret = -ENOMEM;
        page = grab_cache_page(mapping, index);
        if (!page)
 
        unlock_page(page);
        page_cache_release(page);
+       up_read(&BTRFS_I(inode)->root->snap_sem);
 out:
        return ret;
 }
        int ret = -EINVAL;
        u64 page_start;
 
+       down_read(&BTRFS_I(inode)->root->snap_sem);
        lock_page(page);
        wait_on_page_writeback(page);
        size = i_size_read(inode);
        ret = btrfs_cow_one_page(inode, page, end);
 
 out_unlock:
+       up_read(&BTRFS_I(inode)->root->snap_sem);
        unlock_page(page);
        return ret;
 }
        if (!root->ref_cows)
                return -EINVAL;
 
+       down_write(&root->snap_sem);
+       freeze_bdev(root->fs_info->sb->s_bdev);
+       thaw_bdev(root->fs_info->sb->s_bdev, root->fs_info->sb);
+
        mutex_lock(&root->fs_info->fs_mutex);
        trans = btrfs_start_transaction(root, 1);
        BUG_ON(!trans);
        ret = btrfs_inc_root_ref(trans, root);
        if (ret)
                goto fail;
-
 fail:
        err = btrfs_commit_transaction(trans, root);
        if (err && !ret)
                ret = err;
        mutex_unlock(&root->fs_info->fs_mutex);
+       up_write(&root->snap_sem);
        btrfs_btree_balance_dirty(root);
        return ret;
 }