diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 202c1b6df4a4..eec8b2465039 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -779,7 +779,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
779 | struct extent_buffer *tmp; | 779 | struct extent_buffer *tmp; |
780 | struct extent_buffer *old; | 780 | struct extent_buffer *old; |
781 | int ret; | 781 | int ret; |
782 | int namelen; | ||
783 | u64 objectid; | 782 | u64 objectid; |
784 | 783 | ||
785 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 784 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
@@ -816,28 +815,48 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
816 | if (ret) | 815 | if (ret) |
817 | goto fail; | 816 | goto fail; |
818 | 817 | ||
818 | key.offset = (u64)-1; | ||
819 | memcpy(&pending->root_key, &key, sizeof(key)); | ||
820 | fail: | ||
821 | kfree(new_root_item); | ||
822 | return ret; | ||
823 | } | ||
824 | |||
825 | static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, | ||
826 | struct btrfs_pending_snapshot *pending) | ||
827 | { | ||
828 | int ret; | ||
829 | int namelen; | ||
830 | u64 index = 0; | ||
831 | struct btrfs_trans_handle *trans; | ||
832 | struct inode *parent_inode; | ||
833 | struct inode *inode; | ||
834 | |||
835 | trans = btrfs_start_transaction(fs_info->fs_root, 1); | ||
836 | |||
819 | /* | 837 | /* |
820 | * insert the directory item | 838 | * insert the directory item |
821 | */ | 839 | */ |
822 | key.offset = (u64)-1; | ||
823 | namelen = strlen(pending->name); | 840 | namelen = strlen(pending->name); |
824 | ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, | 841 | parent_inode = pending->dentry->d_parent->d_inode; |
825 | pending->name, namelen, | 842 | ret = btrfs_set_inode_index(parent_inode, &index); |
826 | root->fs_info->sb->s_root->d_inode->i_ino, | 843 | ret = btrfs_insert_dir_item(trans, |
827 | &key, BTRFS_FT_DIR, 0); | 844 | BTRFS_I(parent_inode)->root, |
845 | pending->name, namelen, | ||
846 | parent_inode->i_ino, | ||
847 | &pending->root_key, BTRFS_FT_DIR, index); | ||
828 | 848 | ||
829 | if (ret) | 849 | if (ret) |
830 | goto fail; | 850 | goto fail; |
831 | 851 | #if 0 | |
832 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, | 852 | ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, |
833 | pending->name, strlen(pending->name), objectid, | 853 | pending->name, strlen(pending->name), objectid, |
834 | root->fs_info->sb->s_root->d_inode->i_ino, 0); | 854 | root->fs_info->sb->s_root->d_inode->i_ino, 0); |
835 | 855 | #endif | |
836 | /* Invalidate existing dcache entry for new snapshot. */ | 856 | inode = btrfs_lookup_dentry(parent_inode, pending->dentry); |
837 | btrfs_invalidate_dcache_root(root, pending->name, namelen); | 857 | d_instantiate(pending->dentry, inode); |
838 | |||
839 | fail: | 858 | fail: |
840 | kfree(new_root_item); | 859 | btrfs_end_transaction(trans, fs_info->fs_root); |
841 | return ret; | 860 | return ret; |
842 | } | 861 | } |
843 | 862 | ||
@@ -849,12 +868,28 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | |||
849 | { | 868 | { |
850 | struct btrfs_pending_snapshot *pending; | 869 | struct btrfs_pending_snapshot *pending; |
851 | struct list_head *head = &trans->transaction->pending_snapshots; | 870 | struct list_head *head = &trans->transaction->pending_snapshots; |
871 | struct list_head *cur; | ||
872 | int ret; | ||
873 | |||
874 | list_for_each(cur, head) { | ||
875 | pending = list_entry(cur, struct btrfs_pending_snapshot, list); | ||
876 | ret = create_pending_snapshot(trans, fs_info, pending); | ||
877 | BUG_ON(ret); | ||
878 | } | ||
879 | return 0; | ||
880 | } | ||
881 | |||
882 | static noinline int finish_pending_snapshots(struct btrfs_trans_handle *trans, | ||
883 | struct btrfs_fs_info *fs_info) | ||
884 | { | ||
885 | struct btrfs_pending_snapshot *pending; | ||
886 | struct list_head *head = &trans->transaction->pending_snapshots; | ||
852 | int ret; | 887 | int ret; |
853 | 888 | ||
854 | while(!list_empty(head)) { | 889 | while(!list_empty(head)) { |
855 | pending = list_entry(head->next, | 890 | pending = list_entry(head->next, |
856 | struct btrfs_pending_snapshot, list); | 891 | struct btrfs_pending_snapshot, list); |
857 | ret = create_pending_snapshot(trans, fs_info, pending); | 892 | ret = finish_pending_snapshot(fs_info, pending); |
858 | BUG_ON(ret); | 893 | BUG_ON(ret); |
859 | list_del(&pending->list); | 894 | list_del(&pending->list); |
860 | kfree(pending->name); | 895 | kfree(pending->name); |
@@ -1033,11 +1068,15 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1033 | btrfs_drop_dead_reloc_roots(root); | 1068 | btrfs_drop_dead_reloc_roots(root); |
1034 | mutex_unlock(&root->fs_info->tree_reloc_mutex); | 1069 | mutex_unlock(&root->fs_info->tree_reloc_mutex); |
1035 | 1070 | ||
1071 | /* do the directory inserts of any pending snapshot creations */ | ||
1072 | finish_pending_snapshots(trans, root->fs_info); | ||
1073 | |||
1036 | mutex_lock(&root->fs_info->trans_mutex); | 1074 | mutex_lock(&root->fs_info->trans_mutex); |
1037 | 1075 | ||
1038 | cur_trans->commit_done = 1; | 1076 | cur_trans->commit_done = 1; |
1039 | root->fs_info->last_trans_committed = cur_trans->transid; | 1077 | root->fs_info->last_trans_committed = cur_trans->transid; |
1040 | wake_up(&cur_trans->commit_wait); | 1078 | wake_up(&cur_trans->commit_wait); |
1079 | |||
1041 | put_transaction(cur_trans); | 1080 | put_transaction(cur_trans); |
1042 | put_transaction(cur_trans); | 1081 | put_transaction(cur_trans); |
1043 | 1082 | ||
@@ -1046,6 +1085,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1046 | list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots); | 1085 | list_splice_init(&root->fs_info->dead_roots, &dirty_fs_roots); |
1047 | 1086 | ||
1048 | mutex_unlock(&root->fs_info->trans_mutex); | 1087 | mutex_unlock(&root->fs_info->trans_mutex); |
1088 | |||
1049 | kmem_cache_free(btrfs_trans_handle_cachep, trans); | 1089 | kmem_cache_free(btrfs_trans_handle_cachep, trans); |
1050 | 1090 | ||
1051 | if (root->fs_info->closing) { | 1091 | if (root->fs_info->closing) { |