diff options
Diffstat (limited to 'fs/btrfs/transaction.c')
| -rw-r--r-- | fs/btrfs/transaction.c | 322 |
1 files changed, 196 insertions, 126 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index b2acc79f1b34..66e4c66cc63b 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
| 21 | #include <linux/writeback.h> | 22 | #include <linux/writeback.h> |
| 22 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
| @@ -69,7 +70,7 @@ static noinline int join_transaction(struct btrfs_root *root) | |||
| 69 | cur_trans->commit_done = 0; | 70 | cur_trans->commit_done = 0; |
| 70 | cur_trans->start_time = get_seconds(); | 71 | cur_trans->start_time = get_seconds(); |
| 71 | 72 | ||
| 72 | cur_trans->delayed_refs.root.rb_node = NULL; | 73 | cur_trans->delayed_refs.root = RB_ROOT; |
| 73 | cur_trans->delayed_refs.num_entries = 0; | 74 | cur_trans->delayed_refs.num_entries = 0; |
| 74 | cur_trans->delayed_refs.num_heads_ready = 0; | 75 | cur_trans->delayed_refs.num_heads_ready = 0; |
| 75 | cur_trans->delayed_refs.num_heads = 0; | 76 | cur_trans->delayed_refs.num_heads = 0; |
| @@ -147,18 +148,13 @@ static void wait_current_trans(struct btrfs_root *root) | |||
| 147 | while (1) { | 148 | while (1) { |
| 148 | prepare_to_wait(&root->fs_info->transaction_wait, &wait, | 149 | prepare_to_wait(&root->fs_info->transaction_wait, &wait, |
| 149 | TASK_UNINTERRUPTIBLE); | 150 | TASK_UNINTERRUPTIBLE); |
| 150 | if (cur_trans->blocked) { | 151 | if (!cur_trans->blocked) |
| 151 | mutex_unlock(&root->fs_info->trans_mutex); | ||
| 152 | schedule(); | ||
| 153 | mutex_lock(&root->fs_info->trans_mutex); | ||
| 154 | finish_wait(&root->fs_info->transaction_wait, | ||
| 155 | &wait); | ||
| 156 | } else { | ||
| 157 | finish_wait(&root->fs_info->transaction_wait, | ||
| 158 | &wait); | ||
| 159 | break; | 152 | break; |
| 160 | } | 153 | mutex_unlock(&root->fs_info->trans_mutex); |
| 154 | schedule(); | ||
| 155 | mutex_lock(&root->fs_info->trans_mutex); | ||
| 161 | } | 156 | } |
| 157 | finish_wait(&root->fs_info->transaction_wait, &wait); | ||
| 162 | put_transaction(cur_trans); | 158 | put_transaction(cur_trans); |
| 163 | } | 159 | } |
| 164 | } | 160 | } |
| @@ -169,54 +165,89 @@ enum btrfs_trans_type { | |||
| 169 | TRANS_USERSPACE, | 165 | TRANS_USERSPACE, |
| 170 | }; | 166 | }; |
| 171 | 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 | |||
| 172 | static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, | 177 | static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root, |
| 173 | int num_blocks, int type) | 178 | u64 num_items, int type) |
| 174 | { | 179 | { |
| 175 | struct btrfs_trans_handle *h = | 180 | struct btrfs_trans_handle *h; |
| 176 | kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); | 181 | struct btrfs_transaction *cur_trans; |
| 182 | int retries = 0; | ||
| 177 | 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); | ||
| 178 | 188 | ||
| 179 | mutex_lock(&root->fs_info->trans_mutex); | 189 | mutex_lock(&root->fs_info->trans_mutex); |
| 180 | if (!root->fs_info->log_root_recovering && | 190 | if (may_wait_transaction(root, type)) |
| 181 | ((type == TRANS_START && !root->fs_info->open_ioctl_trans) || | ||
| 182 | type == TRANS_USERSPACE)) | ||
| 183 | wait_current_trans(root); | 191 | wait_current_trans(root); |
| 192 | |||
| 184 | ret = join_transaction(root); | 193 | ret = join_transaction(root); |
| 185 | BUG_ON(ret); | 194 | BUG_ON(ret); |
| 186 | 195 | ||
| 187 | h->transid = root->fs_info->running_transaction->transid; | 196 | cur_trans = root->fs_info->running_transaction; |
| 188 | h->transaction = root->fs_info->running_transaction; | 197 | cur_trans->use_count++; |
| 189 | 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; | ||
| 190 | h->blocks_used = 0; | 202 | h->blocks_used = 0; |
| 191 | h->block_group = 0; | 203 | h->block_group = 0; |
| 192 | h->alloc_exclude_nr = 0; | 204 | h->bytes_reserved = 0; |
| 193 | h->alloc_exclude_start = 0; | ||
| 194 | h->delayed_ref_updates = 0; | 205 | h->delayed_ref_updates = 0; |
| 206 | h->block_rsv = NULL; | ||
| 195 | 207 | ||
| 196 | if (!current->journal_info && type != TRANS_USERSPACE) | 208 | smp_mb(); |
| 197 | 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 | } | ||
| 198 | 226 | ||
| 199 | root->fs_info->running_transaction->use_count++; | 227 | mutex_lock(&root->fs_info->trans_mutex); |
| 200 | record_root_in_trans(h, root); | 228 | record_root_in_trans(h, root); |
| 201 | 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; | ||
| 202 | return h; | 233 | return h; |
| 203 | } | 234 | } |
| 204 | 235 | ||
| 205 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, | 236 | struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, |
| 206 | int num_blocks) | 237 | int num_items) |
| 207 | { | 238 | { |
| 208 | return start_transaction(root, num_blocks, TRANS_START); | 239 | return start_transaction(root, num_items, TRANS_START); |
| 209 | } | 240 | } |
| 210 | struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, | 241 | struct btrfs_trans_handle *btrfs_join_transaction(struct btrfs_root *root, |
| 211 | int num_blocks) | 242 | int num_blocks) |
| 212 | { | 243 | { |
| 213 | return start_transaction(root, num_blocks, TRANS_JOIN); | 244 | return start_transaction(root, 0, TRANS_JOIN); |
| 214 | } | 245 | } |
| 215 | 246 | ||
| 216 | 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, |
| 217 | int num_blocks) | 248 | int num_blocks) |
| 218 | { | 249 | { |
| 219 | return start_transaction(r, num_blocks, TRANS_USERSPACE); | 250 | return start_transaction(r, 0, TRANS_USERSPACE); |
| 220 | } | 251 | } |
| 221 | 252 | ||
| 222 | /* wait for a transaction commit to be fully complete */ | 253 | /* wait for a transaction commit to be fully complete */ |
| @@ -290,10 +321,36 @@ void btrfs_throttle(struct btrfs_root *root) | |||
| 290 | mutex_unlock(&root->fs_info->trans_mutex); | 321 | mutex_unlock(&root->fs_info->trans_mutex); |
| 291 | } | 322 | } |
| 292 | 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 | |||
| 293 | static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | 350 | static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, |
| 294 | struct btrfs_root *root, int throttle) | 351 | struct btrfs_root *root, int throttle) |
| 295 | { | 352 | { |
| 296 | struct btrfs_transaction *cur_trans; | 353 | struct btrfs_transaction *cur_trans = trans->transaction; |
| 297 | struct btrfs_fs_info *info = root->fs_info; | 354 | struct btrfs_fs_info *info = root->fs_info; |
| 298 | int count = 0; | 355 | int count = 0; |
| 299 | 356 | ||
| @@ -317,9 +374,21 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans, | |||
| 317 | count++; | 374 | count++; |
| 318 | } | 375 | } |
| 319 | 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 | |||
| 320 | mutex_lock(&info->trans_mutex); | 390 | mutex_lock(&info->trans_mutex); |
| 321 | cur_trans = info->running_transaction; | 391 | WARN_ON(cur_trans != info->running_transaction); |
| 322 | WARN_ON(cur_trans != trans->transaction); | ||
| 323 | WARN_ON(cur_trans->num_writers < 1); | 392 | WARN_ON(cur_trans->num_writers < 1); |
| 324 | cur_trans->num_writers--; | 393 | cur_trans->num_writers--; |
| 325 | 394 | ||
| @@ -607,6 +676,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 607 | 676 | ||
| 608 | btrfs_free_log(trans, root); | 677 | btrfs_free_log(trans, root); |
| 609 | btrfs_update_reloc_root(trans, root); | 678 | btrfs_update_reloc_root(trans, root); |
| 679 | btrfs_orphan_commit_root(trans, root); | ||
| 610 | 680 | ||
| 611 | if (root->commit_root != root->node) { | 681 | if (root->commit_root != root->node) { |
| 612 | switch_commit_root(root); | 682 | switch_commit_root(root); |
| @@ -631,30 +701,30 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans, | |||
| 631 | int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) | 701 | int btrfs_defrag_root(struct btrfs_root *root, int cacheonly) |
| 632 | { | 702 | { |
| 633 | struct btrfs_fs_info *info = root->fs_info; | 703 | struct btrfs_fs_info *info = root->fs_info; |
| 634 | int ret; | ||
| 635 | struct btrfs_trans_handle *trans; | 704 | struct btrfs_trans_handle *trans; |
| 705 | int ret; | ||
| 636 | unsigned long nr; | 706 | unsigned long nr; |
| 637 | 707 | ||
| 638 | smp_mb(); | 708 | if (xchg(&root->defrag_running, 1)) |
| 639 | if (root->defrag_running) | ||
| 640 | return 0; | 709 | return 0; |
| 641 | trans = btrfs_start_transaction(root, 1); | 710 | |
| 642 | while (1) { | 711 | while (1) { |
| 643 | root->defrag_running = 1; | 712 | trans = btrfs_start_transaction(root, 0); |
| 713 | if (IS_ERR(trans)) | ||
| 714 | return PTR_ERR(trans); | ||
| 715 | |||
| 644 | ret = btrfs_defrag_leaves(trans, root, cacheonly); | 716 | ret = btrfs_defrag_leaves(trans, root, cacheonly); |
| 717 | |||
| 645 | nr = trans->blocks_used; | 718 | nr = trans->blocks_used; |
| 646 | btrfs_end_transaction(trans, root); | 719 | btrfs_end_transaction(trans, root); |
| 647 | btrfs_btree_balance_dirty(info->tree_root, nr); | 720 | btrfs_btree_balance_dirty(info->tree_root, nr); |
| 648 | cond_resched(); | 721 | cond_resched(); |
| 649 | 722 | ||
| 650 | trans = btrfs_start_transaction(root, 1); | ||
| 651 | if (root->fs_info->closing || ret != -EAGAIN) | 723 | if (root->fs_info->closing || ret != -EAGAIN) |
| 652 | break; | 724 | break; |
| 653 | } | 725 | } |
| 654 | root->defrag_running = 0; | 726 | root->defrag_running = 0; |
| 655 | smp_mb(); | 727 | return ret; |
| 656 | btrfs_end_transaction(trans, root); | ||
| 657 | return 0; | ||
| 658 | } | 728 | } |
| 659 | 729 | ||
| 660 | #if 0 | 730 | #if 0 |
| @@ -760,29 +830,72 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 760 | struct btrfs_root_item *new_root_item; | 830 | struct btrfs_root_item *new_root_item; |
| 761 | struct btrfs_root *tree_root = fs_info->tree_root; | 831 | struct btrfs_root *tree_root = fs_info->tree_root; |
| 762 | struct btrfs_root *root = pending->root; | 832 | struct btrfs_root *root = pending->root; |
| 833 | struct btrfs_root *parent_root; | ||
| 834 | struct inode *parent_inode; | ||
| 835 | struct dentry *dentry; | ||
| 763 | struct extent_buffer *tmp; | 836 | struct extent_buffer *tmp; |
| 764 | struct extent_buffer *old; | 837 | struct extent_buffer *old; |
| 765 | int ret; | 838 | int ret; |
| 839 | int retries = 0; | ||
| 840 | u64 to_reserve = 0; | ||
| 841 | u64 index = 0; | ||
| 766 | u64 objectid; | 842 | u64 objectid; |
| 767 | 843 | ||
| 768 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 844 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
| 769 | if (!new_root_item) { | 845 | if (!new_root_item) { |
| 770 | ret = -ENOMEM; | 846 | pending->error = -ENOMEM; |
| 771 | goto fail; | 847 | goto fail; |
| 772 | } | 848 | } |
| 849 | |||
| 773 | ret = btrfs_find_free_objectid(trans, tree_root, 0, &objectid); | 850 | ret = btrfs_find_free_objectid(trans, tree_root, 0, &objectid); |
| 774 | if (ret) | 851 | if (ret) { |
| 852 | pending->error = ret; | ||
| 775 | 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 | } | ||
| 867 | |||
| 868 | key.objectid = objectid; | ||
| 869 | key.offset = (u64)-1; | ||
| 870 | key.type = BTRFS_ROOT_ITEM_KEY; | ||
| 871 | |||
| 872 | trans->block_rsv = &pending->block_rsv; | ||
| 873 | |||
| 874 | dentry = pending->dentry; | ||
| 875 | parent_inode = dentry->d_parent->d_inode; | ||
| 876 | parent_root = BTRFS_I(parent_inode)->root; | ||
| 877 | record_root_in_trans(trans, parent_root); | ||
| 878 | |||
| 879 | /* | ||
| 880 | * insert the directory item | ||
| 881 | */ | ||
| 882 | ret = btrfs_set_inode_index(parent_inode, &index); | ||
| 883 | BUG_ON(ret); | ||
| 884 | ret = btrfs_insert_dir_item(trans, parent_root, | ||
| 885 | dentry->d_name.name, dentry->d_name.len, | ||
| 886 | parent_inode->i_ino, &key, | ||
| 887 | BTRFS_FT_DIR, index); | ||
| 888 | BUG_ON(ret); | ||
| 889 | |||
| 890 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | ||
| 891 | dentry->d_name.len * 2); | ||
| 892 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | ||
| 893 | BUG_ON(ret); | ||
| 776 | 894 | ||
| 777 | record_root_in_trans(trans, root); | 895 | record_root_in_trans(trans, root); |
| 778 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); | 896 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); |
| 779 | memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); | 897 | memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); |
| 780 | 898 | ||
| 781 | key.objectid = objectid; | ||
| 782 | /* record when the snapshot was created in key.offset */ | ||
| 783 | key.offset = trans->transid; | ||
| 784 | btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY); | ||
| 785 | |||
| 786 | old = btrfs_lock_root_node(root); | 899 | old = btrfs_lock_root_node(root); |
| 787 | btrfs_cow_block(trans, root, old, NULL, 0, &old); | 900 | btrfs_cow_block(trans, root, old, NULL, 0, &old); |
| 788 | btrfs_set_lock_blocking(old); | 901 | btrfs_set_lock_blocking(old); |
| @@ -792,62 +905,32 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 792 | free_extent_buffer(old); | 905 | free_extent_buffer(old); |
| 793 | 906 | ||
| 794 | btrfs_set_root_node(new_root_item, tmp); | 907 | btrfs_set_root_node(new_root_item, tmp); |
| 795 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key, | 908 | /* record when the snapshot was created in key.offset */ |
| 796 | new_root_item); | 909 | key.offset = trans->transid; |
| 910 | ret = btrfs_insert_root(trans, tree_root, &key, new_root_item); | ||
| 797 | btrfs_tree_unlock(tmp); | 911 | btrfs_tree_unlock(tmp); |
| 798 | free_extent_buffer(tmp); | 912 | free_extent_buffer(tmp); |
| 799 | if (ret) | 913 | BUG_ON(ret); |
| 800 | goto fail; | ||
| 801 | |||
| 802 | key.offset = (u64)-1; | ||
| 803 | memcpy(&pending->root_key, &key, sizeof(key)); | ||
| 804 | fail: | ||
| 805 | kfree(new_root_item); | ||
| 806 | return ret; | ||
| 807 | } | ||
| 808 | |||
| 809 | static noinline int finish_pending_snapshot(struct btrfs_fs_info *fs_info, | ||
| 810 | struct btrfs_pending_snapshot *pending) | ||
| 811 | { | ||
| 812 | int ret; | ||
| 813 | int namelen; | ||
| 814 | u64 index = 0; | ||
| 815 | struct btrfs_trans_handle *trans; | ||
| 816 | struct inode *parent_inode; | ||
| 817 | struct btrfs_root *parent_root; | ||
| 818 | |||
| 819 | parent_inode = pending->dentry->d_parent->d_inode; | ||
| 820 | parent_root = BTRFS_I(parent_inode)->root; | ||
| 821 | trans = btrfs_join_transaction(parent_root, 1); | ||
| 822 | 914 | ||
| 823 | /* | 915 | /* |
| 824 | * insert the directory item | 916 | * insert root back/forward references |
| 825 | */ | 917 | */ |
| 826 | namelen = strlen(pending->name); | 918 | ret = btrfs_add_root_ref(trans, tree_root, objectid, |
| 827 | ret = btrfs_set_inode_index(parent_inode, &index); | ||
| 828 | ret = btrfs_insert_dir_item(trans, parent_root, | ||
| 829 | pending->name, namelen, | ||
| 830 | parent_inode->i_ino, | ||
| 831 | &pending->root_key, BTRFS_FT_DIR, index); | ||
| 832 | |||
| 833 | if (ret) | ||
| 834 | goto fail; | ||
| 835 | |||
| 836 | btrfs_i_size_write(parent_inode, parent_inode->i_size + namelen * 2); | ||
| 837 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | ||
| 838 | BUG_ON(ret); | ||
| 839 | |||
| 840 | ret = btrfs_add_root_ref(trans, parent_root->fs_info->tree_root, | ||
| 841 | pending->root_key.objectid, | ||
| 842 | parent_root->root_key.objectid, | 919 | parent_root->root_key.objectid, |
| 843 | parent_inode->i_ino, index, pending->name, | 920 | parent_inode->i_ino, index, |
| 844 | namelen); | 921 | dentry->d_name.name, dentry->d_name.len); |
| 845 | |||
| 846 | BUG_ON(ret); | 922 | BUG_ON(ret); |
| 847 | 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); | ||
| 848 | fail: | 930 | fail: |
| 849 | btrfs_end_transaction(trans, fs_info->fs_root); | 931 | kfree(new_root_item); |
| 850 | return ret; | 932 | btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1); |
| 933 | return 0; | ||
| 851 | } | 934 | } |
| 852 | 935 | ||
| 853 | /* | 936 | /* |
| @@ -867,25 +950,6 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | |||
| 867 | return 0; | 950 | return 0; |
| 868 | } | 951 | } |
| 869 | 952 | ||
| 870 | static noinline int finish_pending_snapshots(struct btrfs_trans_handle *trans, | ||
| 871 | struct btrfs_fs_info *fs_info) | ||
| 872 | { | ||
| 873 | struct btrfs_pending_snapshot *pending; | ||
| 874 | struct list_head *head = &trans->transaction->pending_snapshots; | ||
| 875 | int ret; | ||
| 876 | |||
| 877 | while (!list_empty(head)) { | ||
| 878 | pending = list_entry(head->next, | ||
| 879 | struct btrfs_pending_snapshot, list); | ||
| 880 | ret = finish_pending_snapshot(fs_info, pending); | ||
| 881 | BUG_ON(ret); | ||
| 882 | list_del(&pending->list); | ||
| 883 | kfree(pending->name); | ||
| 884 | kfree(pending); | ||
| 885 | } | ||
| 886 | return 0; | ||
| 887 | } | ||
| 888 | |||
| 889 | static void update_super_roots(struct btrfs_root *root) | 953 | static void update_super_roots(struct btrfs_root *root) |
| 890 | { | 954 | { |
| 891 | struct btrfs_root_item *root_item; | 955 | struct btrfs_root_item *root_item; |
| @@ -914,6 +978,16 @@ int btrfs_transaction_in_commit(struct btrfs_fs_info *info) | |||
| 914 | return ret; | 978 | return ret; |
| 915 | } | 979 | } |
| 916 | 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 | |||
| 917 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | 991 | int btrfs_commit_transaction(struct btrfs_trans_handle *trans, |
| 918 | struct btrfs_root *root) | 992 | struct btrfs_root *root) |
| 919 | { | 993 | { |
| @@ -935,6 +1009,8 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 935 | ret = btrfs_run_delayed_refs(trans, root, 0); | 1009 | ret = btrfs_run_delayed_refs(trans, root, 0); |
| 936 | BUG_ON(ret); | 1010 | BUG_ON(ret); |
| 937 | 1011 | ||
| 1012 | btrfs_trans_release_metadata(trans, root); | ||
| 1013 | |||
| 938 | cur_trans = trans->transaction; | 1014 | cur_trans = trans->transaction; |
| 939 | /* | 1015 | /* |
| 940 | * set the flushing flag so procs in this transaction have to | 1016 | * set the flushing flag so procs in this transaction have to |
| @@ -987,9 +1063,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 987 | snap_pending = 1; | 1063 | snap_pending = 1; |
| 988 | 1064 | ||
| 989 | WARN_ON(cur_trans != trans->transaction); | 1065 | WARN_ON(cur_trans != trans->transaction); |
| 990 | prepare_to_wait(&cur_trans->writer_wait, &wait, | ||
| 991 | TASK_UNINTERRUPTIBLE); | ||
| 992 | |||
| 993 | if (cur_trans->num_writers > 1) | 1066 | if (cur_trans->num_writers > 1) |
| 994 | timeout = MAX_SCHEDULE_TIMEOUT; | 1067 | timeout = MAX_SCHEDULE_TIMEOUT; |
| 995 | else if (should_grow) | 1068 | else if (should_grow) |
| @@ -997,13 +1070,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 997 | 1070 | ||
| 998 | mutex_unlock(&root->fs_info->trans_mutex); | 1071 | mutex_unlock(&root->fs_info->trans_mutex); |
| 999 | 1072 | ||
| 1000 | if (flush_on_commit) { | 1073 | if (flush_on_commit || snap_pending) { |
| 1001 | btrfs_start_delalloc_inodes(root, 1); | 1074 | btrfs_start_delalloc_inodes(root, 1); |
| 1002 | ret = btrfs_wait_ordered_extents(root, 0, 1); | 1075 | ret = btrfs_wait_ordered_extents(root, 0, 1); |
| 1003 | BUG_ON(ret); | 1076 | BUG_ON(ret); |
| 1004 | } else if (snap_pending) { | ||
| 1005 | ret = btrfs_wait_ordered_extents(root, 0, 1); | ||
| 1006 | BUG_ON(ret); | ||
| 1007 | } | 1077 | } |
| 1008 | 1078 | ||
| 1009 | /* | 1079 | /* |
| @@ -1015,6 +1085,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1015 | */ | 1085 | */ |
| 1016 | btrfs_run_ordered_operations(root, 1); | 1086 | btrfs_run_ordered_operations(root, 1); |
| 1017 | 1087 | ||
| 1088 | prepare_to_wait(&cur_trans->writer_wait, &wait, | ||
| 1089 | TASK_UNINTERRUPTIBLE); | ||
| 1090 | |||
| 1018 | smp_mb(); | 1091 | smp_mb(); |
| 1019 | if (cur_trans->num_writers > 1 || should_grow) | 1092 | if (cur_trans->num_writers > 1 || should_grow) |
| 1020 | schedule_timeout(timeout); | 1093 | schedule_timeout(timeout); |
| @@ -1100,9 +1173,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1100 | 1173 | ||
| 1101 | btrfs_finish_extent_commit(trans, root); | 1174 | btrfs_finish_extent_commit(trans, root); |
| 1102 | 1175 | ||
| 1103 | /* do the directory inserts of any pending snapshot creations */ | ||
| 1104 | finish_pending_snapshots(trans, root->fs_info); | ||
| 1105 | |||
| 1106 | mutex_lock(&root->fs_info->trans_mutex); | 1176 | mutex_lock(&root->fs_info->trans_mutex); |
| 1107 | 1177 | ||
| 1108 | cur_trans->commit_done = 1; | 1178 | cur_trans->commit_done = 1; |
| @@ -1145,9 +1215,9 @@ int btrfs_clean_old_snapshots(struct btrfs_root *root) | |||
| 1145 | 1215 | ||
| 1146 | if (btrfs_header_backref_rev(root->node) < | 1216 | if (btrfs_header_backref_rev(root->node) < |
| 1147 | BTRFS_MIXED_BACKREF_REV) | 1217 | BTRFS_MIXED_BACKREF_REV) |
| 1148 | btrfs_drop_snapshot(root, 0); | 1218 | btrfs_drop_snapshot(root, NULL, 0); |
| 1149 | else | 1219 | else |
| 1150 | btrfs_drop_snapshot(root, 1); | 1220 | btrfs_drop_snapshot(root, NULL, 1); |
| 1151 | } | 1221 | } |
| 1152 | return 0; | 1222 | return 0; |
| 1153 | } | 1223 | } |
