diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 79 |
1 files changed, 68 insertions, 11 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3cf17257f89d..7feac5a475e9 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -849,6 +849,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
849 | spin_lock_init(&root->list_lock); | 849 | spin_lock_init(&root->list_lock); |
850 | mutex_init(&root->objectid_mutex); | 850 | mutex_init(&root->objectid_mutex); |
851 | mutex_init(&root->log_mutex); | 851 | mutex_init(&root->log_mutex); |
852 | init_waitqueue_head(&root->log_writer_wait); | ||
853 | init_waitqueue_head(&root->log_commit_wait[0]); | ||
854 | init_waitqueue_head(&root->log_commit_wait[1]); | ||
855 | atomic_set(&root->log_commit[0], 0); | ||
856 | atomic_set(&root->log_commit[1], 0); | ||
857 | atomic_set(&root->log_writers, 0); | ||
858 | root->log_batch = 0; | ||
859 | root->log_transid = 0; | ||
852 | extent_io_tree_init(&root->dirty_log_pages, | 860 | extent_io_tree_init(&root->dirty_log_pages, |
853 | fs_info->btree_inode->i_mapping, GFP_NOFS); | 861 | fs_info->btree_inode->i_mapping, GFP_NOFS); |
854 | 862 | ||
@@ -933,15 +941,16 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans, | |||
933 | return 0; | 941 | return 0; |
934 | } | 942 | } |
935 | 943 | ||
936 | int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | 944 | static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans, |
937 | struct btrfs_fs_info *fs_info) | 945 | struct btrfs_fs_info *fs_info) |
938 | { | 946 | { |
939 | struct btrfs_root *root; | 947 | struct btrfs_root *root; |
940 | struct btrfs_root *tree_root = fs_info->tree_root; | 948 | struct btrfs_root *tree_root = fs_info->tree_root; |
949 | struct extent_buffer *leaf; | ||
941 | 950 | ||
942 | root = kzalloc(sizeof(*root), GFP_NOFS); | 951 | root = kzalloc(sizeof(*root), GFP_NOFS); |
943 | if (!root) | 952 | if (!root) |
944 | return -ENOMEM; | 953 | return ERR_PTR(-ENOMEM); |
945 | 954 | ||
946 | __setup_root(tree_root->nodesize, tree_root->leafsize, | 955 | __setup_root(tree_root->nodesize, tree_root->leafsize, |
947 | tree_root->sectorsize, tree_root->stripesize, | 956 | tree_root->sectorsize, tree_root->stripesize, |
@@ -950,12 +959,23 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | |||
950 | root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID; | 959 | root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID; |
951 | root->root_key.type = BTRFS_ROOT_ITEM_KEY; | 960 | root->root_key.type = BTRFS_ROOT_ITEM_KEY; |
952 | root->root_key.offset = BTRFS_TREE_LOG_OBJECTID; | 961 | root->root_key.offset = BTRFS_TREE_LOG_OBJECTID; |
962 | /* | ||
963 | * log trees do not get reference counted because they go away | ||
964 | * before a real commit is actually done. They do store pointers | ||
965 | * to file data extents, and those reference counts still get | ||
966 | * updated (along with back refs to the log tree). | ||
967 | */ | ||
953 | root->ref_cows = 0; | 968 | root->ref_cows = 0; |
954 | 969 | ||
955 | root->node = btrfs_alloc_free_block(trans, root, root->leafsize, | 970 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
956 | 0, BTRFS_TREE_LOG_OBJECTID, | 971 | 0, BTRFS_TREE_LOG_OBJECTID, |
957 | trans->transid, 0, 0, 0); | 972 | trans->transid, 0, 0, 0); |
973 | if (IS_ERR(leaf)) { | ||
974 | kfree(root); | ||
975 | return ERR_CAST(leaf); | ||
976 | } | ||
958 | 977 | ||
978 | root->node = leaf; | ||
959 | btrfs_set_header_nritems(root->node, 0); | 979 | btrfs_set_header_nritems(root->node, 0); |
960 | btrfs_set_header_level(root->node, 0); | 980 | btrfs_set_header_level(root->node, 0); |
961 | btrfs_set_header_bytenr(root->node, root->node->start); | 981 | btrfs_set_header_bytenr(root->node, root->node->start); |
@@ -967,7 +987,48 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | |||
967 | BTRFS_FSID_SIZE); | 987 | BTRFS_FSID_SIZE); |
968 | btrfs_mark_buffer_dirty(root->node); | 988 | btrfs_mark_buffer_dirty(root->node); |
969 | btrfs_tree_unlock(root->node); | 989 | btrfs_tree_unlock(root->node); |
970 | fs_info->log_root_tree = root; | 990 | return root; |
991 | } | ||
992 | |||
993 | int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, | ||
994 | struct btrfs_fs_info *fs_info) | ||
995 | { | ||
996 | struct btrfs_root *log_root; | ||
997 | |||
998 | log_root = alloc_log_tree(trans, fs_info); | ||
999 | if (IS_ERR(log_root)) | ||
1000 | return PTR_ERR(log_root); | ||
1001 | WARN_ON(fs_info->log_root_tree); | ||
1002 | fs_info->log_root_tree = log_root; | ||
1003 | return 0; | ||
1004 | } | ||
1005 | |||
1006 | int btrfs_add_log_tree(struct btrfs_trans_handle *trans, | ||
1007 | struct btrfs_root *root) | ||
1008 | { | ||
1009 | struct btrfs_root *log_root; | ||
1010 | struct btrfs_inode_item *inode_item; | ||
1011 | |||
1012 | log_root = alloc_log_tree(trans, root->fs_info); | ||
1013 | if (IS_ERR(log_root)) | ||
1014 | return PTR_ERR(log_root); | ||
1015 | |||
1016 | log_root->last_trans = trans->transid; | ||
1017 | log_root->root_key.offset = root->root_key.objectid; | ||
1018 | |||
1019 | inode_item = &log_root->root_item.inode; | ||
1020 | inode_item->generation = cpu_to_le64(1); | ||
1021 | inode_item->size = cpu_to_le64(3); | ||
1022 | inode_item->nlink = cpu_to_le32(1); | ||
1023 | inode_item->nbytes = cpu_to_le64(root->leafsize); | ||
1024 | inode_item->mode = cpu_to_le32(S_IFDIR | 0755); | ||
1025 | |||
1026 | btrfs_set_root_bytenr(&log_root->root_item, log_root->node->start); | ||
1027 | btrfs_set_root_generation(&log_root->root_item, trans->transid); | ||
1028 | |||
1029 | WARN_ON(root->log_root); | ||
1030 | root->log_root = log_root; | ||
1031 | root->log_transid = 0; | ||
971 | return 0; | 1032 | return 0; |
972 | } | 1033 | } |
973 | 1034 | ||
@@ -1530,10 +1591,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1530 | init_waitqueue_head(&fs_info->transaction_throttle); | 1591 | init_waitqueue_head(&fs_info->transaction_throttle); |
1531 | init_waitqueue_head(&fs_info->transaction_wait); | 1592 | init_waitqueue_head(&fs_info->transaction_wait); |
1532 | init_waitqueue_head(&fs_info->async_submit_wait); | 1593 | init_waitqueue_head(&fs_info->async_submit_wait); |
1533 | init_waitqueue_head(&fs_info->tree_log_wait); | ||
1534 | atomic_set(&fs_info->tree_log_commit, 0); | ||
1535 | atomic_set(&fs_info->tree_log_writers, 0); | ||
1536 | fs_info->tree_log_transid = 0; | ||
1537 | 1594 | ||
1538 | __setup_root(4096, 4096, 4096, 4096, tree_root, | 1595 | __setup_root(4096, 4096, 4096, 4096, tree_root, |
1539 | fs_info, BTRFS_ROOT_TREE_OBJECTID); | 1596 | fs_info, BTRFS_ROOT_TREE_OBJECTID); |