aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-04-05 16:21:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-04-05 16:21:15 -0400
commit795d580baec0d5386b83a8b557df47c20810e86b (patch)
treed0387c37562e9e27a4f43cf7ae425319cbdad359 /fs/btrfs/transaction.c
parent449cedf099b23a250e7d61982e35555ccb871182 (diff)
parent109f6aef5fc436f355ad027f4d97bd696df2049a (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.c112
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));
805fail: 786 pending->root_key.offset = (u64)-1;
806 kfree(new_root_item);
807 return ret;
808}
809
810static 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
849fail: 831fail:
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
871static 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
890static void update_super_roots(struct btrfs_root *root) 853static 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;