Re: [PATCH 06/10] Add yaffs2 file system: Tracing and verificationcode

From: Ryan Mallon
Date: Wed Jan 19 2011 - 19:30:14 EST


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

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@xxxxxxxxxxxx>
> + *
> + * 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@xxxxxxxxxxxx>
> + *
> + * 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@xxxxxxxxxxxx>
> + *
> + * 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@xxxxxxxxxxxx>
> + *
> + * 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@xxxxxxxxxxxx>
> + *
> + * 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@xxxxxxxxxxxxxxxx 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@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/