aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-11-19 15:13:35 -0500
committerChris Mason <chris.mason@oracle.com>2008-11-19 15:13:35 -0500
commit7c2ca4682a2b401cb0c43f96b05eced25eb83eec (patch)
tree8c6cf2661f1f15869acdbbf7096bce2e19a1c1e1 /fs
parentd2c3f4f695edac4d75c1b3eb01a1d16072de63bb (diff)
Btrfs: Do fsync log replay when mount -o ro, except when on readonly media
fsync log replay can change the filesystem, so it cannot be delayed until mount -o rw,remount, and it can't be forgotten entirely. So, this patch changes btrfs to do with reiserfs, ext3 and xfs do, which is to do the log replay even when mounted readonly. On a readonly device if log replay is required, the mount is aborted. Getting all of this right had required fixing up some of the error handling in open_ctree. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/disk-io.c31
1 files changed, 23 insertions, 8 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 8d03e4a3c4e9..c8dcb47b6d7d 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -518,7 +518,6 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
518 extent_submit_bio_hook_t *submit_bio_done) 518 extent_submit_bio_hook_t *submit_bio_done)
519{ 519{
520 struct async_submit_bio *async; 520 struct async_submit_bio *async;
521 int limit = btrfs_async_submit_limit(fs_info);
522 521
523 async = kmalloc(sizeof(*async), GFP_NOFS); 522 async = kmalloc(sizeof(*async), GFP_NOFS);
524 if (!async) 523 if (!async)
@@ -541,6 +540,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode,
541 atomic_inc(&fs_info->nr_async_submits); 540 atomic_inc(&fs_info->nr_async_submits);
542 btrfs_queue_worker(&fs_info->workers, &async->work); 541 btrfs_queue_worker(&fs_info->workers, &async->work);
543#if 0 542#if 0
543 int limit = btrfs_async_submit_limit(fs_info);
544 if (atomic_read(&fs_info->nr_async_submits) > limit) { 544 if (atomic_read(&fs_info->nr_async_submits) > limit) {
545 wait_event_timeout(fs_info->async_submit_wait, 545 wait_event_timeout(fs_info->async_submit_wait,
546 (atomic_read(&fs_info->nr_async_submits) < limit), 546 (atomic_read(&fs_info->nr_async_submits) < limit),
@@ -1732,13 +1732,15 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1732 if (!fs_info->transaction_kthread) 1732 if (!fs_info->transaction_kthread)
1733 goto fail_cleaner; 1733 goto fail_cleaner;
1734 1734
1735 if (sb->s_flags & MS_RDONLY)
1736 goto read_fs_root;
1737
1738 if (btrfs_super_log_root(disk_super) != 0) { 1735 if (btrfs_super_log_root(disk_super) != 0) {
1739 u32 blocksize; 1736 u32 blocksize;
1740 u64 bytenr = btrfs_super_log_root(disk_super); 1737 u64 bytenr = btrfs_super_log_root(disk_super);
1741 1738
1739 if (fs_devices->rw_devices == 0) {
1740 printk("Btrfs log replay required on RO media\n");
1741 err = -EIO;
1742 goto fail_trans_kthread;
1743 }
1742 blocksize = 1744 blocksize =
1743 btrfs_level_size(tree_root, 1745 btrfs_level_size(tree_root,
1744 btrfs_super_log_root_level(disk_super)); 1746 btrfs_super_log_root_level(disk_super));
@@ -1756,21 +1758,32 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1756 BUG_ON(ret); 1758 BUG_ON(ret);
1757 } 1759 }
1758 1760
1759 ret = btrfs_cleanup_reloc_trees(tree_root); 1761 if (!(sb->s_flags & MS_RDONLY)) {
1760 BUG_ON(ret); 1762 ret = btrfs_cleanup_reloc_trees(tree_root);
1763 BUG_ON(ret);
1764 }
1761 1765
1762read_fs_root:
1763 location.objectid = BTRFS_FS_TREE_OBJECTID; 1766 location.objectid = BTRFS_FS_TREE_OBJECTID;
1764 location.type = BTRFS_ROOT_ITEM_KEY; 1767 location.type = BTRFS_ROOT_ITEM_KEY;
1765 location.offset = (u64)-1; 1768 location.offset = (u64)-1;
1766 1769
1767 fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location); 1770 fs_info->fs_root = btrfs_read_fs_root_no_name(fs_info, &location);
1768 if (!fs_info->fs_root) 1771 if (!fs_info->fs_root)
1769 goto fail_cleaner; 1772 goto fail_trans_kthread;
1770 return tree_root; 1773 return tree_root;
1771 1774
1775fail_trans_kthread:
1776 kthread_stop(fs_info->transaction_kthread);
1772fail_cleaner: 1777fail_cleaner:
1773 kthread_stop(fs_info->cleaner_kthread); 1778 kthread_stop(fs_info->cleaner_kthread);
1779
1780 /*
1781 * make sure we're done with the btree inode before we stop our
1782 * kthreads
1783 */
1784 filemap_write_and_wait(fs_info->btree_inode->i_mapping);
1785 invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
1786
1774fail_extent_root: 1787fail_extent_root:
1775 free_extent_buffer(extent_root->node); 1788 free_extent_buffer(extent_root->node);
1776fail_tree_root: 1789fail_tree_root:
@@ -1778,6 +1791,7 @@ fail_tree_root:
1778fail_chunk_root: 1791fail_chunk_root:
1779 free_extent_buffer(chunk_root->node); 1792 free_extent_buffer(chunk_root->node);
1780fail_sys_array: 1793fail_sys_array:
1794 free_extent_buffer(dev_root->node);
1781fail_sb_buffer: 1795fail_sb_buffer:
1782 btrfs_stop_workers(&fs_info->fixup_workers); 1796 btrfs_stop_workers(&fs_info->fixup_workers);
1783 btrfs_stop_workers(&fs_info->delalloc_workers); 1797 btrfs_stop_workers(&fs_info->delalloc_workers);
@@ -1786,6 +1800,7 @@ fail_sb_buffer:
1786 btrfs_stop_workers(&fs_info->endio_write_workers); 1800 btrfs_stop_workers(&fs_info->endio_write_workers);
1787 btrfs_stop_workers(&fs_info->submit_workers); 1801 btrfs_stop_workers(&fs_info->submit_workers);
1788fail_iput: 1802fail_iput:
1803 invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
1789 iput(fs_info->btree_inode); 1804 iput(fs_info->btree_inode);
1790fail: 1805fail:
1791 btrfs_close_devices(fs_info->fs_devices); 1806 btrfs_close_devices(fs_info->fs_devices);