/*
 * Copyright (C) 2008 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 "ref-cache.h"
#include "transaction.h"

/*
 * leaf refs are used to cache the information about which extents
 * a given leaf has references on.  This allows us to process that leaf
 * in btrfs_drop_snapshot without needing to read it back from disk.
 */

/*
 * kmalloc a leaf reference struct and update the counters for the
 * total ref cache size
 */
struct btrfs_leaf_ref *btrfs_alloc_leaf_ref(struct btrfs_root *root,
					    int nr_extents)
{
	struct btrfs_leaf_ref *ref;
	size_t size = btrfs_leaf_ref_size(nr_extents);

	ref = kmalloc(size, GFP_NOFS);
	if (ref) {
		spin_lock(&root->fs_info->ref_cache_lock);
		root->fs_info->total_ref_cache_size += size;
		spin_unlock(&root->fs_info->ref_cache_lock);

		memset(ref, 0, sizeof(*ref));
		atomic_set(&ref->usage, 1);
		INIT_LIST_HEAD(&ref->list);
	}
	return ref;
}

/*
 * free a leaf reference struct and update the counters for the
 * total ref cache size
 */
void btrfs_free_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
{
	if (!ref)
		return;
	WARN_ON(atomic_read(&ref->usage) == 0);
	if (atomic_dec_and_test(&ref->usage)) {
		size_t size = btrfs_leaf_ref_size(ref->nritems);

		BUG_ON(ref->in_tree);
		kfree(ref);

		spin_lock(&root->fs_info->ref_cache_lock);
		root->fs_info->total_ref_cache_size -= size;
		spin_unlock(&root->fs_info->ref_cache_lock);
	}
}

static struct rb_node *tree_insert(struct rb_root *root, u64 bytenr,
				   struct rb_node *node)
{
	struct rb_node ** p = &root->rb_node;
	struct rb_node * parent = NULL;
	struct btrfs_leaf_ref *entry;

	while(*p) {
		parent = *p;
		entry = rb_entry(parent, struct btrfs_leaf_ref, rb_node);

		if (bytenr < entry->bytenr)
			p = &(*p)->rb_left;
		else if (bytenr > entry->bytenr)
			p = &(*p)->rb_right;
		else
			return parent;
	}

	entry = rb_entry(node, struct btrfs_leaf_ref, rb_node);
	rb_link_node(node, parent, p);
	rb_insert_color(node, root);
	return NULL;
}

static struct rb_node *tree_search(struct rb_root *root, u64 bytenr)
{
	struct rb_node * n = root->rb_node;
	struct btrfs_leaf_ref *entry;

	while(n) {
		entry = rb_entry(n, struct btrfs_leaf_ref, rb_node);
		WARN_ON(!entry->in_tree);

		if (bytenr < entry->bytenr)
			n = n->rb_left;
		else if (bytenr > entry->bytenr)
			n = n->rb_right;
		else
			return n;
	}
	return NULL;
}

int btrfs_remove_leaf_refs(struct btrfs_root *root, u64 max_root_gen,
			   int shared)
{
	struct btrfs_leaf_ref *ref = NULL;
	struct btrfs_leaf_ref_tree *tree = root->ref_tree;

	if (shared)
		tree = &root->fs_info->shared_ref_tree;
	if (!tree)
		return 0;

	spin_lock(&tree->lock);
	while(!list_empty(&tree->list)) {
		ref = list_entry(tree->list.next, struct btrfs_leaf_ref, list);
		BUG_ON(ref->tree != tree);
		if (ref->root_gen > max_root_gen)
			break;
		if (!xchg(&ref->in_tree, 0)) {
			cond_resched_lock(&tree->lock);
			continue;
		}

		rb_erase(&ref->rb_node, &tree->root);
		list_del_init(&ref->list);

		spin_unlock(&tree->lock);
		btrfs_free_leaf_ref(root, ref);
		cond_resched();
		spin_lock(&tree->lock);
	}
	spin_unlock(&tree->lock);
	return 0;
}

/*
 * find the leaf ref for a given extent.  This returns the ref struct with
 * a usage reference incremented
 */
struct btrfs_leaf_ref *btrfs_lookup_leaf_ref(struct btrfs_root *root,
					     u64 bytenr)
{
	struct rb_node *rb;
	struct btrfs_leaf_ref *ref = NULL;
	struct btrfs_leaf_ref_tree *tree = root->ref_tree;
again:
	if (tree) {
		spin_lock(&tree->lock);
		rb = tree_search(&tree->root, bytenr);
		if (rb)
			ref = rb_entry(rb, struct btrfs_leaf_ref, rb_node);
		if (ref)
			atomic_inc(&ref->usage);
		spin_unlock(&tree->lock);
		if (ref)
			return ref;
	}
	if (tree != &root->fs_info->shared_ref_tree) {
		tree = &root->fs_info->shared_ref_tree;
		goto again;
	}
	return NULL;
}

/*
 * add a fully filled in leaf ref struct
 * remove all the refs older than a given root generation
 */
int btrfs_add_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref,
		       int shared)
{
	int ret = 0;
	struct rb_node *rb;
	struct btrfs_leaf_ref_tree *tree = root->ref_tree;

	if (shared)
		tree = &root->fs_info->shared_ref_tree;

	spin_lock(&tree->lock);
	rb = tree_insert(&tree->root, ref->bytenr, &ref->rb_node);
	if (rb) {
		ret = -EEXIST;
	} else {
		atomic_inc(&ref->usage);
		ref->tree = tree;
		ref->in_tree = 1;
		list_add_tail(&ref->list, &tree->list);
	}
	spin_unlock(&tree->lock);
	return ret;
}

/*
 * remove a single leaf ref from the tree.  This drops the ref held by the tree
 * only
 */
int btrfs_remove_leaf_ref(struct btrfs_root *root, struct btrfs_leaf_ref *ref)
{
	struct btrfs_leaf_ref_tree *tree;

	if (!xchg(&ref->in_tree, 0))
		return 0;

	tree = ref->tree;
	spin_lock(&tree->lock);

	rb_erase(&ref->rb_node, &tree->root);
	list_del_init(&ref->list);

	spin_unlock(&tree->lock);

	btrfs_free_leaf_ref(root, ref);
	return 0;
}
