From: Charles Manning Date: Wed, 3 Nov 2010 01:04:02 +0000 (+1300) Subject: yaffs: More clean up X-Git-Tag: linux-mainline-patchset-4~136 X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=commitdiff_plain;h=a233a8fc212a32a50cc5f572cd4946e91cc9ca93 yaffs: More clean up Signed-off-by: Charles Manning --- diff --git a/Makefile b/Makefile index 1be1ab9..1dbafc6 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ ifneq ($(KERNELRELEASE),) yaffs2-objs += yaffs_tagscompat.o yaffs_tagsvalidity.o yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o - yaffs2-objs += yaffs_allocator.o yaffs_bitmap.o + yaffs2-objs += yaffs_allocator.o yaffs_bitmap.o yaffs_attribs.o yaffs2-objs += yaffs_yaffs1.o yaffs2-objs += yaffs_yaffs2.o yaffs2-objs += yaffs_verify.o @@ -45,7 +45,7 @@ ifneq ($(KERNELRELEASE),) yaffs2multi-objs += yaffs_tagscompat.o yaffs_tagsvalidity.o yaffs2multi-objs += yaffs_checkptrw.o yaffs_nand.o yaffs2multi-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o - yaffs2multi-objs += yaffs_allocator.o yaffs_bitmap.o + yaffs2multi-objs += yaffs_allocator.o yaffs_bitmap.o yaffs_attribs.o yaffs2multi-objs += yaffs_yaffs1.o yaffs2multi-objs += yaffs_yaffs2.o yaffs2multi-objs += yaffs_verify.o diff --git a/Makefile.kernel b/Makefile.kernel index 9011f70..e63a28a 100644 --- a/Makefile.kernel +++ b/Makefile.kernel @@ -8,7 +8,7 @@ yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o -yaffs-y += yaffs_nameval.o +yaffs-y += yaffs_nameval.o yaffs_attribs.o yaffs-y += yaffs_allocator.o yaffs-y += yaffs_yaffs1.o yaffs-y += yaffs_yaffs2.o diff --git a/direct/basic-test/Makefile b/direct/basic-test/Makefile index 542efba..7847528 100644 --- a/direct/basic-test/Makefile +++ b/direct/basic-test/Makefile @@ -34,8 +34,8 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ yaffs_checkptrw.o yaffs_qsort.o\ - yaffs_nameval.o \ - yaffs_norif1.o ynorsim.o nor_stress.o yaffs_fsx.o \ + yaffs_nameval.o yaffs_attribs.o \ + yaffs_norif1.o ynorsim.o \ yaffs_allocator.o \ yaffs_bitmap.o \ yaffs_yaffs1.o \ @@ -44,17 +44,13 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf # yaffs_checkptrwtest.o\ -YAFFSTESTOBJS = $(COMMONTESTOBJS) yaffs_test.o - - -ALLOBJS = $(sort $(YAFFSTESTOBJS)) YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscompat.c yaffs_tagscompat.h \ yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h \ yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \ yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ yaffs_nameval.c yaffs_nameval.h \ - yaffs_trace.h \ + yaffs_trace.h yaffs_attribs.h \ yaffs_allocator.c yaffs_allocator.h \ yaffs_yaffs1.c yaffs_yaffs1.h \ yaffs_yaffs2.c yaffs_yaffs2.h \ @@ -64,7 +60,7 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ yaffsfs.h yaffs_malloc.h ydirectenv.h \ yaffs_flashif.c yaffscfg.h yaffs_list.h \ - yaffs_qsort.c yportenv.h \ + yaffs_qsort.c yportenv.h yaffs_attribs.c \ yaffs_nandif.c yaffs_nandif.h yaffs_nandemul2k.h @@ -72,21 +68,6 @@ YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ SYMLINKS = $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) - - -COMMONTESTOBJS = yaffsnewcfg.o yramsim.o \ - yaffsfs.o yaffs_guts.o yaffs_ecc.o yaffs_nandif.o \ - yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ - yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ - yaffs_checkptrw.o yaffs_qsort.o\ - yaffs_nameval.o \ - yaffs_norif1.o ynorsim.o \ - yaffs_allocator.o yaffs_yaffs1.o \ - yaffs_yaffs2.o \ - yaffs_bitmap.o yaffs_verify.o - -# yaffs_checkptrwtest.o\ - DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o diff --git a/direct/basic-test/yaffs_fileem2k.c b/direct/basic-test/yaffs_fileem2k.c index d8fde73..06e41e5 100644 --- a/direct/basic-test/yaffs_fileem2k.c +++ b/direct/basic-test/yaffs_fileem2k.c @@ -24,15 +24,16 @@ const char *yaffs_flashif2_c_version = "$Id: yaffs_fileem2k.c,v 1.24 2010-02-18 #include "yaffs_flashif2.h" #include "yaffs_guts.h" +#include "yaffs_fileem2k.h" +#include "yaffs_packedtags2.h" +#include "yaffs_tagsvalidity.h" + #include #include #include #include -#include "yaffs_fileem2k.h" -#include "yaffs_packedtags2.h" - #define REPORT_ERROR 0 @@ -65,7 +66,6 @@ int yaffs_test_partial_write = 0; extern int random_seed; extern int simulate_power_failure; -static int initialised = 0; static int remaining_ops; static int nops_so_far; @@ -179,7 +179,7 @@ int yflash2_WriteChunkWithTagsToNAND(struct yaffs_dev *dev,int nand_chunk,const int nRead; int error; - T(YAFFS_TRACE_MTD,(TSTR("write chunk %d data %x tags %x" TENDSTR),nand_chunk,(unsigned)data, (unsigned)tags)); + T(YAFFS_TRACE_MTD,(TSTR("write chunk %d data %p tags %p" TENDSTR),nand_chunk, data, tags)); CheckInit(); @@ -396,7 +396,7 @@ int yflash2_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 * int retval = YAFFS_OK; int nRead; - T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %x tags %x" TENDSTR),nand_chunk,(unsigned)data, (unsigned)tags)); + T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %p tags %p" TENDSTR),nand_chunk, data, tags)); CheckInit(); diff --git a/direct/python/Makefile b/direct/python/Makefile index f571cf4..7c7a063 100644 --- a/direct/python/Makefile +++ b/direct/python/Makefile @@ -30,7 +30,7 @@ CFLAGS += -O0 -fPIC COMMONTESTOBJS = yaffscfg2k.o yramsim.o yaffs_fileem2k.o\ - yaffs_nandif.o \ + yaffs_nandif.o yaffs_attribs.o \ yaffsfs.o yaffs_ecc.o yaffs_guts.o \ yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ @@ -51,7 +51,7 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h \ yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \ yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ - yaffs_nameval.c yaffs_nameval.h \ + yaffs_nameval.c yaffs_nameval.h yaffs_attribs.h \ yaffs_trace.h \ yaffs_allocator.c yaffs_allocator.h \ yaffs_yaffs1.c yaffs_yaffs1.h \ @@ -63,7 +63,7 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp YAFFSDIRECTSYMLINKS = yaffsfs.c yaffsfs.h yaffscfg.h yaffs_malloc.h ydirectenv.h \ yaffs_flashif.c yaffs_flashif.h yaffs_flashif2.h yaffs_list.h \ yaffs_nandif.c yaffs_nandif.h yaffs_qsort.c yaffs_nandemul2k.h \ - yportenv.h + yportenv.h yaffs_attribs.c DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\ yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \ diff --git a/direct/tests/Makefile b/direct/tests/Makefile index cb90c29..016b934 100644 --- a/direct/tests/Makefile +++ b/direct/tests/Makefile @@ -34,7 +34,7 @@ COMMONTESTOBJS = yaffscfg2k.o yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsf yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \ yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \ yaffs_checkptrw.o yaffs_qsort.o\ - yaffs_nameval.o \ + yaffs_nameval.o yaffs_attribs.o \ yaffs_norif1.o ynorsim.o nor_stress.o yaffs_fsx.o \ yaffs_allocator.o \ yaffs_bitmap.o \ @@ -54,7 +54,7 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \ yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \ yaffs_nameval.c yaffs_nameval.h \ - yaffs_trace.h \ + yaffs_trace.h yaffs_attribs.h \ yaffs_allocator.c yaffs_allocator.h \ yaffs_yaffs1.c yaffs_yaffs1.h \ yaffs_yaffs2.c yaffs_yaffs2.h \ @@ -65,6 +65,7 @@ YAFFSDIRECTSYMLINKS = yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\ yaffsfs.h yaffs_malloc.h ydirectenv.h \ yaffs_flashif.c yaffscfg.h yaffs_qsort.c \ yaffs_nandemul2k.h yaffs_list.h \ + yaffs_attribs.c \ yaffs_nandif.c yaffs_nandif.h yportenv.h diff --git a/direct/yaffs_attribs.c b/direct/yaffs_attribs.c new file mode 100644 index 0000000..89cd7fc --- /dev/null +++ b/direct/yaffs_attribs.c @@ -0,0 +1,153 @@ +/* + * 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 + * + * 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_attribs.h" + + +void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh) +{ + obj->yst_uid = oh->yst_uid; + obj->yst_gid = oh->yst_gid; + obj->yst_atime = oh->yst_atime; + obj->yst_mtime = oh->yst_mtime; + obj->yst_ctime = oh->yst_ctime; + obj->yst_rdev = oh->yst_rdev; +} + + +void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj) +{ +#ifdef CONFIG_YAFFS_WINCE + oh->win_atime[0] = obj->win_atime[0]; + oh->win_ctime[0] = obj->win_ctime[0]; + oh->win_mtime[0] = obj->win_mtime[0]; + oh->win_atime[1] = obj->win_atime[1]; + oh->win_ctime[1] = obj->win_ctime[1]; + oh->win_mtime[1] = obj->win_mtime[1]; +#else + oh->yst_uid = obj->yst_uid; + oh->yst_gid = obj->yst_gid; + oh->yst_atime = obj->yst_atime; + oh->yst_mtime = obj->yst_mtime; + oh->yst_ctime = obj->yst_ctime; + oh->yst_rdev = obj->yst_rdev; +#endif + +} + +void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev) +{ + +#ifdef CONFIG_YAFFS_WINCE + yfsd_win_file_time_now(obj->win_atime); + obj->win_ctime[0] = obj->win_mtime[0] = obj->win_atime[0]; + obj->win_ctime[1] = obj->win_mtime[1] = obj->win_atime[1]; + +#else + yaffs_load_current_time(obj,1,1); + obj->yst_rdev = rdev; + obj->yst_uid = uid; + obj->yst_gid = gid; +#endif +} + +void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c) +{ +#ifdef CONFIG_YAFFS_WINCE + yfsd_win_file_time_now(the_obj->win_atime); + the_obj->win_ctime[0] = the_obj->win_mtime[0] = + the_obj->win_atime[0]; + the_obj->win_ctime[1] = the_obj->win_mtime[1] = + the_obj->win_atime[1]; + +#else + + obj->yst_mtime = Y_CURRENT_TIME; + if(do_a) + obj->yst_atime = obj->yst_atime; + if(do_c) + obj->yst_ctime = obj->yst_atime; +#endif +} + +loff_t yaffs_get_file_size(struct yaffs_obj *obj) +{ + YCHAR *alias = NULL; + obj = yaffs_get_equivalent_obj(obj); + + switch (obj->variant_type) { + case YAFFS_OBJECT_TYPE_FILE: + return obj->variant.file_variant.file_size; + case YAFFS_OBJECT_TYPE_SYMLINK: + alias = obj->variant.symlink_variant.alias; + if(!alias) + return 0; + return yaffs_strnlen(alias,YAFFS_MAX_ALIAS_LENGTH); + default: + return 0; + } +} + +int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr) +{ + unsigned int valid = attr->ia_valid; + + if (valid & ATTR_MODE) + obj->yst_mode = attr->ia_mode; + if (valid & ATTR_UID) + obj->yst_uid = attr->ia_uid; + if (valid & ATTR_GID) + obj->yst_gid = attr->ia_gid; + + if (valid & ATTR_ATIME) + obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime); + if (valid & ATTR_CTIME) + obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime); + if (valid & ATTR_MTIME) + obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime); + + if (valid & ATTR_SIZE) + yaffs_resize_file(obj, attr->ia_size); + + yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); + + return YAFFS_OK; + +} + +int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr) +{ + unsigned int valid = 0; + + attr->ia_mode = obj->yst_mode; + valid |= ATTR_MODE; + attr->ia_uid = obj->yst_uid; + valid |= ATTR_UID; + attr->ia_gid = obj->yst_gid; + valid |= ATTR_GID; + + Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime; + valid |= ATTR_ATIME; + Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime; + valid |= ATTR_CTIME; + Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime; + valid |= ATTR_MTIME; + + attr->ia_size = yaffs_get_file_size(obj); + valid |= ATTR_SIZE; + + attr->ia_valid = valid; + + return YAFFS_OK; +} + diff --git a/direct/yaffs_flashif2.h b/direct/yaffs_flashif2.h index 17d2dfa..75a66de 100644 --- a/direct/yaffs_flashif2.h +++ b/direct/yaffs_flashif2.h @@ -23,7 +23,6 @@ int yflash2_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data int yflash2_WriteChunkWithTagsToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, const struct yaffs_ext_tags *tags); int yflash2_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_spare *spare); int yflash2_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_ext_tags *tags); -int yflash2_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber); int yflash2_InitialiseNAND(struct yaffs_dev *dev); int yflash2_MarkNANDBlockBad(struct yaffs_dev *dev, int block_no); int yflash2_QueryNANDBlock(struct yaffs_dev *dev, int block_no, enum yaffs_block_state *state, u32 *seq_number); diff --git a/yaffs_attribs.c b/yaffs_attribs.c new file mode 100644 index 0000000..651a473 --- /dev/null +++ b/yaffs_attribs.c @@ -0,0 +1,128 @@ +/* + * 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 + * + * 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_guts.h" +#include "yaffs_attribs.h" + +void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh) +{ + obj->yst_uid = oh->yst_uid; + obj->yst_gid = oh->yst_gid; + obj->yst_atime = oh->yst_atime; + obj->yst_mtime = oh->yst_mtime; + obj->yst_ctime = oh->yst_ctime; + obj->yst_rdev = oh->yst_rdev; +} + +void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj) +{ + oh->yst_uid = obj->yst_uid; + oh->yst_gid = obj->yst_gid; + oh->yst_atime = obj->yst_atime; + oh->yst_mtime = obj->yst_mtime; + oh->yst_ctime = obj->yst_ctime; + oh->yst_rdev = obj->yst_rdev; + +} + +void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c) +{ + obj->yst_mtime = Y_CURRENT_TIME; + if(do_a) + obj->yst_atime = obj->yst_atime; + if(do_c) + obj->yst_ctime = obj->yst_atime; +} + +void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev) +{ + yaffs_load_current_time(obj,1,1); + obj->yst_rdev = rdev; + obj->yst_uid = uid; + obj->yst_gid = gid; +} + + +loff_t yaffs_get_file_size(struct yaffs_obj *obj) +{ + YCHAR *alias = NULL; + obj = yaffs_get_equivalent_obj(obj); + + switch (obj->variant_type) { + case YAFFS_OBJECT_TYPE_FILE: + return obj->variant.file_variant.file_size; + case YAFFS_OBJECT_TYPE_SYMLINK: + alias = obj->variant.symlink_variant.alias; + if(!alias) + return 0; + return yaffs_strnlen(alias,YAFFS_MAX_ALIAS_LENGTH); + default: + return 0; + } +} + +int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr) +{ + unsigned int valid = attr->ia_valid; + + if (valid & ATTR_MODE) + obj->yst_mode = attr->ia_mode; + if (valid & ATTR_UID) + obj->yst_uid = attr->ia_uid; + if (valid & ATTR_GID) + obj->yst_gid = attr->ia_gid; + + if (valid & ATTR_ATIME) + obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime); + if (valid & ATTR_CTIME) + obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime); + if (valid & ATTR_MTIME) + obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime); + + if (valid & ATTR_SIZE) + yaffs_resize_file(obj, attr->ia_size); + + yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); + + return YAFFS_OK; + +} + +int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr) +{ + unsigned int valid = 0; + + attr->ia_mode = obj->yst_mode; + valid |= ATTR_MODE; + attr->ia_uid = obj->yst_uid; + valid |= ATTR_UID; + attr->ia_gid = obj->yst_gid; + valid |= ATTR_GID; + + Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime; + valid |= ATTR_ATIME; + Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime; + valid |= ATTR_CTIME; + Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime; + valid |= ATTR_MTIME; + + attr->ia_size = yaffs_get_file_size(obj); + valid |= ATTR_SIZE; + + attr->ia_valid = valid; + + return YAFFS_OK; +} + + diff --git a/yaffs_attribs.h b/yaffs_attribs.h new file mode 100644 index 0000000..c9a0867 --- /dev/null +++ b/yaffs_attribs.h @@ -0,0 +1,32 @@ +/* + * 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 + * + * 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_ATTRIBS_H__ +#define __YAFFS_ATTRIBS_H__ + + +#include "yaffs_guts.h" + + +void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh); +void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj); +void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev); +void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c); +int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr); +int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr); + + +#endif + diff --git a/yaffs_guts.c b/yaffs_guts.c index cd1bb12..ce7ed7e 100644 --- a/yaffs_guts.c +++ b/yaffs_guts.c @@ -33,6 +33,8 @@ #include "yaffs_nameval.h" #include "yaffs_allocator.h" +#include "yaffs_attribs.h" + /* Note YAFFS_GC_GOOD_ENOUGH must be <= YAFFS_GC_PASSIVE_THRESHOLD */ #define YAFFS_GC_GOOD_ENOUGH 2 #define YAFFS_GC_PASSIVE_THRESHOLD 4 @@ -1366,23 +1368,13 @@ struct yaffs_obj *yaffs_new_obj(struct yaffs_dev *dev, int number, the_obj->obj_id = number; yaffs_hash_obj(the_obj); the_obj->variant_type = type; -#ifdef CONFIG_YAFFS_WINCE - yfsd_win_file_time_now(the_obj->win_atime); - the_obj->win_ctime[0] = the_obj->win_mtime[0] = - the_obj->win_atime[0]; - the_obj->win_ctime[1] = the_obj->win_mtime[1] = - the_obj->win_atime[1]; - -#else + yaffs_load_current_time(the_obj,1,1); - the_obj->yst_atime = the_obj->yst_mtime = - the_obj->yst_ctime = Y_CURRENT_TIME; -#endif switch (type) { case YAFFS_OBJECT_TYPE_FILE: the_obj->variant.file_variant.file_size = 0; the_obj->variant.file_variant.scanned_size = 0; - the_obj->variant.file_variant.shrink_size = 0xFFFFFFFF; /* max u32 */ + the_obj->variant.file_variant.shrink_size = ~0;/* max */ the_obj->variant.file_variant.top_level = 0; the_obj->variant.file_variant.top = tn; break; @@ -1491,18 +1483,8 @@ static struct yaffs_obj *yaffs_create_obj(enum yaffs_obj_type type, in->yst_mode = mode; -#ifdef CONFIG_YAFFS_WINCE - yfsd_win_file_time_now(in->win_atime); - in->win_ctime[0] = in->win_mtime[0] = in->win_atime[0]; - in->win_ctime[1] = in->win_mtime[1] = in->win_atime[1]; + yaffs_attribs_init(in, gid, uid, rdev); -#else - in->yst_atime = in->yst_mtime = in->yst_ctime = Y_CURRENT_TIME; - - in->yst_rdev = rdev; - in->yst_uid = uid; - in->yst_gid = gid; -#endif in->n_data_chunks = 0; yaffs_set_obj_name(in, name); @@ -1664,7 +1646,7 @@ int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR *old_name, dev = old_dir->my_dev; #ifdef CONFIG_YAFFS_CASE_INSENSITIVE - /* Special case for case insemsitive systems (eg. WinCE). + /* Special case for case insemsitive systems. * While look-up is case insensitive, the name isn't. * Therefore we might want to change x.txt to X.txt */ @@ -2945,21 +2927,8 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force, oh->yst_mode = in->yst_mode; oh->shadows_obj = oh->inband_shadowed_obj_id = shadows; -#ifdef CONFIG_YAFFS_WINCE - oh->win_atime[0] = in->win_atime[0]; - oh->win_ctime[0] = in->win_ctime[0]; - oh->win_mtime[0] = in->win_mtime[0]; - oh->win_atime[1] = in->win_atime[1]; - oh->win_ctime[1] = in->win_ctime[1]; - oh->win_mtime[1] = in->win_mtime[1]; -#else - oh->yst_uid = in->yst_uid; - oh->yst_gid = in->yst_gid; - oh->yst_atime = in->yst_atime; - oh->yst_mtime = in->yst_mtime; - oh->yst_ctime = in->yst_ctime; - oh->yst_rdev = in->yst_rdev; -#endif + yaffs_load_attribs_oh(oh,in); + if (in->parent) oh->parent_obj_id = in->parent->obj_id; else @@ -3068,13 +3037,13 @@ int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name, int force, } /*------------------------ Short Operations Cache ---------------------------------------- - * In many situations where there is no high level buffering (eg WinCE) a lot of + * In many situations where there is no high level buffering a lot of * reads might be short sequential reads, and a lot of writes may be short * sequential writes. eg. scanning/writing a jpeg file. - * In these cases, a short read/write cache can provide a huge perfomance benefit - * with dumb-as-a-rock code. - * In Linux, the page cache provides read buffering aand the short op cache provides write - * buffering. + * In these cases, a short read/write cache can provide a huge perfomance + * benefit with dumb-as-a-rock code. + * In Linux, the page cache provides read buffering and the short op cache + * provides write buffering. * * There are a limited number (~10) of cache chunks per device so that we don't * need a very intelligent search. @@ -3725,25 +3694,6 @@ int yaffs_resize_file(struct yaffs_obj *in, loff_t new_size) return YAFFS_OK; } -loff_t yaffs_get_file_size(struct yaffs_obj *obj) -{ - YCHAR *alias = NULL; - obj = yaffs_get_equivalent_obj(obj); - - switch (obj->variant_type) { - case YAFFS_OBJECT_TYPE_FILE: - return obj->variant.file_variant.file_size; - case YAFFS_OBJECT_TYPE_SYMLINK: - alias = obj->variant.symlink_variant.alias; - if(!alias) - return 0; - return yaffs_strnlen(alias,YAFFS_MAX_ALIAS_LENGTH); - default: - return 0; - } -} - - int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync) { @@ -3753,15 +3703,8 @@ int yaffs_flush_file(struct yaffs_obj *in, int update_time, int data_sync) if(data_sync) /* Only sync data */ ret_val=YAFFS_OK; else { - if (update_time) { -#ifdef CONFIG_YAFFS_WINCE - yfsd_win_file_time_now(in->win_mtime); -#else - - in->yst_mtime = Y_CURRENT_TIME; - -#endif - } + if (update_time) + yaffs_load_current_time(in,0,0); ret_val = (yaffs_update_oh(in, NULL, 0, 0, 0, NULL) >= 0) ? YAFFS_OK : YAFFS_FAIL; @@ -4264,22 +4207,7 @@ static void yaffs_check_obj_details_loaded(struct yaffs_obj *in) oh = (struct yaffs_obj_hdr *) chunk_data; in->yst_mode = oh->yst_mode; -#ifdef CONFIG_YAFFS_WINCE - in->win_atime[0] = oh->win_atime[0]; - in->win_ctime[0] = oh->win_ctime[0]; - in->win_mtime[0] = oh->win_mtime[0]; - in->win_atime[1] = oh->win_atime[1]; - in->win_ctime[1] = oh->win_ctime[1]; - in->win_mtime[1] = oh->win_mtime[1]; -#else - in->yst_uid = oh->yst_uid; - in->yst_gid = oh->yst_gid; - in->yst_atime = oh->yst_atime; - in->yst_mtime = oh->yst_mtime; - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; - -#endif + yaffs_load_attribs(in, oh); yaffs_set_obj_name_from_oh(in, oh); if (in->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) { @@ -4316,22 +4244,21 @@ static void yaffs_update_parent(struct yaffs_obj *obj) struct yaffs_dev *dev; if(!obj) return; -#ifndef CONFIG_YAFFS_WINCE - dev = obj->my_dev; obj->dirty = 1; - obj->yst_mtime = obj->yst_ctime = Y_CURRENT_TIME; + yaffs_load_current_time(obj,0,1); if(dev->param.defered_dir_update){ struct list_head *link = &obj->variant.dir_variant.dirty; if(list_empty(link)){ list_add(link,&dev->dirty_dirs); - T(YAFFS_TRACE_BACKGROUND, (TSTR("Added object %d to dirty directories" TENDSTR),obj->obj_id)); + T(YAFFS_TRACE_BACKGROUND, + (TSTR("Added object %d to dirty directories" TENDSTR), + obj->obj_id)); } } else yaffs_update_oh(obj, NULL, 0, 0, 0, NULL); -#endif } void yaffs_update_dirty_dirs(struct yaffs_dev *dev) @@ -4716,63 +4643,6 @@ YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj) return yaffs_clone_str(_Y("")); } -#ifndef CONFIG_YAFFS_WINCE - -int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr) -{ - unsigned int valid = attr->ia_valid; - - if (valid & ATTR_MODE) - obj->yst_mode = attr->ia_mode; - if (valid & ATTR_UID) - obj->yst_uid = attr->ia_uid; - if (valid & ATTR_GID) - obj->yst_gid = attr->ia_gid; - - if (valid & ATTR_ATIME) - obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime); - if (valid & ATTR_CTIME) - obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime); - if (valid & ATTR_MTIME) - obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime); - - if (valid & ATTR_SIZE) - yaffs_resize_file(obj, attr->ia_size); - - yaffs_update_oh(obj, NULL, 1, 0, 0, NULL); - - return YAFFS_OK; - -} -int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr) -{ - unsigned int valid = 0; - - attr->ia_mode = obj->yst_mode; - valid |= ATTR_MODE; - attr->ia_uid = obj->yst_uid; - valid |= ATTR_UID; - attr->ia_gid = obj->yst_gid; - valid |= ATTR_GID; - - Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime; - valid |= ATTR_ATIME; - Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime; - valid |= ATTR_CTIME; - Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime; - valid |= ATTR_MTIME; - - attr->ia_size = yaffs_get_file_size(obj); - valid |= ATTR_SIZE; - - attr->ia_valid = valid; - - return YAFFS_OK; -} - -#endif - - static int yaffs_do_xattrib_mod(struct yaffs_obj *obj, int set, const YCHAR *name, const void *value, int size, int flags) { struct yaffs_xattr_mod xmod; diff --git a/yaffs_guts.h b/yaffs_guts.h index 13a2e87..fe6e934 100644 --- a/yaffs_guts.h +++ b/yaffs_guts.h @@ -306,15 +306,11 @@ struct yaffs_obj_hdr { /* The following apply to directories, files, symlinks - not hard links */ u32 yst_mode; /* protection */ -#ifdef CONFIG_YAFFS_WINCE - u32 not_for_wince[5]; -#else u32 yst_uid; u32 yst_gid; u32 yst_atime; u32 yst_mtime; u32 yst_ctime; -#endif /* File size applies to files only */ int file_size; @@ -327,14 +323,10 @@ struct yaffs_obj_hdr { u32 yst_rdev; /* device stuff for block and char devices (major/min) */ -#ifdef CONFIG_YAFFS_WINCE u32 win_ctime[2]; u32 win_atime[2]; u32 win_mtime[2]; -#else - u32 room_to_grow[6]; -#endif u32 inband_shadowed_obj_id; u32 inband_is_shrink; @@ -829,9 +821,6 @@ int yaffs_get_obj_inode(struct yaffs_obj *obj); unsigned yaffs_get_obj_type(struct yaffs_obj *obj); int yaffs_get_obj_link_count(struct yaffs_obj *obj); -int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr); -int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr); - /* File operations */ int yaffs_file_rd(struct yaffs_obj *obj, u8 *buffer, loff_t offset, int n_bytes); @@ -882,11 +871,6 @@ int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name); struct yaffs_obj *yaffs_root(struct yaffs_dev *dev); struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev); -#ifdef CONFIG_YAFFS_WINCE -/* CONFIG_YAFFS_WINCE special stuff */ -void yfsd_win_file_time_now(u32 target[2]); -#endif - void yaffs_handle_defered_free(struct yaffs_obj *obj); void yaffs_update_dirty_dirs(struct yaffs_dev *dev); diff --git a/yaffs_mtdif1_multi.c b/yaffs_mtdif1_multi.c new file mode 100644 index 0000000..ac0f00c --- /dev/null +++ b/yaffs_mtdif1_multi.c @@ -0,0 +1,362 @@ +/* + * YAFFS: Yet another FFS. A NAND-flash specific file system. + * + * Copyright (C) 2002-2010 Aleph One Ltd. + * for Toby Churchill Ltd and Brightstar Engineering + * + * Created by Charles Manning + * + * 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. + */ + +/* + * This module provides the interface between yaffs_nand.c and the + * MTD API. This version is used when the MTD interface supports the + * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17, + * and we have small-page NAND device. + * + * These functions are invoked via function pointers in yaffs_nand.c. + * This replaces functionality provided by functions in yaffs_mtdif.c + * and the yaffs_tags compatability functions in yaffs_tagscompat.c that are + * called in yaffs_mtdif.c when the function pointers are NULL. + * We assume the MTD layer is performing ECC (use_nand_ecc is true). + */ + +#include "yportenv.h" +#include "yaffs_trace.h" +#include "yaffs_guts.h" +#include "yaffs_packedtags1.h" +#include "yaffs_tagscompat.h" /* for yaffs_calc_tags_ecc */ +#include "yaffs_linux.h" + +#include "linux/kernel.h" +#include "linux/version.h" +#include "linux/types.h" +#include "linux/mtd/mtd.h" + +/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */ +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) + +#ifndef CONFIG_YAFFS_9BYTE_TAGS +# define YTAG1_SIZE 8 +#else +# define YTAG1_SIZE 9 +#endif + +#if 0 +/* Use the following nand_ecclayout with MTD when using + * CONFIG_YAFFS_9BYTE_TAGS and the older on-NAND tags layout. + * If you have existing Yaffs images and the byte order differs from this, + * adjust 'oobfree' to match your existing Yaffs data. + * + * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the + * page_status byte (at NAND spare offset 4) scattered/gathered from/to + * the 9th byte. + * + * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5 + * We have/need packed_tags1 plus page_status: T0,T1,T2,T3,T4,T5,T6,T7,P + * where Tn are the tag bytes, En are MTD's ECC bytes, P is the page_status + * byte and B is the small-page bad-block indicator byte. + */ +static struct nand_ecclayout nand_oob_16 = { + .eccbytes = 6, + .eccpos = { 8, 9, 10, 13, 14, 15 }, + .oobavail = 9, + .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } +}; +#endif + +/* Write a chunk (page) of data to NAND. + * + * Caller always provides ExtendedTags data which are converted to a more + * compact (packed) form for storage in NAND. A mini-ECC runs over the + * contents of the tags meta-data; used to valid the tags when read. + * + * - Pack ExtendedTags to packed_tags1 form + * - Compute mini-ECC for packed_tags1 + * - Write data and packed tags to NAND. + * + * Note: Due to the use of the packed_tags1 meta-data which does not include + * a full sequence number (as found in the larger packed_tags2 form) it is + * necessary for Yaffs to re-write a chunk/page (just once) to mark it as + * discarded and dirty. This is not ideal: newer NAND parts are supposed + * to be written just once. When Yaffs performs this operation, this + * function is called with a NULL data pointer -- calling MTD write_oob + * without data is valid usage (2.6.17). + * + * Any underlying MTD error results in YAFFS_FAIL. + * Returns YAFFS_OK or YAFFS_FAIL. + */ +int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, + int nand_chunk, const u8 *data, const struct yaffs_ext_tags *etags) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + int chunk_bytes = dev->data_bytes_per_chunk; + loff_t addr = ((loff_t)nand_chunk) * chunk_bytes; + struct mtd_oob_ops ops; + struct yaffs_packed_tags1 pt1; + int retval; + + /* we assume that packed_tags1 and struct yaffs_tags are compatible */ + compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12); + compile_time_assertion(sizeof(struct yaffs_tags) == 8); + + yaffs_pack_tags1(&pt1, etags); + yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1); + + /* When deleting a chunk, the upper layer provides only skeletal + * etags, one with is_deleted set. However, we need to update the + * tags, not erase them completely. So we use the NAND write property + * that only zeroed-bits stick and set tag bytes to all-ones and + * zero just the (not) deleted bit. + */ +#ifndef CONFIG_YAFFS_9BYTE_TAGS + if (etags->is_deleted) { + memset(&pt1, 0xff, 8); + /* clear delete status bit to indicate deleted */ + pt1.deleted = 0; + } +#else + ((u8 *)&pt1)[8] = 0xff; + if (etags->is_deleted) { + memset(&pt1, 0xff, 8); + /* zero page_status byte to indicate deleted */ + ((u8 *)&pt1)[8] = 0; + } +#endif + + memset(&ops, 0, sizeof(ops)); + ops.mode = MTD_OOB_AUTO; + ops.len = (data) ? chunk_bytes : 0; + ops.ooblen = YTAG1_SIZE; + ops.datbuf = (u8 *)data; + ops.oobbuf = (u8 *)&pt1; + + retval = mtd->write_oob(mtd, addr, &ops); + if (retval) { + T(YAFFS_TRACE_MTD, + (TSTR("write_oob failed, chunk %d, mtd error %d"TENDSTR), + nand_chunk, retval)); + } + return retval ? YAFFS_FAIL : YAFFS_OK; +} + +/* Return with empty ExtendedTags but add ecc_result. + */ +static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval) +{ + if (etags) { + memset(etags, 0, sizeof(*etags)); + etags->ecc_result = ecc_result; + } + return retval; +} + +/* Read a chunk (page) from NAND. + * + * Caller expects ExtendedTags data to be usable even on error; that is, + * all members except ecc_result and block_bad are zeroed. + * + * - Check ECC results for data (if applicable) + * - Check for blank/erased block (return empty ExtendedTags if blank) + * - Check the packed_tags1 mini-ECC (correct if necessary/possible) + * - Convert packed_tags1 to ExtendedTags + * - Update ecc_result and block_bad members to refect state. + * + * Returns YAFFS_OK or YAFFS_FAIL. + */ +int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, + int nand_chunk, u8 *data, struct yaffs_ext_tags *etags) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + int chunk_bytes = dev->data_bytes_per_chunk; + loff_t addr = ((loff_t)nand_chunk) * chunk_bytes; + int eccres = YAFFS_ECC_RESULT_NO_ERROR; + struct mtd_oob_ops ops; + struct yaffs_packed_tags1 pt1; + int retval; + int deleted; + + memset(&ops, 0, sizeof(ops)); + ops.mode = MTD_OOB_AUTO; + ops.len = (data) ? chunk_bytes : 0; + ops.ooblen = YTAG1_SIZE; + ops.datbuf = data; + ops.oobbuf = (u8 *)&pt1; + +#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20)) + /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug; + * help it out with ops.len = ops.ooblen when ops.datbuf == NULL. + */ + ops.len = (ops.datbuf) ? ops.len : ops.ooblen; +#endif + /* Read page and oob using MTD. + * Check status and determine ECC result. + */ + retval = mtd->read_oob(mtd, addr, &ops); + if (retval) { + T(YAFFS_TRACE_MTD, + (TSTR("read_oob failed, chunk %d, mtd error %d"TENDSTR), + nand_chunk, retval)); + } + + switch (retval) { + case 0: + /* no error */ + break; + + case -EUCLEAN: + /* MTD's ECC fixed the data */ + eccres = YAFFS_ECC_RESULT_FIXED; + dev->n_ecc_fixed++; + break; + + case -EBADMSG: + /* MTD's ECC could not fix the data */ + dev->n_ecc_unfixed++; + /* fall into... */ + default: + rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0); + etags->block_bad = (mtd->block_isbad)(mtd, addr); + return YAFFS_FAIL; + } + + /* Check for a blank/erased chunk. + */ + if (yaffs_check_ff((u8 *)&pt1, 8)) { + /* when blank, upper layers want ecc_result to be <= NO_ERROR */ + return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK); + } + +#ifndef CONFIG_YAFFS_9BYTE_TAGS + /* Read deleted status (bit) then return it to it's non-deleted + * state before performing tags mini-ECC check. pt1.deleted is + * inverted. + */ + deleted = !pt1.deleted; + pt1.deleted = 1; +#else + deleted = (yaffs_count_bits(((u8 *)&pt1)[8]) < 7); +#endif + + /* Check the packed tags mini-ECC and correct if necessary/possible. + */ + retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1); + switch (retval) { + case 0: + /* no tags error, use MTD result */ + break; + case 1: + /* recovered tags-ECC error */ + dev->n_tags_ecc_fixed++; + if (eccres == YAFFS_ECC_RESULT_NO_ERROR) + eccres = YAFFS_ECC_RESULT_FIXED; + break; + default: + /* unrecovered tags-ECC error */ + dev->n_tags_ecc_unfixed++; + return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL); + } + + /* Unpack the tags to extended form and set ECC result. + * [set should_be_ff just to keep yaffs_unpack_tags1 happy] + */ + pt1.should_be_ff = 0xFFFFFFFF; + yaffs_unpack_tags1(etags, &pt1); + etags->ecc_result = eccres; + + /* Set deleted state */ + etags->is_deleted = deleted; + return YAFFS_OK; +} + +/* Mark a block bad. + * + * This is a persistant state. + * Use of this function should be rare. + * + * Returns YAFFS_OK or YAFFS_FAIL. + */ +int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk; + int retval; + + T(YAFFS_TRACE_BAD_BLOCKS,(TSTR("marking block %d bad"TENDSTR), block_no)); + + retval = mtd->block_markbad(mtd, (loff_t)blocksize * block_no); + return (retval) ? YAFFS_FAIL : YAFFS_OK; +} + +/* Check any MTD prerequists. + * + * Returns YAFFS_OK or YAFFS_FAIL. + */ +static int nandmtd1_test_prerequists(struct mtd_info *mtd) +{ + /* 2.6.18 has mtd->ecclayout->oobavail */ + /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */ + int oobavail = mtd->ecclayout->oobavail; + + if (oobavail < YTAG1_SIZE) { + T(YAFFS_TRACE_ERROR, + (TSTR("mtd device has only %d bytes for tags, need %d"TENDSTR), + oobavail, YTAG1_SIZE)); + return YAFFS_FAIL; + } + return YAFFS_OK; +} + +/* Query for the current state of a specific block. + * + * Examine the tags of the first chunk of the block and return the state: + * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad + * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use + * - YAFFS_BLOCK_STATE_EMPTY, the block is clean + * + * Always returns YAFFS_OK. + */ +int nandmtd1_query_block(struct yaffs_dev *dev, int block_no, + enum yaffs_block_state *state_ptr, u32 *seq_ptr) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + int chunk_num = block_no * dev->param.chunks_per_block; + loff_t addr = (loff_t)chunk_num * dev->data_bytes_per_chunk; + struct yaffs_ext_tags etags; + int state = YAFFS_BLOCK_STATE_DEAD; + int seqnum = 0; + int retval; + + /* We don't yet have a good place to test for MTD config prerequists. + * Do it here as we are called during the initial scan. + */ + if (nandmtd1_test_prerequists(mtd) != YAFFS_OK) + return YAFFS_FAIL; + + retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags); + etags.block_bad = (mtd->block_isbad)(mtd, addr); + if (etags.block_bad) { + T(YAFFS_TRACE_BAD_BLOCKS, + (TSTR("block %d is marked bad"TENDSTR), block_no)); + state = YAFFS_BLOCK_STATE_DEAD; + } else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) { + /* bad tags, need to look more closely */ + state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; + } else if (etags.chunk_used) { + state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; + seqnum = etags.seq_number; + } else { + state = YAFFS_BLOCK_STATE_EMPTY; + } + + *state_ptr = state; + *seq_ptr = seqnum; + + /* query always succeeds */ + return YAFFS_OK; +} + +#endif /*MTD_VERSION*/ diff --git a/yaffs_mtdif2_multi.c b/yaffs_mtdif2_multi.c new file mode 100644 index 0000000..04fb39d --- /dev/null +++ b/yaffs_mtdif2_multi.c @@ -0,0 +1,256 @@ +/* + * 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 + * + * 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. + */ + +/* mtd interface for YAFFS2 */ + +#include "yportenv.h" +#include "yaffs_trace.h" + +#include "yaffs_mtdif2.h" + +#include "linux/mtd/mtd.h" +#include "linux/types.h" +#include "linux/time.h" + +#include "yaffs_packedtags2.h" + +#include "yaffs_linux.h" + +/* NB For use with inband tags.... + * We assume that the data buffer is of size total_bytes_per_chunk so that we can also + * use it to load the tags. + */ +int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, + const u8 *data, + const struct yaffs_ext_tags *tags) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) + struct mtd_oob_ops ops; +#else + size_t dummy; +#endif + int retval = 0; + + loff_t addr; + + struct yaffs_packed_tags2 pt; + + int packed_tags_size = dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); + void * packed_tags_ptr = dev->param.no_tags_ecc ? (void *) &pt.t : (void *)&pt; + + T(YAFFS_TRACE_MTD, + (TSTR + ("nandmtd2_write_chunk_tags chunk %d data %p tags %p" + TENDSTR), nand_chunk, data, tags)); + + + addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; + + /* For yaffs2 writing there must be both data and tags. + * If we're using inband tags, then the tags are stuffed into + * the end of the data buffer. + */ + if (!data || !tags) + BUG(); + else if (dev->param.inband_tags) { + struct yaffs_packed_tags2_tags_only *pt2tp; + pt2tp = (struct yaffs_packed_tags2_tags_only *)(data + dev->data_bytes_per_chunk); + yaffs_pack_tags2_tags_only(pt2tp, tags); + } else + yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc); + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) + ops.mode = MTD_OOB_AUTO; + ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size; + ops.len = dev->param.total_bytes_per_chunk; + ops.ooboffs = 0; + ops.datbuf = (u8 *)data; + ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr; + retval = mtd->write_oob(mtd, addr, &ops); + +#else + if (!dev->param.inband_tags) { + retval = + mtd->write_ecc(mtd, addr, dev->data_bytes_per_chunk, + &dummy, data, (u8 *) packed_tags_ptr, NULL); + } else { + retval = + mtd->write(mtd, addr, dev->param.total_bytes_per_chunk, &dummy, + data); + } +#endif + + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; +} + +int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, + u8 *data, struct yaffs_ext_tags *tags) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); +#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17)) + struct mtd_oob_ops ops; +#endif + size_t dummy; + int retval = 0; + int local_data = 0; + + loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk; + + struct yaffs_packed_tags2 pt; + + int packed_tags_size = dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt); + void * packed_tags_ptr = dev->param.no_tags_ecc ? (void *) &pt.t: (void *)&pt; + + T(YAFFS_TRACE_MTD, + (TSTR + ("nandmtd2_read_chunk_tags chunk %d data %p tags %p" + TENDSTR), nand_chunk, data, tags)); + + if (dev->param.inband_tags) { + + if (!data) { + local_data = 1; + data = yaffs_get_temp_buffer(dev, __LINE__); + } + + + } + + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) + if (dev->param.inband_tags || (data && !tags)) + retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk, + &dummy, data); + else if (tags) { + ops.mode = MTD_OOB_AUTO; + ops.ooblen = packed_tags_size; + ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size; + ops.ooboffs = 0; + ops.datbuf = data; + ops.oobbuf = yaffs_dev_to_lc(dev)->spare_buffer; + retval = mtd->read_oob(mtd, addr, &ops); + } +#else + if (!dev->param.inband_tags && data && tags) { + + retval = mtd->read_ecc(mtd, addr, dev->data_bytes_per_chunk, + &dummy, data, dev->spare_buffer, + NULL); + } else { + if (data) + retval = + mtd->read(mtd, addr, dev->data_bytes_per_chunk, &dummy, + data); + if (!dev->param.inband_tags && tags) + retval = + mtd->read_oob(mtd, addr, mtd->oobsize, &dummy, + dev->spare_buffer); + } +#endif + + + if (dev->param.inband_tags) { + if (tags) { + struct yaffs_packed_tags2_tags_only *pt2tp; + pt2tp = (struct yaffs_packed_tags2_tags_only *)&data[dev->data_bytes_per_chunk]; + yaffs_unpack_tags2_tags_only(tags, pt2tp); + } + } else { + if (tags) { + memcpy(packed_tags_ptr, yaffs_dev_to_lc(dev)->spare_buffer, packed_tags_size); + yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc); + } + } + + if (local_data) + yaffs_release_temp_buffer(dev, data, __LINE__); + + if (tags && retval == -EBADMSG && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) { + tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED; + dev->n_ecc_unfixed++; + } + if(tags && retval == -EUCLEAN && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) { + tags->ecc_result = YAFFS_ECC_RESULT_FIXED; + dev->n_ecc_fixed++; + } + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; +} + +int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + int retval; + T(YAFFS_TRACE_MTD, + (TSTR("nandmtd2_mark_block_bad %d" TENDSTR), block_no)); + + retval = + mtd->block_markbad(mtd, + block_no * dev->param.chunks_per_block * + dev->param.total_bytes_per_chunk); + + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; + +} + +int nandmtd2_query_block(struct yaffs_dev *dev, int block_no, + enum yaffs_block_state *state, u32 *seq_number) +{ + struct mtd_info *mtd = yaffs_dev_to_mtd(dev); + int retval; + + T(YAFFS_TRACE_MTD, + (TSTR("nandmtd2_query_block %d" TENDSTR), block_no)); + retval = + mtd->block_isbad(mtd, + block_no * dev->param.chunks_per_block * + dev->param.total_bytes_per_chunk); + + if (retval) { + T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR))); + + *state = YAFFS_BLOCK_STATE_DEAD; + *seq_number = 0; + } else { + struct yaffs_ext_tags t; + nandmtd2_read_chunk_tags(dev, block_no * + dev->param.chunks_per_block, NULL, + &t); + + if (t.chunk_used) { + *seq_number = t.seq_number; + *state = YAFFS_BLOCK_STATE_NEEDS_SCANNING; + } else { + *seq_number = 0; + *state = YAFFS_BLOCK_STATE_EMPTY; + } + } + T(YAFFS_TRACE_MTD, + (TSTR("block is bad seq %d state %d" TENDSTR), *seq_number, + *state)); + + if (retval == 0) + return YAFFS_OK; + else + return YAFFS_FAIL; +} + diff --git a/yaffs_vfs_multi.c b/yaffs_vfs_multi.c index fa83cab..6e2f8f8 100644 --- a/yaffs_vfs_multi.c +++ b/yaffs_vfs_multi.c @@ -163,6 +163,7 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) #include "yportenv.h" #include "yaffs_trace.h" #include "yaffs_guts.h" +#include "yaffs_attribs.h" #include "yaffs_linux.h" diff --git a/yaffs_vfs_single.c b/yaffs_vfs_single.c index cb5968f..aa1c15e 100644 --- a/yaffs_vfs_single.c +++ b/yaffs_vfs_single.c @@ -86,6 +86,7 @@ static uint32_t YCALCBLOCKS(uint64_t partition_size, uint32_t block_size) #include "yportenv.h" #include "yaffs_trace.h" #include "yaffs_guts.h" +#include "yaffs_attribs.h" #include "yaffs_linux.h" diff --git a/yaffs_yaffs1.c b/yaffs_yaffs1.c index 3816962..059d125 100644 --- a/yaffs_yaffs1.c +++ b/yaffs_yaffs1.c @@ -17,7 +17,7 @@ #include "yaffs_bitmap.h" #include "yaffs_getblockinfo.h" #include "yaffs_nand.h" - +#include "yaffs_attribs.h" int yaffs1_scan(struct yaffs_dev *dev) { @@ -259,21 +259,7 @@ int yaffs1_scan(struct yaffs_dev *dev) in->variant_type = oh->type; in->yst_mode = oh->yst_mode; -#ifdef CONFIG_YAFFS_WINCE - in->win_atime[0] = oh->win_atime[0]; - in->win_ctime[0] = oh->win_ctime[0]; - in->win_mtime[0] = oh->win_mtime[0]; - in->win_atime[1] = oh->win_atime[1]; - in->win_ctime[1] = oh->win_ctime[1]; - in->win_mtime[1] = oh->win_mtime[1]; -#else - in->yst_uid = oh->yst_uid; - in->yst_gid = oh->yst_gid; - in->yst_atime = oh->yst_atime; - in->yst_mtime = oh->yst_mtime; - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; -#endif + yaffs_load_attribs(in, oh); in->hdr_chunk = chunk; in->serial = tags.serial_number; @@ -284,21 +270,7 @@ int yaffs1_scan(struct yaffs_dev *dev) in->variant_type = oh->type; in->yst_mode = oh->yst_mode; -#ifdef CONFIG_YAFFS_WINCE - in->win_atime[0] = oh->win_atime[0]; - in->win_ctime[0] = oh->win_ctime[0]; - in->win_mtime[0] = oh->win_mtime[0]; - in->win_atime[1] = oh->win_atime[1]; - in->win_ctime[1] = oh->win_ctime[1]; - in->win_mtime[1] = oh->win_mtime[1]; -#else - in->yst_uid = oh->yst_uid; - in->yst_gid = oh->yst_gid; - in->yst_atime = oh->yst_atime; - in->yst_mtime = oh->yst_mtime; - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; -#endif + yaffs_load_attribs(in, oh); in->hdr_chunk = chunk; in->serial = tags.serial_number; diff --git a/yaffs_yaffs2.c b/yaffs_yaffs2.c index d5b167f..debb56d 100644 --- a/yaffs_yaffs2.c +++ b/yaffs_yaffs2.c @@ -20,6 +20,7 @@ #include "yaffs_nand.h" #include "yaffs_getblockinfo.h" #include "yaffs_verify.h" +#include "yaffs_attribs.h" /* * Checkpoints are really no benefit on very small partitions. @@ -1318,24 +1319,8 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) if (oh) { in->yst_mode = oh->yst_mode; -#ifdef CONFIG_YAFFS_WINCE - in->win_atime[0] = oh->win_atime[0]; - in->win_ctime[0] = oh->win_ctime[0]; - in->win_mtime[0] = oh->win_mtime[0]; - in->win_atime[1] = oh->win_atime[1]; - in->win_ctime[1] = oh->win_ctime[1]; - in->win_mtime[1] = oh->win_mtime[1]; -#else - in->yst_uid = oh->yst_uid; - in->yst_gid = oh->yst_gid; - in->yst_atime = oh->yst_atime; - in->yst_mtime = oh->yst_mtime; - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; - + yaffs_load_attribs(in, oh); in->lazy_loaded = 0; - -#endif } else in->lazy_loaded = 1; @@ -1351,21 +1336,7 @@ int yaffs2_scan_backwards(struct yaffs_dev *dev) in->variant_type = oh->type; in->yst_mode = oh->yst_mode; -#ifdef CONFIG_YAFFS_WINCE - in->win_atime[0] = oh->win_atime[0]; - in->win_ctime[0] = oh->win_ctime[0]; - in->win_mtime[0] = oh->win_mtime[0]; - in->win_atime[1] = oh->win_atime[1]; - in->win_ctime[1] = oh->win_ctime[1]; - in->win_mtime[1] = oh->win_mtime[1]; -#else - in->yst_uid = oh->yst_uid; - in->yst_gid = oh->yst_gid; - in->yst_atime = oh->yst_atime; - in->yst_mtime = oh->yst_mtime; - in->yst_ctime = oh->yst_ctime; - in->yst_rdev = oh->yst_rdev; -#endif + yaffs_load_attribs(in, oh); if (oh->shadows_obj > 0) yaffs_handle_shadowed_obj(dev, diff --git a/yportenv.h b/yportenv.h new file mode 120000 index 0000000..b21fbc6 --- /dev/null +++ b/yportenv.h @@ -0,0 +1 @@ +yportenv_multi.h \ No newline at end of file