diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-05 16:21:15 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-05 16:21:15 -0400 |
commit | 795d580baec0d5386b83a8b557df47c20810e86b (patch) | |
tree | d0387c37562e9e27a4f43cf7ae425319cbdad359 /fs/btrfs/transaction.c | |
parent | 449cedf099b23a250e7d61982e35555ccb871182 (diff) | |
parent | 109f6aef5fc436f355ad027f4d97bd696df2049a (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable
* git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable:
Btrfs: add check for changed leaves in setup_leaf_for_split
Btrfs: create snapshot references in same commit as snapshot
Btrfs: fix small race with delalloc flushing waitqueue's
Btrfs: use add_to_page_cache_lru, use __page_cache_alloc
Btrfs: fix chunk allocate size calculation
Btrfs: kill max_extent mount option
Btrfs: fail to mount if we have problems reading the block groups
Btrfs: check btrfs_get_extent return for IS_ERR()
Btrfs: handle kmalloc() failure in inode lookup ioctl
Btrfs: dereferencing freed memory
Btrfs: Simplify num_stripes's calculation logical for __btrfs_alloc_chunk()
Btrfs: Add error handle for btrfs_search_slot() in btrfs_read_chunk_tree()
Btrfs: Remove unnecessary finish_wait() in wait_current_trans()
Btrfs: add NULL check for do_walk_down()
Btrfs: remove duplicate include in ioctl.c
Fix trivial conflict in fs/btrfs/compression.c due to slab.h include
cleanups.
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 112 |
1 files changed, 36 insertions, 76 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index c0d0e3e7bc63..2cb116099b90 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -148,18 +148,13 @@ static void wait_current_trans(struct btrfs_root *root) | |||
148 | while (1) { | 148 | while (1) { |
149 | prepare_to_wait(&root->fs_info->transaction_wait, &wait, | 149 | prepare_to_wait(&root->fs_info->transaction_wait, &wait, |
150 | TASK_UNINTERRUPTIBLE); | 150 | TASK_UNINTERRUPTIBLE); |
151 | if (cur_trans->blocked) { | 151 | if (!cur_trans->blocked) |
152 | mutex_unlock(&root->fs_info->trans_mutex); | ||
153 | schedule(); | ||
154 | mutex_lock(&root->fs_info->trans_mutex); | ||
155 | finish_wait(&root->fs_info->transaction_wait, | ||
156 | &wait); | ||
157 | } else { | ||
158 | finish_wait(&root->fs_info->transaction_wait, | ||
159 | &wait); | ||
160 | break; | 152 | break; |
161 | } | 153 | mutex_unlock(&root->fs_info->trans_mutex); |
154 | schedule(); | ||
155 | mutex_lock(&root->fs_info->trans_mutex); | ||
162 | } | 156 | } |
157 | finish_wait(&root->fs_info->transaction_wait, &wait); | ||
163 | put_transaction(cur_trans); | 158 | put_transaction(cur_trans); |
164 | } | 159 | } |
165 | } | 160 | } |
@@ -761,10 +756,17 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
761 | struct btrfs_root_item *new_root_item; | 756 | struct btrfs_root_item *new_root_item; |
762 | struct btrfs_root *tree_root = fs_info->tree_root; | 757 | struct btrfs_root *tree_root = fs_info->tree_root; |
763 | struct btrfs_root *root = pending->root; | 758 | struct btrfs_root *root = pending->root; |
759 | struct btrfs_root *parent_root; | ||
760 | struct inode *parent_inode; | ||
764 | struct extent_buffer *tmp; | 761 | struct extent_buffer *tmp; |
765 | struct extent_buffer *old; | 762 | struct extent_buffer *old; |
766 | int ret; | 763 | int ret; |
767 | u64 objectid; | 764 | u64 objectid; |
765 | int namelen; | ||
766 | u64 index = 0; | ||
767 | |||
768 | parent_inode = pending->dentry->d_parent->d_inode; | ||
769 | parent_root = BTRFS_I(parent_inode)->root; | ||
768 | 770 | ||
769 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 771 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
770 | if (!new_root_item) { | 772 | if (!new_root_item) { |
@@ -775,79 +777,59 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
775 | if (ret) | 777 | if (ret) |
776 | goto fail; | 778 | goto fail; |
777 | 779 | ||
778 | record_root_in_trans(trans, root); | ||
779 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); | ||
780 | memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); | ||
781 | |||
782 | key.objectid = objectid; | 780 | key.objectid = objectid; |
783 | /* record when the snapshot was created in key.offset */ | 781 | /* record when the snapshot was created in key.offset */ |
784 | key.offset = trans->transid; | 782 | key.offset = trans->transid; |
785 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | 783 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); |
786 | 784 | ||
787 | old = btrfs_lock_root_node(root); | ||
788 | btrfs_cow_block(trans, root, old, NULL, 0, &old); | ||
789 | btrfs_set_lock_blocking(old); | ||
790 | |||
791 | btrfs_copy_root(trans, root, old, &tmp, objectid); | ||
792 | btrfs_tree_unlock(old); | ||
793 | free_extent_buffer(old); | ||
794 | |||
795 | btrfs_set_root_node(new_root_item, tmp); | ||
796 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | ||
797 | new_root_item); | ||
798 | btrfs_tree_unlock(tmp); | ||
799 | free_extent_buffer(tmp); | ||
800 | if (ret) | ||
801 | goto fail; | ||
802 | |||
803 | key.offset = (u64)-1; | ||
804 | memcpy(&pending->root_key, &key, sizeof(key)); | 785 | memcpy(&pending->root_key, &key, sizeof(key)); |
805 | fail: | 786 | pending->root_key.offset = (u64)-1; |
806 | kfree(new_root_item); | ||
807 | return ret; | ||
808 | } | ||
809 | |||
810 | static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, | ||
811 | struct btrfs_pending_snapshot *pending) | ||
812 | { | ||
813 | int ret; | ||
814 | int namelen; | ||
815 | u64 index = 0; | ||
816 | struct btrfs_trans_handle *trans; | ||
817 | struct inode *parent_inode; | ||
818 | struct btrfs_root *parent_root; | ||
819 | |||
820 | parent_inode = pending->dentry->d_parent->d_inode; | ||
821 | parent_root = BTRFS_I(parent_inode)->root; | ||
822 | trans = btrfs_join_transaction(parent_root, 1); | ||
823 | 787 | ||
788 | record_root_in_trans(trans, parent_root); | ||
824 | /* | 789 | /* |
825 | * insert the directory item | 790 | * insert the directory item |
826 | */ | 791 | */ |
827 | namelen = strlen(pending->name); | 792 | namelen = strlen(pending->name); |
828 | ret = btrfs_set_inode_index(parent_inode, &index); | 793 | ret = btrfs_set_inode_index(parent_inode, &index); |
794 | BUG_ON(ret); | ||
829 | ret = btrfs_insert_dir_item(trans, parent_root, | 795 | ret = btrfs_insert_dir_item(trans, parent_root, |
830 | pending->name, namelen, | 796 | pending->name, namelen, |
831 | parent_inode->i_ino, | 797 | parent_inode->i_ino, |
832 | &pending->root_key, BTRFS_FT_DIR, index); | 798 | &pending->root_key, BTRFS_FT_DIR, index); |
833 | 799 | BUG_ON(ret); | |
834 | if (ret) | ||
835 | goto fail; | ||
836 | 800 | ||
837 | btrfs_i_size_write(parent_inode, parent_inode->i_size + namelen * 2); | 801 | btrfs_i_size_write(parent_inode, parent_inode->i_size + namelen * 2); |
838 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | 802 | ret = btrfs_update_inode(trans, parent_root, parent_inode); |
839 | BUG_ON(ret); | 803 | BUG_ON(ret); |
840 | 804 | ||
805 | record_root_in_trans(trans, root); | ||
806 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); | ||
807 | memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); | ||
808 | |||
809 | old = btrfs_lock_root_node(root); | ||
810 | btrfs_cow_block(trans, root, old, NULL, 0, &old); | ||
811 | btrfs_set_lock_blocking(old); | ||
812 | |||
813 | btrfs_copy_root(trans, root, old, &tmp, objectid); | ||
814 | btrfs_tree_unlock(old); | ||
815 | free_extent_buffer(old); | ||
816 | |||
817 | btrfs_set_root_node(new_root_item, tmp); | ||
818 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | ||
819 | new_root_item); | ||
820 | BUG_ON(ret); | ||
821 | btrfs_tree_unlock(tmp); | ||
822 | free_extent_buffer(tmp); | ||
823 | |||
841 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, | 824 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, |
842 | pending->root_key.objectid, | 825 | pending->root_key.objectid, |
843 | parent_root->root_key.objectid, | 826 | parent_root->root_key.objectid, |
844 | parent_inode->i_ino, index, pending->name, | 827 | parent_inode->i_ino, index, pending->name, |
845 | namelen); | 828 | namelen); |
846 | |||
847 | BUG_ON(ret); | 829 | BUG_ON(ret); |
848 | 830 | ||
849 | fail: | 831 | fail: |
850 | btrfs_end_transaction(trans, fs_info->fs_root); | 832 | kfree(new_root_item); |
851 | return ret; | 833 | return ret; |
852 | } | 834 | } |
853 | 835 | ||
@@ -868,25 +850,6 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | |||
868 | return 0; | 850 | return 0; |
869 | } | 851 | } |
870 | 852 | ||
871 | static noinline int finish_pending_snapshots(struct btrfs_trans_handle *trans, | ||
872 | struct btrfs_fs_info *fs_info) | ||
873 | { | ||
874 | struct btrfs_pending_snapshot *pending; | ||
875 | struct list_head *head = &trans->transaction->pending_snapshots; | ||
876 | int ret; | ||
877 | |||
878 | while (!list_empty(head)) { | ||
879 | pending = list_entry(head->next, | ||
880 | struct btrfs_pending_snapshot, list); | ||
881 | ret = finish_pending_snapshot(fs_info, pending); | ||
882 | BUG_ON(ret); | ||
883 | list_del(&pending->list); | ||
884 | kfree(pending->name); | ||
885 | kfree(pending); | ||
886 | } | ||
887 | return 0; | ||
888 | } | ||
889 | |||
890 | static void update_super_roots(struct btrfs_root *root) | 853 | static void update_super_roots(struct btrfs_root *root) |
891 | { | 854 | { |
892 | struct btrfs_root_item *root_item; | 855 | struct btrfs_root_item *root_item; |
@@ -1098,9 +1061,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
1098 | 1061 | ||
1099 | btrfs_finish_extent_commit(trans, root); | 1062 | btrfs_finish_extent_commit(trans, root); |
1100 | 1063 | ||
1101 | /* do the directory inserts of any pending snapshot creations */ | ||
1102 | finish_pending_snapshots(trans, root->fs_info); | ||
1103 | |||
1104 | mutex_lock(&root->fs_info->trans_mutex); | 1064 | mutex_lock(&root->fs_info->trans_mutex); |
1105 | 1065 | ||
1106 | cur_trans->commit_done = 1; | 1066 | cur_trans->commit_done = 1; |