/*
 * 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;
}
