diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r-- | fs/btrfs/transaction.c | 232 |
1 files changed, 172 insertions, 60 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2cb116099b90..66e4c66cc63b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -165,54 +165,89 @@ enum btrfs_trans_type { | |||
165 | TRANS_USERSPACE, | 165 | TRANS_USERSPACE, |
166 | }; | 166 | }; |
167 | 167 | ||
168 | static int may_wait_transaction(struct btrfs_root *root, int type) | ||
169 | { | ||
170 | if (!root->fs_info->log_root_recovering && | ||
171 | ((type == TRANS_START && !root->fs_info->open_ioctl_trans) || | ||
172 | type == TRANS_USERSPACE)) | ||
173 | return 1; | ||
174 | return 0; | ||
175 | } | ||
176 | |||
168 | static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | 177 | static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, |
169 | int num_blocks, int type) | 178 | u64 num_items, int type) |
170 | { | 179 | { |
171 | struct btrfs_trans_handle *h = | 180 | struct btrfs_trans_handle *h; |
172 | kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | 181 | struct btrfs_transaction *cur_trans; |
182 | int retries = 0; | ||
173 | int ret; | 183 | int ret; |
184 | again: | ||
185 | h = kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | ||
186 | if (!h) | ||
187 | return ERR_PTR(-ENOMEM); | ||
174 | 188 | ||
175 | mutex_lock(&root->fs_info->trans_mutex); | 189 | mutex_lock(&root->fs_info->trans_mutex); |
176 | if (!root->fs_info->log_root_recovering && | 190 | if (may_wait_transaction(root, type)) |
177 | ((type == TRANS_START && !root->fs_info->open_ioctl_trans) || | ||
178 | type == TRANS_USERSPACE)) | ||
179 | wait_current_trans(root); | 191 | wait_current_trans(root); |
192 | |||
180 | ret = join_transaction(root); | 193 | ret = join_transaction(root); |
181 | BUG_ON(ret); | 194 | BUG_ON(ret); |
182 | 195 | ||
183 | h->transid = root->fs_info->running_transaction->transid; | 196 | cur_trans = root->fs_info->running_transaction; |
184 | h->transaction = root->fs_info->running_transaction; | 197 | cur_trans->use_count++; |
185 | h->blocks_reserved = num_blocks; | 198 | mutex_unlock(&root->fs_info->trans_mutex); |
199 | |||
200 | h->transid = cur_trans->transid; | ||
201 | h->transaction = cur_trans; | ||
186 | h->blocks_used = 0; | 202 | h->blocks_used = 0; |
187 | h->block_group = 0; | 203 | h->block_group = 0; |
188 | h->alloc_exclude_nr = 0; | 204 | h->bytes_reserved = 0; |
189 | h->alloc_exclude_start = 0; | ||
190 | h->delayed_ref_updates = 0; | 205 | h->delayed_ref_updates = 0; |
206 | h->block_rsv = NULL; | ||
191 | 207 | ||
192 | if (!current->journal_info && type != TRANS_USERSPACE) | 208 | smp_mb(); |
193 | current->journal_info = h; | 209 | if (cur_trans->blocked && may_wait_transaction(root, type)) { |
210 | btrfs_commit_transaction(h, root); | ||
211 | goto again; | ||
212 | } | ||
213 | |||
214 | if (num_items > 0) { | ||
215 | ret = btrfs_trans_reserve_metadata(h, root, num_items, | ||
216 | &retries); | ||
217 | if (ret == -EAGAIN) { | ||
218 | btrfs_commit_transaction(h, root); | ||
219 | goto again; | ||
220 | } | ||
221 | if (ret < 0) { | ||
222 | btrfs_end_transaction(h, root); | ||
223 | return ERR_PTR(ret); | ||
224 | } | ||
225 | } | ||
194 | 226 | ||
195 | root->fs_info->running_transaction->use_count++; | 227 | mutex_lock(&root->fs_info->trans_mutex); |
196 | record_root_in_trans(h, root); | 228 | record_root_in_trans(h, root); |
197 | mutex_unlock(&root->fs_info->trans_mutex); | 229 | mutex_unlock(&root->fs_info->trans_mutex); |
230 | |||
231 | if (!current->journal_info && type != TRANS_USERSPACE) | ||
232 | current->journal_info = h; | ||
198 | return h; | 233 | return h; |
199 | } | 234 | } |
200 | 235 | ||
201 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | 236 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, |
202 | int num_blocks) | 237 | int num_items) |
203 | { | 238 | { |
204 | return start_transaction(root, num_blocks, TRANS_START); | 239 | return start_transaction(root, num_items, TRANS_START); |
205 | } | 240 | } |
206 | struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, | 241 | struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, |
207 | int num_blocks) | 242 | int num_blocks) |
208 | { | 243 | { |
209 | return start_transaction(root, num_blocks, TRANS_JOIN); | 244 | return start_transaction(root, 0, TRANS_JOIN); |
210 | } | 245 | } |
211 | 246 | ||
212 | struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, | 247 | struct btrfs_trans_handle *btrfs_start_ioctl_transaction(struct btrfs_root *r, |
213 | int num_blocks) | 248 | int num_blocks) |
214 | { | 249 | { |
215 | return start_transaction(r, num_blocks, TRANS_USERSPACE); | 250 | return start_transaction(r, 0, TRANS_USERSPACE); |
216 | } | 251 | } |
217 | 252 | ||
218 | /* wait for a transaction commit to be fully complete */ | 253 | /* wait for a transaction commit to be fully complete */ |
@@ -286,10 +321,36 @@ void btrfs_throttle(struct btrfs_root *root) | |||
286 | mutex_unlock(&root->fs_info->trans_mutex); | 321 | mutex_unlock(&root->fs_info->trans_mutex); |
287 | } | 322 | } |
288 | 323 | ||
324 | static int should_end_transaction(struct btrfs_trans_handle *trans, | ||
325 | struct btrfs_root *root) | ||
326 | { | ||
327 | int ret; | ||
328 | ret = btrfs_block_rsv_check(trans, root, | ||
329 | &root->fs_info->global_block_rsv, 0, 5); | ||
330 | return ret ? 1 : 0; | ||
331 | } | ||
332 | |||
333 | int btrfs_should_end_transaction(struct btrfs_trans_handle *trans, | ||
334 | struct btrfs_root *root) | ||
335 | { | ||
336 | struct btrfs_transaction *cur_trans = trans->transaction; | ||
337 | int updates; | ||
338 | |||
339 | if (cur_trans->blocked || cur_trans->delayed_refs.flushing) | ||
340 | return 1; | ||
341 | |||
342 | updates = trans->delayed_ref_updates; | ||
343 | trans->delayed_ref_updates = 0; | ||
344 | if (updates) | ||
345 | btrfs_run_delayed_refs(trans, root, updates); | ||
346 | |||
347 | return should_end_transaction(trans, root); | ||
348 | } | ||
349 | |||
289 | static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | 350 | static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, |
290 | struct btrfs_root *root, int throttle) | 351 | struct btrfs_root *root, int throttle) |
291 | { | 352 | { |
292 | struct btrfs_transaction *cur_trans; | 353 | struct btrfs_transaction *cur_trans = trans->transaction; |
293 | struct btrfs_fs_info *info = root->fs_info; | 354 | struct btrfs_fs_info *info = root->fs_info; |
294 | int count = 0; | 355 | int count = 0; |
295 | 356 | ||
@@ -313,9 +374,21 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
313 | count++; | 374 | count++; |
314 | } | 375 | } |
315 | 376 | ||
377 | btrfs_trans_release_metadata(trans, root); | ||
378 | |||
379 | if (!root->fs_info->open_ioctl_trans && | ||
380 | should_end_transaction(trans, root)) | ||
381 | trans->transaction->blocked = 1; | ||
382 | |||
383 | if (cur_trans->blocked && !cur_trans->in_commit) { | ||
384 | if (throttle) | ||
385 | return btrfs_commit_transaction(trans, root); | ||
386 | else | ||
387 | wake_up_process(info->transaction_kthread); | ||
388 | } | ||
389 | |||
316 | mutex_lock(&info->trans_mutex); | 390 | mutex_lock(&info->trans_mutex); |
317 | cur_trans = info->running_transaction; | 391 | WARN_ON(cur_trans != info->running_transaction); |
318 | WARN_ON(cur_trans != trans->transaction); | ||
319 | WARN_ON(cur_trans->num_writers < 1); | 392 | WARN_ON(cur_trans->num_writers < 1); |
320 | cur_trans->num_writers--; | 393 | cur_trans->num_writers--; |
321 | 394 | ||
@@ -603,6 +676,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
603 | 676 | ||
604 | btrfs_free_log(trans, root); | 677 | btrfs_free_log(trans, root); |
605 | btrfs_update_reloc_root(trans, root); | 678 | btrfs_update_reloc_root(trans, root); |
679 | btrfs_orphan_commit_root(trans, root); | ||
606 | 680 | ||
607 | if (root->commit_root != root->node) { | 681 | if (root->commit_root != root->node) { |
608 | switch_commit_root(root); | 682 | switch_commit_root(root); |
@@ -627,30 +701,30 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
627 | int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) | 701 | int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) |
628 | { | 702 | { |
629 | struct btrfs_fs_info *info = root->fs_info; | 703 | struct btrfs_fs_info *info = root->fs_info; |
630 | int ret; | ||
631 | struct btrfs_trans_handle *trans; | 704 | struct btrfs_trans_handle *trans; |
705 | int ret; | ||
632 | unsigned long nr; | 706 | unsigned long nr; |
633 | 707 | ||
634 | smp_mb(); | 708 | if (xchg(&root->defrag_running, 1)) |
635 | if (root->defrag_running) | ||
636 | return 0; | 709 | return 0; |
637 | trans = btrfs_start_transaction(root, 1); | 710 | |
638 | while (1) { | 711 | while (1) { |
639 | root->defrag_running = 1; | 712 | trans = btrfs_start_transaction(root, 0); |
713 | if (IS_ERR(trans)) | ||
714 | return PTR_ERR(trans); | ||
715 | |||
640 | ret = btrfs_defrag_leaves(trans, root, cacheonly); | 716 | ret = btrfs_defrag_leaves(trans, root, cacheonly); |
717 | |||
641 | nr = trans->blocks_used; | 718 | nr = trans->blocks_used; |
642 | btrfs_end_transaction(trans, root); | 719 | btrfs_end_transaction(trans, root); |
643 | btrfs_btree_balance_dirty(info->tree_root, nr); | 720 | btrfs_btree_balance_dirty(info->tree_root, nr); |
644 | cond_resched(); | 721 | cond_resched(); |
645 | 722 | ||
646 | trans = btrfs_start_transaction(root, 1); | ||
647 | if (root->fs_info->closing || ret != -EAGAIN) | 723 | if (root->fs_info->closing || ret != -EAGAIN) |
648 | break; | 724 | break; |
649 | } | 725 | } |
650 | root->defrag_running = 0; | 726 | root->defrag_running = 0; |
651 | smp_mb(); | 727 | return ret; |
652 | btrfs_end_transaction(trans, root); | ||
653 | return 0; | ||
654 | } | 728 | } |
655 | 729 | ||
656 | #if 0 | 730 | #if 0 |
@@ -758,47 +832,63 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
758 | struct btrfs_root *root = pending->root; | 832 | struct btrfs_root *root = pending->root; |
759 | struct btrfs_root *parent_root; | 833 | struct btrfs_root *parent_root; |
760 | struct inode *parent_inode; | 834 | struct inode *parent_inode; |
835 | struct dentry *dentry; | ||
761 | struct extent_buffer *tmp; | 836 | struct extent_buffer *tmp; |
762 | struct extent_buffer *old; | 837 | struct extent_buffer *old; |
763 | int ret; | 838 | int ret; |
764 | u64 objectid; | 839 | int retries = 0; |
765 | int namelen; | 840 | u64 to_reserve = 0; |
766 | u64 index = 0; | 841 | u64 index = 0; |
767 | 842 | u64 objectid; | |
768 | parent_inode = pending->dentry->d_parent->d_inode; | ||
769 | parent_root = BTRFS_I(parent_inode)->root; | ||
770 | 843 | ||
771 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 844 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
772 | if (!new_root_item) { | 845 | if (!new_root_item) { |
773 | ret = -ENOMEM; | 846 | pending->error = -ENOMEM; |
774 | goto fail; | 847 | goto fail; |
775 | } | 848 | } |
849 | |||
776 | ret = btrfs_find_free_objectid(trans, tree_root, 0, &objectid); | 850 | ret = btrfs_find_free_objectid(trans, tree_root, 0, &objectid); |
777 | if (ret) | 851 | if (ret) { |
852 | pending->error = ret; | ||
778 | goto fail; | 853 | goto fail; |
854 | } | ||
855 | |||
856 | btrfs_reloc_pre_snapshot(trans, pending, &to_reserve); | ||
857 | btrfs_orphan_pre_snapshot(trans, pending, &to_reserve); | ||
858 | |||
859 | if (to_reserve > 0) { | ||
860 | ret = btrfs_block_rsv_add(trans, root, &pending->block_rsv, | ||
861 | to_reserve, &retries); | ||
862 | if (ret) { | ||
863 | pending->error = ret; | ||
864 | goto fail; | ||
865 | } | ||
866 | } | ||
779 | 867 | ||
780 | key.objectid = objectid; | 868 | key.objectid = objectid; |
781 | /* record when the snapshot was created in key.offset */ | 869 | key.offset = (u64)-1; |
782 | key.offset = trans->transid; | 870 | key.type = BTRFS_ROOT_ITEM_KEY; |
783 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | ||
784 | 871 | ||
785 | memcpy(&pending->root_key, &key, sizeof(key)); | 872 | trans->block_rsv = &pending->block_rsv; |
786 | pending->root_key.offset = (u64)-1; | ||
787 | 873 | ||
874 | dentry = pending->dentry; | ||
875 | parent_inode = dentry->d_parent->d_inode; | ||
876 | parent_root = BTRFS_I(parent_inode)->root; | ||
788 | record_root_in_trans(trans, parent_root); | 877 | record_root_in_trans(trans, parent_root); |
878 | |||
789 | /* | 879 | /* |
790 | * insert the directory item | 880 | * insert the directory item |
791 | */ | 881 | */ |
792 | namelen = strlen(pending->name); | ||
793 | ret = btrfs_set_inode_index(parent_inode, &index); | 882 | ret = btrfs_set_inode_index(parent_inode, &index); |
794 | BUG_ON(ret); | 883 | BUG_ON(ret); |
795 | ret = btrfs_insert_dir_item(trans, parent_root, | 884 | ret = btrfs_insert_dir_item(trans, parent_root, |
796 | pending->name, namelen, | 885 | dentry->d_name.name, dentry->d_name.len, |
797 | parent_inode->i_ino, | 886 | parent_inode->i_ino, &key, |
798 | &pending->root_key, BTRFS_FT_DIR, index); | 887 | BTRFS_FT_DIR, index); |
799 | BUG_ON(ret); | 888 | BUG_ON(ret); |
800 | 889 | ||
801 | btrfs_i_size_write(parent_inode, parent_inode->i_size + namelen * 2); | 890 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
891 | dentry->d_name.len * 2); | ||
802 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | 892 | ret = btrfs_update_inode(trans, parent_root, parent_inode); |
803 | BUG_ON(ret); | 893 | BUG_ON(ret); |
804 | 894 | ||
@@ -815,22 +905,32 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
815 | free_extent_buffer(old); | 905 | free_extent_buffer(old); |
816 | 906 | ||
817 | btrfs_set_root_node(new_root_item, tmp); | 907 | btrfs_set_root_node(new_root_item, tmp); |
818 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 908 | /* record when the snapshot was created in key.offset */ |
819 | new_root_item); | 909 | key.offset = trans->transid; |
820 | BUG_ON(ret); | 910 | ret = btrfs_insert_root(trans, tree_root, &key, new_root_item); |
821 | btrfs_tree_unlock(tmp); | 911 | btrfs_tree_unlock(tmp); |
822 | free_extent_buffer(tmp); | 912 | free_extent_buffer(tmp); |
913 | BUG_ON(ret); | ||
823 | 914 | ||
824 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, | 915 | /* |
825 | pending->root_key.objectid, | 916 | * insert root back/forward references |
917 | */ | ||
918 | ret = btrfs_add_root_ref(trans, tree_root, objectid, | ||
826 | parent_root->root_key.objectid, | 919 | parent_root->root_key.objectid, |
827 | parent_inode->i_ino, index, pending->name, | 920 | parent_inode->i_ino, index, |
828 | namelen); | 921 | dentry->d_name.name, dentry->d_name.len); |
829 | BUG_ON(ret); | 922 | BUG_ON(ret); |
830 | 923 | ||
924 | key.offset = (u64)-1; | ||
925 | pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key); | ||
926 | BUG_ON(IS_ERR(pending->snap)); | ||
927 | |||
928 | btrfs_reloc_post_snapshot(trans, pending); | ||
929 | btrfs_orphan_post_snapshot(trans, pending); | ||
831 | fail: | 930 | fail: |
832 | kfree(new_root_item); | 931 | kfree(new_root_item); |
833 | return ret; | 932 | btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); |
933 | return 0; | ||
834 | } | 934 | } |
835 | 935 | ||
836 | /* | 936 | /* |
@@ -878,6 +978,16 @@ int btrfs_transaction_in_commit(struct btrfs_fs_info *info) | |||
878 | return ret; | 978 | return ret; |
879 | } | 979 | } |
880 | 980 | ||
981 | int btrfs_transaction_blocked(struct btrfs_fs_info *info) | ||
982 | { | ||
983 | int ret = 0; | ||
984 | spin_lock(&info->new_trans_lock); | ||
985 | if (info->running_transaction) | ||
986 | ret = info->running_transaction->blocked; | ||
987 | spin_unlock(&info->new_trans_lock); | ||
988 | return ret; | ||
989 | } | ||
990 | |||
881 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 991 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, |
882 | struct btrfs_root *root) | 992 | struct btrfs_root *root) |
883 | { | 993 | { |
@@ -899,6 +1009,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
899 | ret = btrfs_run_delayed_refs(trans, root, 0); | 1009 | ret = btrfs_run_delayed_refs(trans, root, 0); |
900 | BUG_ON(ret); | 1010 | BUG_ON(ret); |
901 | 1011 | ||
1012 | btrfs_trans_release_metadata(trans, root); | ||
1013 | |||
902 | cur_trans = trans->transaction; | 1014 | cur_trans = trans->transaction; |
903 | /* | 1015 | /* |
904 | * set the flushing flag so procs in this transaction have to | 1016 | * set the flushing flag so procs in this transaction have to |
@@ -951,9 +1063,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
951 | snap_pending = 1; | 1063 | snap_pending = 1; |
952 | 1064 | ||
953 | WARN_ON(cur_trans != trans->transaction); | 1065 | WARN_ON(cur_trans != trans->transaction); |
954 | prepare_to_wait(&cur_trans->writer_wait, &wait, | ||
955 | TASK_UNINTERRUPTIBLE); | ||
956 | |||
957 | if (cur_trans->num_writers > 1) | 1066 | if (cur_trans->num_writers > 1) |
958 | timeout = MAX_SCHEDULE_TIMEOUT; | 1067 | timeout = MAX_SCHEDULE_TIMEOUT; |
959 | else if (should_grow) | 1068 | else if (should_grow) |
@@ -976,6 +1085,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
976 | */ | 1085 | */ |
977 | btrfs_run_ordered_operations(root, 1); | 1086 | btrfs_run_ordered_operations(root, 1); |
978 | 1087 | ||
1088 | prepare_to_wait(&cur_trans->writer_wait, &wait, | ||
1089 | TASK_UNINTERRUPTIBLE); | ||
1090 | |||
979 | smp_mb(); | 1091 | smp_mb(); |
980 | if (cur_trans->num_writers > 1 || should_grow) | 1092 | if (cur_trans->num_writers > 1 || should_grow) |
981 | schedule_timeout(timeout); | 1093 | schedule_timeout(timeout); |
@@ -1103,9 +1215,9 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root) | |||
1103 | 1215 | ||
1104 | if (btrfs_header_backref_rev(root->node) < | 1216 | if (btrfs_header_backref_rev(root->node) < |
1105 | BTRFS_MIXED_BACKREF_REV) | 1217 | BTRFS_MIXED_BACKREF_REV) |
1106 | btrfs_drop_snapshot(root, 0); | 1218 | btrfs_drop_snapshot(root, NULL, 0); |
1107 | else | 1219 | else |
1108 | btrfs_drop_snapshot(root, 1); | 1220 | btrfs_drop_snapshot(root, NULL, 1); |
1109 | } | 1221 | } |
1110 | return 0; | 1222 | return 0; |
1111 | } | 1223 | } |