aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2010-03-15 13:27:13 -0400
committerChris Mason <chris.mason@oracle.com>2010-04-05 14:42:01 -0400
commit6bdb72ded1e281cd8844918c39d00cdd0e59f655 (patch)
tree39c25c85ddb1c2eecf7977e7e21a95f1c95ec21f /fs
parentb5cb160084fad438c513d0952849e597ffe9e3d9 (diff)
Btrfs: create snapshot references in same commit as snapshot
This creates the reference to a new snapshot in the same commit as the snapshot itself. This avoids the need for a second commit in order for a snapshot to be persistent, and also avoids the problem of "leaking" a new snapshot tree root if the host crashes before the second commit takes place. It is not at all clear to me why it wasn't always done this way. If there is still a reason for the two-stage {create,finish}_pending_snapshots() approach I'm missing something! :) I've been running this for a couple weeks under pretty heavy usage (a few snapshots per minute) without obvious problems. Signed-off-by: Sage Weil <sage@newdream.net> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/transaction.c97
1 files changed, 31 insertions, 66 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 43054285f638..01cebd661997 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -755,10 +755,17 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
755 struct btrfs_root_item *new_root_item; 755 struct btrfs_root_item *new_root_item;
756 struct btrfs_root *tree_root = fs_info->tree_root; 756 struct btrfs_root *tree_root = fs_info->tree_root;
757 struct btrfs_root *root = pending->root; 757 struct btrfs_root *root = pending->root;
758 struct btrfs_root *parent_root;
759 struct inode *parent_inode;
758 struct extent_buffer *tmp; 760 struct extent_buffer *tmp;
759 struct extent_buffer *old; 761 struct extent_buffer *old;
760 int ret; 762 int ret;
761 u64 objectid; 763 u64 objectid;
764 int namelen;
765 u64 index = 0;
766
767 parent_inode = pending->dentry->d_parent->d_inode;
768 parent_root = BTRFS_I(parent_inode)->root;
762 769
763 new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); 770 new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
764 if (!new_root_item) { 771 if (!new_root_item) {
@@ -769,79 +776,59 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
769 if (ret) 776 if (ret)
770 goto fail; 777 goto fail;
771 778
772 record_root_in_trans(trans, root);
773 btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
774 memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
775
776 key.objectid = objectid; 779 key.objectid = objectid;
777 /* record when the snapshot was created in key.offset */ 780 /* record when the snapshot was created in key.offset */
778 key.offset = trans->transid; 781 key.offset = trans->transid;
779 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); 782 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
780 783
781 old = btrfs_lock_root_node(root);
782 btrfs_cow_block(trans, root, old, NULL, 0, &old);
783 btrfs_set_lock_blocking(old);
784
785 btrfs_copy_root(trans, root, old, &tmp, objectid);
786 btrfs_tree_unlock(old);
787 free_extent_buffer(old);
788
789 btrfs_set_root_node(new_root_item, tmp);
790 ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
791 new_root_item);
792 btrfs_tree_unlock(tmp);
793 free_extent_buffer(tmp);
794 if (ret)
795 goto fail;
796
797 key.offset = (u64)-1;
798 memcpy(&pending->root_key, &key, sizeof(key)); 784 memcpy(&pending->root_key, &key, sizeof(key));
799fail: 785 pending->root_key.offset = (u64)-1;
800 kfree(new_root_item);
801 return ret;
802}
803
804static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info,
805 struct btrfs_pending_snapshot *pending)
806{
807 int ret;
808 int namelen;
809 u64 index = 0;
810 struct btrfs_trans_handle *trans;
811 struct inode *parent_inode;
812 struct btrfs_root *parent_root;
813
814 parent_inode = pending->dentry->d_parent->d_inode;
815 parent_root = BTRFS_I(parent_inode)->root;
816 trans = btrfs_join_transaction(parent_root, 1);
817 786
787 record_root_in_trans(trans, parent_root);
818 /* 788 /*
819 * insert the directory item 789 * insert the directory item
820 */ 790 */
821 namelen = strlen(pending->name); 791 namelen = strlen(pending->name);
822 ret = btrfs_set_inode_index(parent_inode, &index); 792 ret = btrfs_set_inode_index(parent_inode, &index);
793 BUG_ON(ret);
823 ret = btrfs_insert_dir_item(trans, parent_root, 794 ret = btrfs_insert_dir_item(trans, parent_root,
824 pending->name, namelen, 795 pending->name, namelen,
825 parent_inode->i_ino, 796 parent_inode->i_ino,
826 &pending->root_key, BTRFS_FT_DIR, index); 797 &pending->root_key, BTRFS_FT_DIR, index);
827 798 BUG_ON(ret);
828 if (ret)
829 goto fail;
830 799
831 btrfs_i_size_write(parent_inode, parent_inode->i_size + namelen * 2); 800 btrfs_i_size_write(parent_inode, parent_inode->i_size + namelen * 2);
832 ret = btrfs_update_inode(trans, parent_root, parent_inode); 801 ret = btrfs_update_inode(trans, parent_root, parent_inode);
833 BUG_ON(ret); 802 BUG_ON(ret);
834 803
804 record_root_in_trans(trans, root);
805 btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
806 memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
807
808 old = btrfs_lock_root_node(root);
809 btrfs_cow_block(trans, root, old, NULL, 0, &old);
810 btrfs_set_lock_blocking(old);
811
812 btrfs_copy_root(trans, root, old, &tmp, objectid);
813 btrfs_tree_unlock(old);
814 free_extent_buffer(old);
815
816 btrfs_set_root_node(new_root_item, tmp);
817 ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
818 new_root_item);
819 BUG_ON(ret);
820 btrfs_tree_unlock(tmp);
821 free_extent_buffer(tmp);
822
835 ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, 823 ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root,
836 pending->root_key.objectid, 824 pending->root_key.objectid,
837 parent_root->root_key.objectid, 825 parent_root->root_key.objectid,
838 parent_inode->i_ino, index, pending->name, 826 parent_inode->i_ino, index, pending->name,
839 namelen); 827 namelen);
840
841 BUG_ON(ret); 828 BUG_ON(ret);
842 829
843fail: 830fail:
844 btrfs_end_transaction(trans, fs_info->fs_root); 831 kfree(new_root_item);
845 return ret; 832 return ret;
846} 833}
847 834
@@ -862,25 +849,6 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans,
862 return 0; 849 return 0;
863} 850}
864 851
865static noinline int finish_pending_snapshots(struct btrfs_trans_handle *trans,
866 struct btrfs_fs_info *fs_info)
867{
868 struct btrfs_pending_snapshot *pending;
869 struct list_head *head = &trans->transaction->pending_snapshots;
870 int ret;
871
872 while (!list_empty(head)) {
873 pending = list_entry(head->next,
874 struct btrfs_pending_snapshot, list);
875 ret = finish_pending_snapshot(fs_info, pending);
876 BUG_ON(ret);
877 list_del(&pending->list);
878 kfree(pending->name);
879 kfree(pending);
880 }
881 return 0;
882}
883
884static void update_super_roots(struct btrfs_root *root) 852static void update_super_roots(struct btrfs_root *root)
885{ 853{
886 struct btrfs_root_item *root_item; 854 struct btrfs_root_item *root_item;
@@ -1092,9 +1060,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
1092 1060
1093 btrfs_finish_extent_commit(trans, root); 1061 btrfs_finish_extent_commit(trans, root);
1094 1062
1095 /* do the directory inserts of any pending snapshot creations */
1096 finish_pending_snapshots(trans, root->fs_info);
1097
1098 mutex_lock(&root->fs_info->trans_mutex); 1063 mutex_lock(&root->fs_info->trans_mutex);
1099 1064
1100 cur_trans->commit_done = 1; 1065 cur_trans->commit_done = 1;