aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/transaction.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-01-08 15:46:30 -0500
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:03:59 -0400
commit3063d29f2a4d4a4e9fa1ec77c124514f287c6da7 (patch)
tree61aa53d18c6684a327b6166764eecbea9d0e6b5b /fs/btrfs/transaction.c
parentdc17ff8f11d129db9e83ab7244769e4eae05e14d (diff)
Btrfs: Move snapshot creation to commit time
It is very difficult to create a consistent snapshot of the btree when other writers may update the btree before the commit is done. This changes the snapshot creation to happen during the commit, while no other updates are possible. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/transaction.c')
-rw-r--r--fs/btrfs/transaction.c81
1 files changed, 78 insertions, 3 deletions
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 3ed5868e7c0f..dc9865323e38 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -66,6 +66,7 @@ static int join_transaction(struct btrfs_root *root)
66 cur_trans->use_count = 1; 66 cur_trans->use_count = 1;
67 cur_trans->commit_done = 0; 67 cur_trans->commit_done = 0;
68 cur_trans->start_time = get_seconds(); 68 cur_trans->start_time = get_seconds();
69 INIT_LIST_HEAD(&cur_trans->pending_snapshots);
69 list_add_tail(&cur_trans->list, &root->fs_info->trans_list); 70 list_add_tail(&cur_trans->list, &root->fs_info->trans_list);
70 btrfs_ordered_inode_tree_init(&cur_trans->ordered_inode_tree); 71 btrfs_ordered_inode_tree_init(&cur_trans->ordered_inode_tree);
71 extent_map_tree_init(&cur_trans->dirty_pages, 72 extent_map_tree_init(&cur_trans->dirty_pages,
@@ -481,10 +482,8 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
481 struct inode *inode; 482 struct inode *inode;
482 u64 root_objectid = 0; 483 u64 root_objectid = 0;
483 u64 objectid = 0; 484 u64 objectid = 0;
484 u64 transid = trans->transid;
485 int ret; 485 int ret;
486 486
487printk("write ordered trans %Lu\n", transid);
488 while(1) { 487 while(1) {
489 ret = btrfs_find_first_ordered_inode( 488 ret = btrfs_find_first_ordered_inode(
490 &cur_trans->ordered_inode_tree, 489 &cur_trans->ordered_inode_tree,
@@ -524,7 +523,80 @@ printk("write ordered trans %Lu\n", transid);
524 mutex_lock(&root->fs_info->fs_mutex); 523 mutex_lock(&root->fs_info->fs_mutex);
525 mutex_lock(&root->fs_info->trans_mutex); 524 mutex_lock(&root->fs_info->trans_mutex);
526 } 525 }
527printk("done write ordered trans %Lu\n", transid); 526 return 0;
527}
528
529static int create_pending_snapshot(struct btrfs_trans_handle *trans,
530 struct btrfs_fs_info *fs_info,
531 struct btrfs_pending_snapshot *pending)
532{
533 struct btrfs_key key;
534 struct btrfs_root_item new_root_item;
535 struct btrfs_root *tree_root = fs_info->tree_root;
536 struct btrfs_root *root = pending->root;
537 struct extent_buffer *tmp;
538 int ret;
539 u64 objectid;
540
541 ret = btrfs_find_free_objectid(trans, tree_root, 0, &objectid);
542 if (ret)
543 goto fail;
544
545 memcpy(&new_root_item, &root->root_item, sizeof(new_root_item));
546
547 key.objectid = objectid;
548 key.offset = 1;
549 btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
550
551 extent_buffer_get(root->node);
552 btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp);
553 free_extent_buffer(tmp);
554
555 btrfs_copy_root(trans, root, root->node, &tmp, objectid);
556
557 btrfs_set_root_bytenr(&new_root_item, tmp->start);
558 btrfs_set_root_level(&new_root_item, btrfs_header_level(tmp));
559 ret = btrfs_insert_root(trans, root->fs_info->tree_root, &key,
560 &new_root_item);
561 free_extent_buffer(tmp);
562 if (ret)
563 goto fail;
564
565 /*
566 * insert the directory item
567 */
568 key.offset = (u64)-1;
569 ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root,
570 pending->name, strlen(pending->name),
571 root->fs_info->sb->s_root->d_inode->i_ino,
572 &key, BTRFS_FT_DIR);
573
574 if (ret)
575 goto fail;
576
577 ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root,
578 pending->name, strlen(pending->name), objectid,
579 root->fs_info->sb->s_root->d_inode->i_ino);
580fail:
581 return ret;
582}
583
584static int create_pending_snapshots(struct btrfs_trans_handle *trans,
585 struct btrfs_fs_info *fs_info)
586{
587 struct btrfs_pending_snapshot *pending;
588 struct list_head *head = &trans->transaction->pending_snapshots;
589 int ret;
590
591 while(!list_empty(head)) {
592 pending = list_entry(head->next,
593 struct btrfs_pending_snapshot, list);
594 ret = create_pending_snapshot(trans, fs_info, pending);
595 BUG_ON(ret);
596 list_del(&pending->list);
597 kfree(pending->name);
598 kfree(pending);
599 }
528 return 0; 600 return 0;
529} 601}
530 602
@@ -610,6 +682,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
610 } while (cur_trans->num_writers > 1 || 682 } while (cur_trans->num_writers > 1 ||
611 (cur_trans->num_joined != joined)); 683 (cur_trans->num_joined != joined));
612 684
685 ret = create_pending_snapshots(trans, root->fs_info);
686 BUG_ON(ret);
687
613 WARN_ON(cur_trans != trans->transaction); 688 WARN_ON(cur_trans != trans->transaction);
614 689
615 ret = add_dirty_roots(trans, &root->fs_info->fs_roots_radix, 690 ret = add_dirty_roots(trans, &root->fs_info->fs_roots_radix,