/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include "yaffs_verify.h"
#include "yaffs_trace.h"
#include "yaffs_bitmap.h"
#include "yaffs_getblockinfo.h"
#include "yaffs_nand.h"

int yaffs_skip_verification(struct yaffs_dev *dev)
{
	return !(yaffs_trace_mask &
		 (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
}

static int yaffs_skip_full_verification(struct yaffs_dev *dev)
{
	return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_FULL));
}

static int yaffs_skip_nand_verification(struct yaffs_dev *dev)
{
	return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_NAND));
}

static const char * const block_state_name[] = {
	"Unknown",
	"Needs scan",
	"Scanning",
	"Empty",
	"Allocating",
	"Full",
	"Dirty",
	"Checkpoint",
	"Collecting",
	"Dead"
};

void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi, int n)
{
	int actually_used;
	int in_use;

	if (yaffs_skip_verification(dev))
		return;

	/* Report illegal runtime states */
	if (bi->block_state >= YAFFS_NUMBER_OF_BLOCK_STATES)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Block %d has undefined state %d",
			n, bi->block_state);

	switch (bi->block_state) {
	case YAFFS_BLOCK_STATE_UNKNOWN:
	case YAFFS_BLOCK_STATE_SCANNING:
	case YAFFS_BLOCK_STATE_NEEDS_SCAN:
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Block %d has bad run-state %s",
			n, block_state_name[bi->block_state]);
	}

	/* Check pages in use and soft deletions are legal */

	actually_used = bi->pages_in_use - bi->soft_del_pages;

	if (bi->pages_in_use < 0 ||
	    bi->pages_in_use > dev->param.chunks_per_block ||
	    bi->soft_del_pages < 0 ||
	    bi->soft_del_pages > dev->param.chunks_per_block ||
	    actually_used < 0 || actually_used > dev->param.chunks_per_block)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Block %d has illegal values pages_in_used %d soft_del_pages %d",
			n, bi->pages_in_use, bi->soft_del_pages);

	/* Check chunk bitmap legal */
	in_use = yaffs_count_chunk_bits(dev, n);
	if (in_use != bi->pages_in_use)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Block %d has inconsistent values pages_in_use %d counted chunk bits %d",
			n, bi->pages_in_use, in_use);
}

void yaffs_verify_collected_blk(struct yaffs_dev *dev,
				struct yaffs_block_info *bi, int n)
{
	yaffs_verify_blk(dev, bi, n);

	/* After collection the block should be in the erased state */

	if (bi->block_state != YAFFS_BLOCK_STATE_COLLECTING &&
	    bi->block_state != YAFFS_BLOCK_STATE_EMPTY) {
		yaffs_trace(YAFFS_TRACE_ERROR,
			"Block %d is in state %d after gc, should be erased",
			n, bi->block_state);
	}
}

void yaffs_verify_blocks(struct yaffs_dev *dev)
{
	int i;
	int state_count[YAFFS_NUMBER_OF_BLOCK_STATES];
	int illegal_states = 0;

	if (yaffs_skip_verification(dev))
		return;

	memset(state_count, 0, sizeof(state_count));

	for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
		struct yaffs_block_info *bi = yaffs_get_block_info(dev, i);
		yaffs_verify_blk(dev, bi, i);

		if (bi->block_state < YAFFS_NUMBER_OF_BLOCK_STATES)
			state_count[bi->block_state]++;
		else
			illegal_states++;
	}

	yaffs_trace(YAFFS_TRACE_VERIFY,	"Block summary");

	yaffs_trace(YAFFS_TRACE_VERIFY,
		"%d blocks have illegal states",
		illegal_states);
	if (state_count[YAFFS_BLOCK_STATE_ALLOCATING] > 1)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Too many allocating blocks");

	for (i = 0; i < YAFFS_NUMBER_OF_BLOCK_STATES; i++)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"%s %d blocks",
			block_state_name[i], state_count[i]);

	if (dev->blocks_in_checkpt != state_count[YAFFS_BLOCK_STATE_CHECKPOINT])
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Checkpoint block count wrong dev %d count %d",
			dev->blocks_in_checkpt,
			state_count[YAFFS_BLOCK_STATE_CHECKPOINT]);

	if (dev->n_erased_blocks != state_count[YAFFS_BLOCK_STATE_EMPTY])
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Erased block count wrong dev %d count %d",
			dev->n_erased_blocks,
			state_count[YAFFS_BLOCK_STATE_EMPTY]);

	if (state_count[YAFFS_BLOCK_STATE_COLLECTING] > 1)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Too many collecting blocks %d (max is 1)",
			state_count[YAFFS_BLOCK_STATE_COLLECTING]);
}

/*
 * Verify the object header. oh must be valid, but obj and tags may be NULL in
 * which case those tests will not be performed.
 */
void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
		     struct yaffs_ext_tags *tags, int parent_check)
{
	if (obj && yaffs_skip_verification(obj->my_dev))
		return;

	if (!(tags && obj && oh)) {
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Verifying object header tags %p obj %p oh %p",
			tags, obj, oh);
		return;
	}

	if (oh->type <= YAFFS_OBJECT_TYPE_UNKNOWN ||
	    oh->type > YAFFS_OBJECT_TYPE_MAX)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d header type is illegal value 0x%x",
			tags->obj_id, oh->type);

	if (tags->obj_id != obj->obj_id)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d header mismatch obj_id %d",
			tags->obj_id, obj->obj_id);

	/*
	 * Check that the object's parent ids match if parent_check requested.
	 *
	 * Tests do not apply to the root object.
	 */

	if (parent_check && tags->obj_id > 1 && !obj->parent)
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d header mismatch parent_id %d obj->parent is NULL",
			tags->obj_id, oh->parent_obj_id);

	if (parent_check && obj->parent &&
	    oh->parent_obj_id != obj->parent->obj_id &&
	    (oh->parent_obj_id != YAFFS_OBJECTID_UNLINKED ||
	     obj->parent->obj_id != YAFFS_OBJECTID_DELETED))
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d header mismatch parent_id %d parent_obj_id %d",
			tags->obj_id, oh->parent_obj_id,
			obj->parent->obj_id);

	if (tags->obj_id > 1 && oh->name[0] == 0)	/* Null name */
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d header name is NULL",
			obj->obj_id);

	if (tags->obj_id > 1 && ((u8) (oh->name[0])) == 0xff)	/* Junk name */
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d header name is 0xff",
			obj->obj_id);
}

void yaffs_verify_file(struct yaffs_obj *obj)
{
	u32 x;
	int required_depth;
	int last_chunk;
	u32 offset_in_chunk;
	u32 the_chunk;

	u32 i;
	struct yaffs_dev *dev;
	struct yaffs_ext_tags tags;
	struct yaffs_tnode *tn;
	u32 obj_id;

	if (!obj)
		return;

	if (yaffs_skip_verification(obj->my_dev))
		return;

	dev = obj->my_dev;
	obj_id = obj->obj_id;

	/* Check file size is consistent with tnode depth */
	yaffs_addr_to_chunk(dev, obj->variant.file_variant.file_size,
				&last_chunk, &offset_in_chunk);
	last_chunk++;
	x = last_chunk >> YAFFS_TNODES_LEVEL0_BITS;
	required_depth = 0;
	while (x > 0) {
		x >>= YAFFS_TNODES_INTERNAL_BITS;
		required_depth++;
	}

	/* Check that the chunks in the tnode tree are all correct.
	 * We do this by scanning through the tnode tree and
	 * checking the tags for every chunk match.
	 */

	if (yaffs_skip_nand_verification(dev))
		return;

	for (i = 1; i <= last_chunk; i++) {
		tn = yaffs_find_tnode_0(dev, &obj->variant.file_variant, i);

		if (!tn)
			continue;

		the_chunk = yaffs_get_group_base(dev, tn, i);
		if (the_chunk > 0) {
			yaffs_rd_chunk_tags_nand(dev, the_chunk, NULL,
						 &tags);
			if (tags.obj_id != obj_id || tags.chunk_id != i)
				yaffs_trace(YAFFS_TRACE_VERIFY,
					"Object %d chunk_id %d NAND mismatch chunk %d tags (%d:%d)",
					obj_id, i, the_chunk,
					tags.obj_id, tags.chunk_id);
		}
	}
}

void yaffs_verify_link(struct yaffs_obj *obj)
{
	if (obj && yaffs_skip_verification(obj->my_dev))
		return;

	/* Verify sane equivalent object */
}

void yaffs_verify_symlink(struct yaffs_obj *obj)
{
	if (obj && yaffs_skip_verification(obj->my_dev))
		return;

	/* Verify symlink string */
}

void yaffs_verify_special(struct yaffs_obj *obj)
{
	if (obj && yaffs_skip_verification(obj->my_dev))
		return;
}

void yaffs_verify_obj(struct yaffs_obj *obj)
{
	struct yaffs_dev *dev;
	u32 chunk_min;
	u32 chunk_max;
	u32 chunk_id_ok;
	u32 chunk_in_range;
	u32 chunk_wrongly_deleted;
	u32 chunk_valid;

	if (!obj)
		return;

	if (obj->being_created)
		return;

	dev = obj->my_dev;

	if (yaffs_skip_verification(dev))
		return;

	/* Check sane object header chunk */

	chunk_min = dev->internal_start_block * dev->param.chunks_per_block;
	chunk_max =
	    (dev->internal_end_block + 1) * dev->param.chunks_per_block - 1;

	chunk_in_range = (((unsigned)(obj->hdr_chunk)) >= chunk_min &&
			  ((unsigned)(obj->hdr_chunk)) <= chunk_max);
	chunk_id_ok = chunk_in_range || (obj->hdr_chunk == 0);
	chunk_valid = chunk_in_range &&
	    yaffs_check_chunk_bit(dev,
				  obj->hdr_chunk / dev->param.chunks_per_block,
				  obj->hdr_chunk % dev->param.chunks_per_block);
	chunk_wrongly_deleted = chunk_in_range && !chunk_valid;

	if (!obj->fake && (!chunk_id_ok || chunk_wrongly_deleted))
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d has chunk_id %d %s %s",
			obj->obj_id, obj->hdr_chunk,
			chunk_id_ok ? "" : ",out of range",
			chunk_wrongly_deleted ? ",marked as deleted" : "");

	if (chunk_valid && !yaffs_skip_nand_verification(dev)) {
		struct yaffs_ext_tags tags;
		struct yaffs_obj_hdr *oh;
		u8 *buffer = yaffs_get_temp_buffer(dev);

		oh = (struct yaffs_obj_hdr *)buffer;

		yaffs_rd_chunk_tags_nand(dev, obj->hdr_chunk, buffer, &tags);

		yaffs_verify_oh(obj, oh, &tags, 1);

		yaffs_release_temp_buffer(dev, buffer);
	}

	/* Verify it has a parent */
	if (obj && !obj->fake && (!obj->parent || obj->parent->my_dev != dev)) {
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d has parent pointer %p which does not look like an object",
			obj->obj_id, obj->parent);
	}

	/* Verify parent is a directory */
	if (obj->parent &&
	    obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d's parent is not a directory (type %d)",
			obj->obj_id, obj->parent->variant_type);
	}

	switch (obj->variant_type) {
	case YAFFS_OBJECT_TYPE_FILE:
		yaffs_verify_file(obj);
		break;
	case YAFFS_OBJECT_TYPE_SYMLINK:
		yaffs_verify_symlink(obj);
		break;
	case YAFFS_OBJECT_TYPE_DIRECTORY:
		yaffs_verify_dir(obj);
		break;
	case YAFFS_OBJECT_TYPE_HARDLINK:
		yaffs_verify_link(obj);
		break;
	case YAFFS_OBJECT_TYPE_SPECIAL:
		yaffs_verify_special(obj);
		break;
	case YAFFS_OBJECT_TYPE_UNKNOWN:
	default:
		yaffs_trace(YAFFS_TRACE_VERIFY,
			"Obj %d has illegaltype %d",
		   obj->obj_id, obj->variant_type);
		break;
	}
}

void yaffs_verify_objects(struct yaffs_dev *dev)
{
	struct yaffs_obj *obj;
	int i;
	struct list_head *lh;

	if (yaffs_skip_verification(dev))
		return;

	/* Iterate through the objects in each hash entry */

	for (i = 0; i < YAFFS_NOBJECT_BUCKETS; i++) {
		list_for_each(lh, &dev->obj_bucket[i].list) {
			obj = list_entry(lh, struct yaffs_obj, hash_link);
			yaffs_verify_obj(obj);
		}
	}
}

void yaffs_verify_obj_in_dir(struct yaffs_obj *obj)
{
	struct list_head *lh;
	struct yaffs_obj *list_obj;
	int count = 0;

	if (!obj) {
		yaffs_trace(YAFFS_TRACE_ALWAYS, "No object to verify");
		BUG();
		return;
	}

	if (yaffs_skip_verification(obj->my_dev))
		return;

	if (!obj->parent) {
		yaffs_trace(YAFFS_TRACE_ALWAYS, "Object does not have parent");
		BUG();
		return;
	}

	if (obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
		yaffs_trace(YAFFS_TRACE_ALWAYS, "Parent is not directory");
		BUG();
	}

	/* Iterate through the objects in each hash entry */

	list_for_each(lh, &obj->parent->variant.dir_variant.children) {
		list_obj = list_entry(lh, struct yaffs_obj, siblings);
		yaffs_verify_obj(list_obj);
		if (obj == list_obj)
			count++;
	}

	if (count != 1) {
		yaffs_trace(YAFFS_TRACE_ALWAYS,
			"Object in directory %d times",
			count);
		BUG();
	}
}

void yaffs_verify_dir(struct yaffs_obj *directory)
{
	struct list_head *lh;
	struct yaffs_obj *list_obj;

	if (!directory) {
		BUG();
		return;
	}

	if (yaffs_skip_full_verification(directory->my_dev))
		return;

	if (directory->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
		yaffs_trace(YAFFS_TRACE_ALWAYS,
			"Directory has wrong type: %d",
			directory->variant_type);
		BUG();
	}

	/* Iterate through the objects in each hash entry */

	list_for_each(lh, &directory->variant.dir_variant.children) {
		list_obj = list_entry(lh, struct yaffs_obj, siblings);
		if (list_obj->parent != directory) {
			yaffs_trace(YAFFS_TRACE_ALWAYS,
				"Object in directory list has wrong parent %p",
				list_obj->parent);
			BUG();
		}
		yaffs_verify_obj_in_dir(list_obj);
	}
}

static int yaffs_free_verification_failures;

void yaffs_verify_free_chunks(struct yaffs_dev *dev)
{
	int counted;
	int difference;

	if (yaffs_skip_verification(dev))
		return;

	counted = yaffs_count_free_chunks(dev);

	difference = dev->n_free_chunks - counted;

	if (difference) {
		yaffs_trace(YAFFS_TRACE_ALWAYS,
			"Freechunks verification failure %d %d %d",
			dev->n_free_chunks, counted, difference);
		yaffs_free_verification_failures++;
	}
}

int yaffs_verify_file_sane(struct yaffs_obj *in)
{
	return YAFFS_OK;
}
