lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4D378212.4080409@bluewatersys.com>
Date:	Thu, 20 Jan 2011 13:30:10 +1300
From:	Ryan Mallon <ryan@...ewatersys.com>
To:	Charles Manning <cdhmanning@...il.com>
CC:	linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org,
	akpm@...ux-foundation.org
Subject: Re: [PATCH 06/10] Add yaffs2 file system: Tracing and verification
 code

On 01/14/2011 04:06 PM, Charles Manning wrote:
> Signed-off-by: Charles Manning <cdhmanning@...il.com>

Some comments below.

~Ryan

> ---
>  fs/yaffs2/yaffs_tagsvalidity.c |   26 ++
>  fs/yaffs2/yaffs_tagsvalidity.h |   23 ++
>  fs/yaffs2/yaffs_trace.h        |   57 +++++
>  fs/yaffs2/yaffs_verify.c       |  524 ++++++++++++++++++++++++++++++++++++++++
>  fs/yaffs2/yaffs_verify.h       |   43 ++++
>  5 files changed, 673 insertions(+), 0 deletions(-)
>  create mode 100644 fs/yaffs2/yaffs_tagsvalidity.c
>  create mode 100644 fs/yaffs2/yaffs_tagsvalidity.h
>  create mode 100644 fs/yaffs2/yaffs_trace.h
>  create mode 100644 fs/yaffs2/yaffs_verify.c
>  create mode 100644 fs/yaffs2/yaffs_verify.h
> 
> diff --git a/fs/yaffs2/yaffs_tagsvalidity.c b/fs/yaffs2/yaffs_tagsvalidity.c
> new file mode 100644
> index 0000000..582f36a
> --- /dev/null
> +++ b/fs/yaffs2/yaffs_tagsvalidity.c
> @@ -0,0 +1,26 @@
> +/*
> + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
> + *
> + * Copyright (C) 2002-2010 Aleph One Ltd.
> + *   for Toby Churchill Ltd and Brightstar Engineering
> + *
> + * Created by Charles Manning <charles@...ph1.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_tagsvalidity.h"
> +
> +void yaffs_init_tags(struct yaffs_ext_tags *tags)
> +{
> +	memset(tags, 0, sizeof(struct yaffs_ext_tags));
> +	tags->validity0 = 0xAAAAAAAA;
> +	tags->validity1 = 0x55555555;
> +}
> +
> +int yaffs_validate_tags(struct yaffs_ext_tags *tags)
> +{
> +	return (tags->validity0 == 0xAAAAAAAA && tags->validity1 == 0x55555555);
> +}

These are simple enough that they could be made static inline in the
yaffs_tagsvalidity.h header file and drop the c file altogether. You
could further reduce the file count by merging it all with
yaffs_tagscompat.[ch]

> diff --git a/fs/yaffs2/yaffs_tagsvalidity.h b/fs/yaffs2/yaffs_tagsvalidity.h
> new file mode 100644
> index 0000000..36a021f
> --- /dev/null
> +++ b/fs/yaffs2/yaffs_tagsvalidity.h
> @@ -0,0 +1,23 @@
> +/*
> + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
> + *
> + * Copyright (C) 2002-2010 Aleph One Ltd.
> + *   for Toby Churchill Ltd and Brightstar Engineering
> + *
> + * Created by Charles Manning <charles@...ph1.co.uk>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License version 2.1 as
> + * published by the Free Software Foundation.
> + *
> + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
> + */
> +
> +#ifndef __YAFFS_TAGS_VALIDITY_H__
> +#define __YAFFS_TAGS_VALIDITY_H__
> +
> +#include "yaffs_guts.h"
> +
> +void yaffs_init_tags(struct yaffs_ext_tags *tags);
> +int yaffs_validate_tags(struct yaffs_ext_tags *tags);
> +#endif
> diff --git a/fs/yaffs2/yaffs_trace.h b/fs/yaffs2/yaffs_trace.h
> new file mode 100644
> index 0000000..6273dbf
> --- /dev/null
> +++ b/fs/yaffs2/yaffs_trace.h
> @@ -0,0 +1,57 @@
> +/*
> + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
> + *
> + * Copyright (C) 2002-2010 Aleph One Ltd.
> + *   for Toby Churchill Ltd and Brightstar Engineering
> + *
> + * Created by Charles Manning <charles@...ph1.co.uk>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License version 2.1 as
> + * published by the Free Software Foundation.
> + *
> + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
> + */
> +
> +#ifndef __YTRACE_H__
> +#define __YTRACE_H__
> +
> +extern unsigned int yaffs_trace_mask;
> +extern unsigned int yaffs_wr_attempts;
> +
> +/*
> + * Tracing flags.
> + * The flags masked in YAFFS_TRACE_ALWAYS are always traced.
> + */
> +
> +#define YAFFS_TRACE_OS			0x00000002
> +#define YAFFS_TRACE_ALLOCATE		0x00000004
> +#define YAFFS_TRACE_SCAN		0x00000008
> +#define YAFFS_TRACE_BAD_BLOCKS		0x00000010
> +#define YAFFS_TRACE_ERASE		0x00000020
> +#define YAFFS_TRACE_GC			0x00000040
> +#define YAFFS_TRACE_WRITE		0x00000080
> +#define YAFFS_TRACE_TRACING		0x00000100
> +#define YAFFS_TRACE_DELETION		0x00000200
> +#define YAFFS_TRACE_BUFFERS		0x00000400
> +#define YAFFS_TRACE_NANDACCESS		0x00000800
> +#define YAFFS_TRACE_GC_DETAIL		0x00001000
> +#define YAFFS_TRACE_SCAN_DEBUG		0x00002000
> +#define YAFFS_TRACE_MTD			0x00004000
> +#define YAFFS_TRACE_CHECKPOINT		0x00008000
> +
> +#define YAFFS_TRACE_VERIFY		0x00010000
> +#define YAFFS_TRACE_VERIFY_NAND		0x00020000
> +#define YAFFS_TRACE_VERIFY_FULL		0x00040000
> +#define YAFFS_TRACE_VERIFY_ALL		0x000F0000
> +
> +#define YAFFS_TRACE_SYNC		0x00100000
> +#define YAFFS_TRACE_BACKGROUND		0x00200000
> +#define YAFFS_TRACE_LOCK		0x00400000
> +#define YAFFS_TRACE_MOUNT		0x00800000
> +
> +#define YAFFS_TRACE_ERROR		0x40000000
> +#define YAFFS_TRACE_BUG			0x80000000
> +#define YAFFS_TRACE_ALWAYS		0xF0000000
> +
> +#endif
> diff --git a/fs/yaffs2/yaffs_verify.c b/fs/yaffs2/yaffs_verify.c
> new file mode 100644
> index 0000000..1a5ed9a
> --- /dev/null
> +++ b/fs/yaffs2/yaffs_verify.c
> @@ -0,0 +1,524 @@
> +/*
> + * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
> + *
> + * Copyright (C) 2002-2010 Aleph One Ltd.
> + *   for Toby Churchill Ltd and Brightstar Engineering
> + *
> + * Created by Charles Manning <charles@...ph1.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)
> +{
> +	dev = dev;

Mark dev as __always_unused if this causes a build warning. Same in
other functions.

> +	return !(yaffs_trace_mask &
> +		 (YAFFS_TRACE_VERIFY | YAFFS_TRACE_VERIFY_FULL));
> +}
> +
> +static int yaffs_skip_full_verification(struct yaffs_dev *dev)
> +{
> +	dev = dev;
> +	return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_FULL));
> +}
> +
> +static int yaffs_skip_nand_verification(struct yaffs_dev *dev)
> +{
> +	dev = dev;
> +	return !(yaffs_trace_mask & (YAFFS_TRACE_VERIFY_NAND));
> +}
> +
> +static const char * const block_state_name[] = {
> +	"Unknown",
> +	"Needs scanning",
> +	"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_SCANNING:
> +		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)
> +{
> +	int required_depth;
> +	int actual_depth;
> +	u32 last_chunk;
> +	u32 x;
> +	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 */
> +	last_chunk =
> +	    obj->variant.file_variant.file_size / dev->data_bytes_per_chunk + 1;
> +	x = last_chunk >> YAFFS_TNODES_LEVEL0_BITS;
> +	required_depth = 0;
> +	while (x > 0) {
> +		x >>= YAFFS_TNODES_INTERNAL_BITS;
> +		required_depth++;
> +	}
> +
> +	actual_depth = obj->variant.file_variant.top_level;
> +
> +	/* 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) {
> +			u32 the_chunk = yaffs_get_group_base(dev, tn, i);
> +			if (the_chunk > 0) {


You can reduce the indentation level by doing:
		
		if (!tn)
			continue;

		the_chunk = yaffs_get_group_base(dev, tn, i);
		if (!the_chunk)
			continue;

> +				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;
> +

This (and the functions below) doesn't do anything. What's it for?

> +	/* 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, __LINE__);
> +
> +		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, __LINE__);
> +	}
> +
> +	/* 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;

Print a warning/do nothing for the verifications which have empty functions?

> +	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);

	list_for_each_entry(lh, &dev->obj_bucket[i].list, 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");
> +		YBUG();
> +		return;
> +	}
> +
> +	if (yaffs_skip_verification(obj->my_dev))
> +		return;
> +
> +	if (!obj->parent) {
> +		yaffs_trace(YAFFS_TRACE_ALWAYS, "Object does not have parent");
> +		YBUG();
> +		return;
> +	}
> +
> +	if (obj->parent->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY) {
> +		yaffs_trace(YAFFS_TRACE_ALWAYS, "Parent is not directory");
> +		YBUG();
> +	}
> +
> +	/* 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);

	list_for_each_entry(lh,
		&obj->parent->variant.dir_variant.children, 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);
> +		YBUG();
> +	}
> +}
> +
> +void yaffs_verify_dir(struct yaffs_obj *directory)
> +{
> +	struct list_head *lh;
> +	struct yaffs_obj *list_obj;
> +
> +	if (!directory) {
> +		YBUG();
> +		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);
> +		YBUG();
> +	}
> +
> +	/* 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);

	list_for_each_entry(lh,
		&directory->variant.dir_variant.children, siblings)

> +		if (list_obj->parent != directory) {
> +			yaffs_trace(YAFFS_TRACE_ALWAYS,
> +				"Object in directory list has wrong parent %p",
> +				list_obj->parent);
> +			YBUG();
> +		}
> +		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)
> +{
> +	in = in;
> +	return YAFFS_OK;
> +}

Useless function.

> +
> diff --git a/fs/yaffs2/yaffs_verify.h b/fs/yaffs2/yaffs_verify.h
> new file mode 100644
> index 0000000..cc6f889
> --- /dev/null
> +++ b/fs/yaffs2/yaffs_verify.h
> @@ -0,0 +1,43 @@
> +/*
> + * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
> + *
> + * Copyright (C) 2002-2010 Aleph One Ltd.
> + *   for Toby Churchill Ltd and Brightstar Engineering
> + *
> + * Created by Charles Manning <charles@...ph1.co.uk>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU Lesser General Public License version 2.1 as
> + * published by the Free Software Foundation.
> + *
> + * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
> + */
> +
> +#ifndef __YAFFS_VERIFY_H__
> +#define __YAFFS_VERIFY_H__
> +
> +#include "yaffs_guts.h"
> +
> +void yaffs_verify_blk(struct yaffs_dev *dev, struct yaffs_block_info *bi,
> +		      int n);
> +void yaffs_verify_collected_blk(struct yaffs_dev *dev,
> +				struct yaffs_block_info *bi, int n);
> +void yaffs_verify_blocks(struct yaffs_dev *dev);
> +
> +void yaffs_verify_oh(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh,
> +		     struct yaffs_ext_tags *tags, int parent_check);
> +void yaffs_verify_file(struct yaffs_obj *obj);
> +void yaffs_verify_link(struct yaffs_obj *obj);
> +void yaffs_verify_symlink(struct yaffs_obj *obj);
> +void yaffs_verify_special(struct yaffs_obj *obj);
> +void yaffs_verify_obj(struct yaffs_obj *obj);
> +void yaffs_verify_objects(struct yaffs_dev *dev);
> +void yaffs_verify_obj_in_dir(struct yaffs_obj *obj);
> +void yaffs_verify_dir(struct yaffs_obj *directory);
> +void yaffs_verify_free_chunks(struct yaffs_dev *dev);
> +
> +int yaffs_verify_file_sane(struct yaffs_obj *obj);
> +
> +int yaffs_skip_verification(struct yaffs_dev *dev);
> +
> +#endif


-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

Ryan Mallon         		5 Amuri Park, 404 Barbadoes St
ryan@...ewatersys.com         	PO Box 13 889, Christchurch 8013
http://www.bluewatersys.com	New Zealand
Phone: +64 3 3779127		Freecall: Australia 1800 148 751
Fax:   +64 3 3779135			  USA 1800 261 2934
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ