Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 199c2a9c authored by Miao Xie's avatar Miao Xie Committed by Josef Bacik
Browse files

Btrfs: introduce per-subvolume ordered extent list



The reason we introduce per-subvolume ordered extent list is the same
as the per-subvolume delalloc inode list.

Signed-off-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
parent eb73c1b7
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -1437,17 +1437,18 @@ struct btrfs_fs_info {
	atomic_t open_ioctl_trans;

	/*
	 * this is used by the balancing code to wait for all the pending
	 * ordered extents
	 * this is used to protect the following list -- ordered_roots.
	 */
	spinlock_t ordered_extent_lock;
	spinlock_t ordered_root_lock;

	/*
	 * all of the data=ordered extents pending writeback
	 * all fs/file tree roots in which there are data=ordered extents
	 * pending writeback are added into this list.
	 *
	 * these can span multiple transactions and basically include
	 * every dirty data page that isn't from nodatacow
	 */
	struct list_head ordered_extents;
	struct list_head ordered_roots;

	spinlock_t delalloc_root_lock;
	/* all fs/file tree roots that have delalloc inodes. */
@@ -1753,6 +1754,20 @@ struct btrfs_root {
	struct list_head delalloc_inodes;
	struct list_head delalloc_root;
	u64 nr_delalloc_inodes;
	/*
	 * this is used by the balancing code to wait for all the pending
	 * ordered extents
	 */
	spinlock_t ordered_extent_lock;

	/*
	 * all of the data=ordered extents pending writeback
	 * these can span multiple transactions and basically include
	 * every dirty data page that isn't from nodatacow
	 */
	struct list_head ordered_extents;
	struct list_head ordered_root;
	u64 nr_ordered_extents;
};

struct btrfs_ioctl_defrag_range_args {
+2 −2
Original line number Diff line number Diff line
@@ -400,7 +400,7 @@ int btrfs_dev_replace_start(struct btrfs_root *root,
	args->result = BTRFS_IOCTL_DEV_REPLACE_RESULT_NO_ERROR;
	btrfs_dev_replace_unlock(dev_replace);

	btrfs_wait_ordered_extents(root, 0);
	btrfs_wait_all_ordered_extents(root->fs_info, 0);

	/* force writing the updated state information to disk */
	trans = btrfs_start_transaction(root, 0);
@@ -475,7 +475,7 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
		mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
		return ret;
	}
	btrfs_wait_ordered_extents(root, 0);
	btrfs_wait_all_ordered_extents(root->fs_info, 0);

	trans = btrfs_start_transaction(root, 0);
	if (IS_ERR(trans)) {
+35 −10
Original line number Diff line number Diff line
@@ -1192,6 +1192,7 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
	root->last_trans = 0;
	root->highest_objectid = 0;
	root->nr_delalloc_inodes = 0;
	root->nr_ordered_extents = 0;
	root->name = NULL;
	root->inode_tree = RB_ROOT;
	INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC);
@@ -1202,11 +1203,14 @@ static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
	INIT_LIST_HEAD(&root->root_list);
	INIT_LIST_HEAD(&root->delalloc_inodes);
	INIT_LIST_HEAD(&root->delalloc_root);
	INIT_LIST_HEAD(&root->ordered_extents);
	INIT_LIST_HEAD(&root->ordered_root);
	INIT_LIST_HEAD(&root->logged_list[0]);
	INIT_LIST_HEAD(&root->logged_list[1]);
	spin_lock_init(&root->orphan_lock);
	spin_lock_init(&root->inode_lock);
	spin_lock_init(&root->delalloc_lock);
	spin_lock_init(&root->ordered_extent_lock);
	spin_lock_init(&root->accounting_lock);
	spin_lock_init(&root->log_extents_lock[0]);
	spin_lock_init(&root->log_extents_lock[1]);
@@ -2193,8 +2197,8 @@ int open_ctree(struct super_block *sb,
	fs_info->thread_pool_size = min_t(unsigned long,
					  num_online_cpus() + 2, 8);

	INIT_LIST_HEAD(&fs_info->ordered_extents);
	spin_lock_init(&fs_info->ordered_extent_lock);
	INIT_LIST_HEAD(&fs_info->ordered_roots);
	spin_lock_init(&fs_info->ordered_root_lock);
	fs_info->delayed_root = kmalloc(sizeof(struct btrfs_delayed_root),
					GFP_NOFS);
	if (!fs_info->delayed_root) {
@@ -3683,7 +3687,7 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t,
	INIT_LIST_HEAD(&splice);

	mutex_lock(&root->fs_info->ordered_operations_mutex);
	spin_lock(&root->fs_info->ordered_extent_lock);
	spin_lock(&root->fs_info->ordered_root_lock);

	list_splice_init(&t->ordered_operations, &splice);
	while (!list_empty(&splice)) {
@@ -3691,14 +3695,14 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t,
					 ordered_operations);

		list_del_init(&btrfs_inode->ordered_operations);
		spin_unlock(&root->fs_info->ordered_extent_lock);
		spin_unlock(&root->fs_info->ordered_root_lock);

		btrfs_invalidate_inodes(btrfs_inode->root);

		spin_lock(&root->fs_info->ordered_extent_lock);
		spin_lock(&root->fs_info->ordered_root_lock);
	}

	spin_unlock(&root->fs_info->ordered_extent_lock);
	spin_unlock(&root->fs_info->ordered_root_lock);
	mutex_unlock(&root->fs_info->ordered_operations_mutex);
}

@@ -3706,15 +3710,36 @@ static void btrfs_destroy_ordered_extents(struct btrfs_root *root)
{
	struct btrfs_ordered_extent *ordered;

	spin_lock(&root->fs_info->ordered_extent_lock);
	spin_lock(&root->ordered_extent_lock);
	/*
	 * This will just short circuit the ordered completion stuff which will
	 * make sure the ordered extent gets properly cleaned up.
	 */
	list_for_each_entry(ordered, &root->fs_info->ordered_extents,
	list_for_each_entry(ordered, &root->ordered_extents,
			    root_extent_list)
		set_bit(BTRFS_ORDERED_IOERR, &ordered->flags);
	spin_unlock(&root->fs_info->ordered_extent_lock);
	spin_unlock(&root->ordered_extent_lock);
}

static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info)
{
	struct btrfs_root *root;
	struct list_head splice;

	INIT_LIST_HEAD(&splice);

	spin_lock(&fs_info->ordered_root_lock);
	list_splice_init(&fs_info->ordered_roots, &splice);
	while (!list_empty(&splice)) {
		root = list_first_entry(&splice, struct btrfs_root,
					ordered_root);
		list_del_init(&root->ordered_root);

		btrfs_destroy_ordered_extents(root);

		cond_resched_lock(&fs_info->ordered_root_lock);
	}
	spin_unlock(&fs_info->ordered_root_lock);
}

int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
@@ -3977,7 +4002,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)

		btrfs_destroy_ordered_operations(t, root);

		btrfs_destroy_ordered_extents(root);
		btrfs_destroy_all_ordered_extents(root->fs_info);

		btrfs_destroy_delayed_refs(t, root);

+3 −3
Original line number Diff line number Diff line
@@ -3901,7 +3901,7 @@ static void btrfs_writeback_inodes_sb_nr(struct btrfs_root *root,
		 */
		btrfs_start_all_delalloc_inodes(root->fs_info, 0);
		if (!current->journal_info)
			btrfs_wait_ordered_extents(root, 0);
			btrfs_wait_all_ordered_extents(root->fs_info, 0);
	}
}

@@ -3931,7 +3931,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,
	if (delalloc_bytes == 0) {
		if (trans)
			return;
		btrfs_wait_ordered_extents(root, 0);
		btrfs_wait_all_ordered_extents(root->fs_info, 0);
		return;
	}

@@ -3959,7 +3959,7 @@ static void shrink_delalloc(struct btrfs_root *root, u64 to_reclaim, u64 orig,

		loops++;
		if (wait_ordered && !trans) {
			btrfs_wait_ordered_extents(root, 0);
			btrfs_wait_all_ordered_extents(root->fs_info, 0);
		} else {
			time_left = schedule_timeout_killable(1);
			if (time_left)
+2 −2
Original line number Diff line number Diff line
@@ -7991,9 +7991,9 @@ void btrfs_destroy_inode(struct inode *inode)
	 */
	smp_mb();
	if (!list_empty(&BTRFS_I(inode)->ordered_operations)) {
		spin_lock(&root->fs_info->ordered_extent_lock);
		spin_lock(&root->fs_info->ordered_root_lock);
		list_del_init(&BTRFS_I(inode)->ordered_operations);
		spin_unlock(&root->fs_info->ordered_extent_lock);
		spin_unlock(&root->fs_info->ordered_root_lock);
	}

	if (test_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
Loading