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
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
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
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 \
# 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 \
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
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
#include "yaffs_flashif2.h"
#include "yaffs_guts.h"
+#include "yaffs_fileem2k.h"
+#include "yaffs_packedtags2.h"
+#include "yaffs_tagsvalidity.h"
+
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
-#include "yaffs_fileem2k.h"
-#include "yaffs_packedtags2.h"
-
#define REPORT_ERROR 0
extern int random_seed;
extern int simulate_power_failure;
-static int initialised = 0;
static int remaining_ops;
static int nops_so_far;
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();
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();
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 \
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 \
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 \
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 \
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 \
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
--- /dev/null
+/*
+ * 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@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "yaffs_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;
+}
+
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);
--- /dev/null
+/*
+ * 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@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+
+#include "yaffs_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;
+}
+
+
--- /dev/null
+/*
+ * 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@aleph1.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_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
+
#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
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;
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);
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
*/
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
}
/*------------------------ 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.
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)
{
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;
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) {
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)
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;
/* 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;
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;
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);
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);
--- /dev/null
+/*
+ * 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 <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * 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*/
--- /dev/null
+/*
+ * 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@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* 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;
+}
+
#include "yportenv.h"
#include "yaffs_trace.h"
#include "yaffs_guts.h"
+#include "yaffs_attribs.h"
#include "yaffs_linux.h"
#include "yportenv.h"
#include "yaffs_trace.h"
#include "yaffs_guts.h"
+#include "yaffs_attribs.h"
#include "yaffs_linux.h"
#include "yaffs_bitmap.h"
#include "yaffs_getblockinfo.h"
#include "yaffs_nand.h"
-
+#include "yaffs_attribs.h"
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;
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;
#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.
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;
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,
--- /dev/null
+yportenv_multi.h
\ No newline at end of file