/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public
 * License v2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 021110-1307, USA.
 */

#include <linux/sched.h>
#include "ctree.h"
#include "disk-io.h"
#include "print-tree.h"
#include "transaction.h"

static void reada_defrag(struct btrfs_root *root,
			 struct extent_buffer *node)
{
	int i;
	u32 nritems;
	u64 bytenr;
	u32 blocksize;
	int ret;

	blocksize = btrfs_level_size(root, btrfs_header_level(node) - 1);
	nritems = btrfs_header_nritems(node);
	for (i = 0; i < nritems; i++) {
		bytenr = btrfs_node_blockptr(node, i);
		ret = readahead_tree_block(root, bytenr, blocksize);
		if (ret)
			break;
	}
}

static int defrag_walk_down(struct btrfs_trans_handle *trans,
			    struct btrfs_root *root,
			    struct btrfs_path *path, int *level,
			    int cache_only, u64 *last_ret)
{
	struct extent_buffer *next;
	struct extent_buffer *cur;
	u64 bytenr;
	int ret = 0;
	int is_extent = 0;

	WARN_ON(*level < 0);
	WARN_ON(*level >= BTRFS_MAX_LEVEL);

	if (root->fs_info->extent_root == root)
		is_extent = 1;

	if (*level == 1 && cache_only && path->nodes[1] &&
	    !btrfs_buffer_defrag(path->nodes[1])) {
		goto out;
	}
	while(*level > 0) {
		WARN_ON(*level < 0);
		WARN_ON(*level >= BTRFS_MAX_LEVEL);
		cur = path->nodes[*level];

		if (!cache_only && *level > 1 && path->slots[*level] == 0)
			reada_defrag(root, cur);

		if (btrfs_header_level(cur) != *level)
			WARN_ON(1);

		if (path->slots[*level] >=
		    btrfs_header_nritems(cur))
			break;

		if (*level == 1) {
			WARN_ON(btrfs_header_generation(path->nodes[*level]) !=
							trans->transid);
			ret = btrfs_realloc_node(trans, root,
						 path->nodes[*level],
						 path->slots[*level],
						 cache_only, last_ret,
						 &root->defrag_progress);
			if (is_extent)
				btrfs_extent_post_op(trans, root);

			break;
		}
		bytenr = btrfs_node_blockptr(cur, path->slots[*level]);

		if (cache_only) {
			next = btrfs_find_tree_block(root, bytenr,
					   btrfs_level_size(root, *level - 1));
			if (!next || !btrfs_buffer_uptodate(next) ||
			    !btrfs_buffer_defrag(next)) {
				free_extent_buffer(next);
				path->slots[*level]++;
				continue;
			}
		} else {
			next = read_tree_block(root, bytenr,
				       btrfs_level_size(root, *level - 1));
		}
		ret = btrfs_cow_block(trans, root, next, path->nodes[*level],
				      path->slots[*level], &next);
		BUG_ON(ret);
		if (is_extent)
			btrfs_extent_post_op(trans, root);

		WARN_ON(*level <= 0);
		if (path->nodes[*level-1])
			free_extent_buffer(path->nodes[*level-1]);
		path->nodes[*level-1] = next;
		*level = btrfs_header_level(next);
		path->slots[*level] = 0;
	}
	WARN_ON(*level < 0);
	WARN_ON(*level >= BTRFS_MAX_LEVEL);

	btrfs_clear_buffer_defrag(path->nodes[*level]);
out:
	free_extent_buffer(path->nodes[*level]);
	path->nodes[*level] = NULL;
	*level += 1;
	WARN_ON(ret && ret != -EAGAIN);
	return ret;
}

static int defrag_walk_up(struct btrfs_trans_handle *trans,
			  struct btrfs_root *root,
			  struct btrfs_path *path, int *level,
			  int cache_only)
{
	int i;
	int slot;
	struct extent_buffer *node;

	for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) {
		slot = path->slots[i];
		if (slot < btrfs_header_nritems(path->nodes[i]) - 1) {
			path->slots[i]++;
			*level = i;
			node = path->nodes[i];
			WARN_ON(i == 0);
			btrfs_node_key_to_cpu(node, &root->defrag_progress,
					      path->slots[i]);
			root->defrag_level = i;
			return 0;
		} else {
			btrfs_clear_buffer_defrag(path->nodes[*level]);
			free_extent_buffer(path->nodes[*level]);
			path->nodes[*level] = NULL;
			*level = i + 1;
		}
	}
	return 1;
}

int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
			struct btrfs_root *root, int cache_only)
{
	struct btrfs_path *path = NULL;
	struct extent_buffer *tmp;
	int ret = 0;
	int wret;
	int level;
	int orig_level;
	int i;
	int is_extent = 0;
	u64 last_ret = 0;

	if (root->fs_info->extent_root == root)
		is_extent = 1;

	if (root->ref_cows == 0 && !is_extent)
		goto out;

	path = btrfs_alloc_path();
	if (!path)
		return -ENOMEM;

	level = btrfs_header_level(root->node);
	orig_level = level;

	if (level == 0) {
		goto out;
	}
	if (root->defrag_progress.objectid == 0) {
		extent_buffer_get(root->node);
		ret = btrfs_cow_block(trans, root, root->node, NULL, 0, &tmp);
		BUG_ON(ret);
		path->nodes[level] = root->node;
		path->slots[level] = 0;
		if (is_extent)
			btrfs_extent_post_op(trans, root);
	} else {
		level = root->defrag_level;
		path->lowest_level = level;
		wret = btrfs_search_slot(trans, root, &root->defrag_progress,
					 path, 0, 1);

		if (is_extent)
			btrfs_extent_post_op(trans, root);

		if (wret < 0) {
			ret = wret;
			goto out;
		}

		while(level > 0 && !path->nodes[level])
			level--;

		if (!path->nodes[level]) {
			ret = 0;
			goto out;
		}
	}

	while(1) {
		wret = defrag_walk_down(trans, root, path, &level, cache_only,
					&last_ret);
		if (wret > 0)
			break;
		if (wret < 0)
			ret = wret;

		wret = defrag_walk_up(trans, root, path, &level, cache_only);
		if (wret > 0)
			break;
		if (wret < 0)
			ret = wret;
		else
			ret = -EAGAIN;
		break;
	}
	for (i = 0; i <= orig_level; i++) {
		if (path->nodes[i]) {
			free_extent_buffer(path->nodes[i]);
			path->nodes[i] = NULL;
		}
	}
out:
	if (path)
		btrfs_free_path(path);
	if (ret != -EAGAIN) {
		memset(&root->defrag_progress, 0,
		       sizeof(root->defrag_progress));
	}
	return ret;
}
