Commit e9d0b13b authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse
Browse files

Btrfs: Btree defrag on the extent-mapping tree as well

parent 409eb95d
Loading
Loading
Loading
Loading
+11 −7
Original line number Diff line number Diff line
@@ -99,7 +99,6 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root
		if (ret)
			return ret;
	} else {
		WARN_ON(!root->ref_cows);
		clean_tree_block(trans, root, buf);
	}

@@ -162,13 +161,14 @@ static int close_blocks(u64 blocknr, u64 other)

int btrfs_realloc_node(struct btrfs_trans_handle *trans,
		       struct btrfs_root *root, struct buffer_head *parent,
		       int cache_only)
		       int cache_only, u64 *last_ret)
{
	struct btrfs_node *parent_node;
	struct buffer_head *cur_bh;
	struct buffer_head *tmp_bh;
	u64 blocknr;
	u64 search_start = 0;
	u64 search_start = *last_ret;
	u64 last_block = 0;
	u64 other;
	u32 parent_nritems;
	int start_slot;
@@ -198,6 +198,8 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
	for (i = start_slot; i < end_slot; i++) {
		int close = 1;
		blocknr = btrfs_node_blockptr(parent_node, i);
		if (last_block == 0)
			last_block = blocknr;
		if (i > 0) {
			other = btrfs_node_blockptr(parent_node, i - 1);
			close = close_blocks(blocknr, other);
@@ -206,8 +208,10 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
			other = btrfs_node_blockptr(parent_node, i + 1);
			close = close_blocks(blocknr, other);
		}
		if (close)
		if (close) {
			last_block = blocknr;
			continue;
		}

		cur_bh = btrfs_find_tree_block(root, blocknr);
		if (!cur_bh || !buffer_uptodate(cur_bh) ||
@@ -219,9 +223,9 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
			brelse(cur_bh);
			cur_bh = read_tree_block(root, blocknr);
		}
		if (search_start == 0) {
			search_start = bh_blocknr(cur_bh) & ~((u64)65535);
		}
		if (search_start == 0)
			search_start = last_block & ~((u64)65535);

		err = __btrfs_cow_block(trans, root, cur_bh, parent, i,
					&tmp_bh, search_start,
					min(8, end_slot - i));
+3 −1
Original line number Diff line number Diff line
@@ -1019,6 +1019,8 @@ static inline void btrfs_memmove(struct btrfs_root *root,
	btrfs_item_offset((leaf)->items + (slot))))

/* extent-tree.c */
int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
			 struct btrfs_root *root);
int btrfs_copy_pinned(struct btrfs_root *root, struct radix_tree_root *copy);
struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
							 btrfs_fs_info *info,
@@ -1066,7 +1068,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root
		      ins_len, int cow);
int btrfs_realloc_node(struct btrfs_trans_handle *trans,
		       struct btrfs_root *root, struct buffer_head *parent,
		       int cache_only);
		       int cache_only, u64 *last_ret);
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
struct btrfs_path *btrfs_alloc_path(void);
void btrfs_free_path(struct btrfs_path *p);
+27 −1
Original line number Diff line number Diff line
@@ -396,6 +396,14 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
	return 0;
}

int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
			 struct btrfs_root *root)
{
	finish_current_insert(trans, root->fs_info->extent_root);
	del_pending_extents(trans, root->fs_info->extent_root);
	return 0;
}

static int lookup_extent_ref(struct btrfs_trans_handle *trans,
			     struct btrfs_root *root, u64 blocknr,
			     u64 num_blocks, u32 *refs)
@@ -1374,7 +1382,25 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root
			BUG_ON(ret);
			continue;
		}
		next = btrfs_find_tree_block(root, blocknr);
		if (!next || !buffer_uptodate(next)) {
			brelse(next);
			mutex_unlock(&root->fs_info->fs_mutex);
			next = read_tree_block(root, blocknr);
			mutex_lock(&root->fs_info->fs_mutex);

			/* we dropped the lock, check one more time */
			ret = lookup_extent_ref(trans, root, blocknr, 1, &refs);
			BUG_ON(ret);
			if (refs != 1) {
				path->slots[*level]++;
				brelse(next);
				ret = btrfs_free_extent(trans, root,
							blocknr, 1, 1);
				BUG_ON(ret);
				continue;
			}
		}
		WARN_ON(*level <= 0);
		if (path->nodes[*level-1])
			btrfs_block_release(root, path->nodes[*level-1]);
+2 −21
Original line number Diff line number Diff line
@@ -2159,9 +2159,7 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int
{
	struct btrfs_root *root = BTRFS_I(inode)->root;
	struct btrfs_ioctl_vol_args vol_args;
	struct btrfs_trans_handle *trans;
	int ret = 0;
	int err;
	struct btrfs_dir_item *di;
	int namelen;
	struct btrfs_path *path;
@@ -2201,25 +2199,8 @@ int btrfs_ioctl(struct inode *inode, struct file *filp, unsigned int

	case BTRFS_IOC_DEFRAG:
		mutex_lock(&root->fs_info->fs_mutex);
		trans = btrfs_start_transaction(root, 1);
		memset(&root->defrag_progress, 0,
		       sizeof(root->defrag_progress));
		while (1) {
			root->defrag_running = 1;
			err = btrfs_defrag_leaves(trans, root, 0);

			btrfs_end_transaction(trans, root);
			mutex_unlock(&root->fs_info->fs_mutex);

			btrfs_btree_balance_dirty(root);

			mutex_lock(&root->fs_info->fs_mutex);
			trans = btrfs_start_transaction(root, 1);
			if (err != -EAGAIN)
				break;
		}
		root->defrag_running = 0;
		btrfs_end_transaction(trans, root);
		btrfs_defrag_root(root, 0);
		btrfs_defrag_root(root->fs_info->extent_root, 0);
		mutex_unlock(&root->fs_info->fs_mutex);
		ret = 0;
		break;
+2 −0
Original line number Diff line number Diff line
@@ -121,7 +121,9 @@ static int btrfs_sync_fs(struct super_block *sb, int wait)
		filemap_flush(root->fs_info->btree_inode->i_mapping);
		return 0;
	}
	btrfs_clean_old_snapshots(root);
	mutex_lock(&root->fs_info->fs_mutex);
	btrfs_defrag_dirty_roots(root->fs_info);
	trans = btrfs_start_transaction(root, 1);
	ret = btrfs_commit_transaction(trans, root);
	sb->s_dirt = 0;
Loading