Re: [Yaffs] [PATCH] YAFFS2 to work with current MTD

Top Page
Attachments:
Message as email
+ (text/plain)
+ yaffs2-new.patch (text/x-patch)
Delete this message
Reply to this message
Author: Vitaly Wool
Date:  
To: Karl Olsen
CC: yaffs
Subject: Re: [Yaffs] [PATCH] YAFFS2 to work with current MTD
Hi Karl,

> In the read and write functions, isn't the "if (dev->useNANDECC)"
> unnecessary since the yaffs2 code only supports the MTD ECC?


I thought YAFFS2 was also capable of doing its own ECC. Anyway, I was
aiming to preserve functionality and only make things work with the
curernt MTD stack.

> And in the write function, you write the data and tags using separate mtd
> calls. This means (at least for normal NAND) that the spare area is written
> twice, first with data ecc, and then with tags. Wouldn't something like
> this be better, since write_oob() can write both in one go? Note that tags
> is never NULL.


There definitely is rationale in your words. Though, as far as I
thought, tags might be NULL, but anyway tags were never written
without writing data.
I was trying to do writing both data and tags in one call but I wasn't
successful. Later I discovered that the problem was outside YAFFS and
submitted the patch fixing it linux-mtd, so now everything is ready to
do that in a better way (ie as you propose).

>
> /* Write data and oob area, or only oob area */
> yaffs_PackTags2 (&pt, tags);
> ops.mode = MTD_OOB_AUTO;
> ops.oobbuf = (void *)&pt;
> ops.ooblen = sizeof(pt);
> ops.len = data ? dev->nBytesPerChunk : sizeof(pt);
> ops.ooboffs = 0;
> ops.datbuf = (uint8_t *)data;
> retval = mtd->write_oob (mtd, addr, &ops);


Well, a bit differently, but still... please find the updated patch attached.
Thanks for feedback!

Best regards,
Vitaly

Index: linux-2.6.git/fs/yaffs2/yaffs_ecc.h
===================================================================
--- linux-2.6.git.orig/fs/yaffs2/yaffs_ecc.h
+++ linux-2.6.git/fs/yaffs2/yaffs_ecc.h
@@ -26,10 +26,10 @@
#ifndef __YAFFS_ECC_H__
#define __YAFFS_ECC_H__

-typedef struct {
+typedef struct __attribute__((packed)) {
     unsigned char colParity;
-    unsigned lineParity;
-    unsigned lineParityPrime;
+    unsigned short lineParity;
+    unsigned short lineParityPrime;
 } yaffs_ECCOther;


 void yaffs_ECCCalculate(const unsigned char *data, unsigned char *ecc);
Index: linux-2.6.git/fs/yaffs2/yaffs_fs.c
===================================================================
--- linux-2.6.git.orig/fs/yaffs2/yaffs_fs.c
+++ linux-2.6.git/fs/yaffs2/yaffs_fs.c
@@ -103,7 +103,7 @@ static void yaffs_put_super(struct super
 static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,
                 loff_t * pos);


-static int yaffs_file_flush(struct file *file);
+static int yaffs_file_flush(struct file *file, fl_owner_t id);

 static int yaffs_sync_object(struct file *file, struct dentry *dentry,
                  int datasync);
@@ -137,10 +137,12 @@ static int yaffs_rename(struct inode *ol
             struct inode *new_dir, struct dentry *new_dentry);
 static int yaffs_setattr(struct dentry *dentry, struct iattr *attr);


-static int yaffs_sync_fs(struct super_block *sb);
-static int yaffs_write_super(struct super_block *sb);
+static int yaffs_sync_fs(struct super_block *sb, int wait);
+static void yaffs_write_super(struct super_block *sb);

-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16))
+static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf);
 #else
 static int yaffs_statfs(struct super_block *sb, struct statfs *buf);
@@ -438,7 +440,7 @@ static void yaffs_delete_inode(struct in
     clear_inode(inode);
 }


-static int yaffs_file_flush(struct file *file)
+static int yaffs_file_flush(struct file *file, fl_owner_t id)
 {
     yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry);


@@ -1223,14 +1225,21 @@ static int yaffs_setattr(struct dentry *
     return error;
 }


-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16))
+static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf)
+{
+    yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;
+    struct super_block *sb = dentry->d_sb;
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
 static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)
+{
+    yaffs_Device *dev = yaffs_SuperToDevice(sb);
 #else
 static int yaffs_statfs(struct super_block *sb, struct statfs *buf)
-#endif
 {
-
     yaffs_Device *dev = yaffs_SuperToDevice(sb);
+#endif
+
     T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n"));


     yaffs_GrossLock(dev);
@@ -1287,16 +1296,14 @@ static int yaffs_do_sync_fs(struct super
 }



-static int yaffs_write_super(struct super_block *sb)
+static void yaffs_write_super(struct super_block *sb)
{

     T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_write_super\n"));
-    return 0; /* yaffs_do_sync_fs(sb);*/
-    
 }



-static int yaffs_sync_fs(struct super_block *sb)
+static int yaffs_sync_fs(struct super_block *sb, int wait)
{

     T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_sync_fs\n"));
@@ -1452,7 +1459,7 @@ static struct super_block *yaffs_interna
     T(YAFFS_TRACE_OS, (" writeoob %p\n", mtd->write_oob));
     T(YAFFS_TRACE_OS, (" block_isbad %p\n", mtd->block_isbad));
     T(YAFFS_TRACE_OS, (" block_markbad %p\n", mtd->block_markbad));
-    T(YAFFS_TRACE_OS, (" oobblock %d\n", mtd->oobblock));
+    T(YAFFS_TRACE_OS, (" eccsize %d\n", mtd->eccsize));
     T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize));
     T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize));
     T(YAFFS_TRACE_OS, (" size %d\n", mtd->size));
@@ -1460,14 +1467,14 @@ static struct super_block *yaffs_interna
 #ifdef CONFIG_YAFFS_AUTO_YAFFS2


     if (yaffsVersion == 1 && 
-        mtd->oobblock >= 2048) {
+        mtd->writesize >= 2048) {
         T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));
         yaffsVersion = 2;
     }    

    
     /* Added NCB 26/5/2006 for completeness */
     if (yaffsVersion == 2 && 
-        mtd->oobblock == 512) {
+        mtd->writesize == 512) {
         T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs1\n"));
         yaffsVersion = 1;
     }    
@@ -1481,15 +1488,14 @@ static struct super_block *yaffs_interna
             !mtd->block_markbad ||
             !mtd->read ||
             !mtd->write ||
-            !mtd->write_ecc ||
-            !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
+            !mtd->read_oob || !mtd->write_oob) {
             T(YAFFS_TRACE_ALWAYS,
               ("yaffs: MTD device does not support required "
                "functions\n"));;
             return NULL;
         }


-        if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
+        if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||
             mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) {
             T(YAFFS_TRACE_ALWAYS,
               ("yaffs: MTD device does not have the "
@@ -1501,15 +1507,14 @@ static struct super_block *yaffs_interna
         if (!mtd->erase ||
             !mtd->read ||
             !mtd->write ||
-            !mtd->write_ecc ||
-            !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {
+            !mtd->read_oob || !mtd->write_oob) {
             T(YAFFS_TRACE_ALWAYS,
               ("yaffs: MTD device does not support required "
                "functions\n"));;
             return NULL;
         }


-        if (mtd->oobblock != YAFFS_BYTES_PER_CHUNK ||
+        if (mtd->writesize != YAFFS_BYTES_PER_CHUNK ||
             mtd->oobsize != YAFFS_BYTES_PER_SPARE) {
             T(YAFFS_TRACE_ALWAYS,
               ("yaffs: MTD device does not support have the "
@@ -1560,8 +1565,8 @@ static struct super_block *yaffs_interna
         dev->queryNANDBlock = nandmtd2_QueryNANDBlock;
         dev->spareBuffer = YMALLOC(mtd->oobsize);
         dev->isYaffs2 = 1;
-        dev->nBytesPerChunk = mtd->oobblock;
-        dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;
+        dev->nBytesPerChunk = mtd->writesize;
+        dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;
         nBlocks = mtd->size / mtd->erasesize;


         dev->nCheckpointReservedBlocks = 10;
@@ -1641,6 +1646,16 @@ static int yaffs_internal_read_super_mtd
     return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;
 }


+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16))
+static int yaffs_read_super(struct file_system_type *fs,
+                int flags, const char *dev_name,
+                void *data, struct vfsmount *mnt)
+{
+
+    return get_sb_bdev(fs, flags, dev_name, data,
+               yaffs_internal_read_super_mtd, mnt);
+}
+#else
 static struct super_block *yaffs_read_super(struct file_system_type *fs,
                         int flags, const char *dev_name,
                         void *data)
@@ -1649,6 +1664,7 @@ static struct super_block *yaffs_read_su
     return get_sb_bdev(fs, flags, dev_name, data,
                yaffs_internal_read_super_mtd);
 }
+#endif


 static struct file_system_type yaffs_fs_type = {
     .owner = THIS_MODULE,
@@ -1678,6 +1694,15 @@ static int yaffs2_internal_read_super_mt
     return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;
 }


+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,16))
+static int yaffs2_read_super(struct file_system_type *fs,
+            int flags, const char *dev_name, void *data,
+            struct vfsmount *mnt)
+{
+    return get_sb_bdev(fs, flags, dev_name, data,
+            yaffs2_internal_read_super_mtd, mnt);
+}
+#else
 static struct super_block *yaffs2_read_super(struct file_system_type *fs,
                          int flags, const char *dev_name,
                          void *data)
@@ -1686,6 +1711,7 @@ static struct super_block *yaffs2_read_s
     return get_sb_bdev(fs, flags, dev_name, data,
                yaffs2_internal_read_super_mtd);
 }
+#endif


 static struct file_system_type yaffs2_fs_type = {
     .owner = THIS_MODULE,
Index: linux-2.6.git/fs/yaffs2/yaffs_mtdif.c
===================================================================
--- linux-2.6.git.orig/fs/yaffs2/yaffs_mtdif.c
+++ linux-2.6.git/fs/yaffs2/yaffs_mtdif.c
@@ -26,20 +26,11 @@ const char *yaffs_mtdif_c_version =
 #include "linux/time.h"
 #include "linux/mtd/nand.h"


-static struct nand_oobinfo yaffs_oobinfo = {
-    .useecc = 1,
-    .eccbytes = 6,
-    .eccpos = {8, 9, 10, 13, 14, 15}
-};
-
-static struct nand_oobinfo yaffs_noeccinfo = {
-    .useecc = 0,
-};
-
 int nandmtd_WriteChunkToNAND(yaffs_Device * dev, int chunkInNAND,
                  const __u8 * data, const yaffs_Spare * spare)
 {
     struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+    struct mtd_oob_ops ops;
     size_t dummy;
     int retval = 0;


@@ -47,26 +38,21 @@ int nandmtd_WriteChunkToNAND(yaffs_Devic

     __u8 *spareAsBytes = (__u8 *) spare;


-    if (data && spare) {
+    if (data)
+        retval = mtd->write(mtd, addr, dev->nBytesPerChunk,
+                &dummy, data);
+
+    if (spare) {
         if (dev->useNANDECC)
-            retval =
-                mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
-                       &dummy, data, spareAsBytes,
-                       &yaffs_oobinfo);
+            ops.mode = MTD_OOB_AUTO;
         else
-            retval =
-                mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
-                       &dummy, data, spareAsBytes,
-                       &yaffs_noeccinfo);
-    } else {
-        if (data)
-            retval =
-                mtd->write(mtd, addr, dev->nBytesPerChunk, &dummy,
-                       data);
-        if (spare)
-            retval =
-                mtd->write_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
-                       &dummy, spareAsBytes);
+            ops.mode = MTD_OOB_RAW;
+        ops.len = YAFFS_BYTES_PER_SPARE;
+        ops.ooblen = YAFFS_BYTES_PER_SPARE;
+        ops.datbuf = NULL;
+        ops.ooboffs = 0;
+        ops.oobbuf = spareAsBytes;
+        retval = mtd->write_oob(mtd, addr, &ops);
     }


     if (retval == 0)
@@ -79,6 +65,7 @@ int nandmtd_ReadChunkFromNAND(yaffs_Devi
                   yaffs_Spare * spare)
 {
     struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+    struct mtd_oob_ops ops;
     size_t dummy;
     int retval = 0;


@@ -86,31 +73,21 @@ int nandmtd_ReadChunkFromNAND(yaffs_Devi

     __u8 *spareAsBytes = (__u8 *) spare;


-    if (data && spare) {
-        if (dev->useNANDECC) {    
-            /* Careful, this call adds 2 ints */
-            /* to the end of the spare data.  Calling function */
-            /* should allocate enough memory for spare, */
-            /* i.e. [YAFFS_BYTES_PER_SPARE+2*sizeof(int)]. */
-            retval =
-                mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
-                      &dummy, data, spareAsBytes,
-                      &yaffs_oobinfo);
-        } else {
-            retval =
-                mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
-                      &dummy, data, spareAsBytes,
-                      &yaffs_noeccinfo);
-        }
-    } else {
-        if (data)
-            retval =
-                mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy,
-                      data);
-        if (spare)
-            retval =
-                mtd->read_oob(mtd, addr, YAFFS_BYTES_PER_SPARE,
-                      &dummy, spareAsBytes);
+    if (data)
+        retval = mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy,
+                data);
+
+    if (spare) {
+        if (dev->useNANDECC)
+            ops.mode = MTD_OOB_AUTO;
+        else
+            ops.mode = MTD_OOB_RAW;
+        ops.len = YAFFS_BYTES_PER_SPARE;
+        ops.ooblen = YAFFS_BYTES_PER_SPARE;
+        ops.datbuf = NULL;
+        ops.ooboffs = 0;
+        ops.oobbuf = spareAsBytes;
+        retval = mtd->read_oob(mtd, addr, &ops);
     }


     if (retval == 0)
Index: linux-2.6.git/fs/yaffs2/yaffs_mtdif2.c
===================================================================
--- linux-2.6.git.orig/fs/yaffs2/yaffs_mtdif2.c
+++ linux-2.6.git/fs/yaffs2/yaffs_mtdif2.c
@@ -34,6 +34,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
                       const yaffs_ExtendedTags * tags)
 {
     struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+    struct mtd_oob_ops ops;
     size_t dummy;
     int retval = 0;


@@ -50,26 +51,24 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
         yaffs_PackTags2(&pt, tags);
     }


-    if (data && tags) {
-        if (dev->useNANDECC)
-            retval =
-                mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
-                       &dummy, data, (__u8 *) & pt, NULL);
-        else
-            retval =
-                mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
-                       &dummy, data, (__u8 *) & pt, NULL);
-    } else {
-        if (data)
-            retval =
-                mtd->write(mtd, addr, dev->nBytesPerChunk, &dummy,
-                       data);
-        if (tags)
-            retval =
-                mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
-                       (__u8 *) & pt);
-
-    }
+    if (data && !tags)
+        retval = mtd->write(mtd, addr, dev->nBytesPerChunk,
+                &dummy, data);
+    else if (data) {
+        if (dev->useNANDECC) {
+            ops.mode = MTD_OOB_AUTO;
+            ops.ooblen = sizeof(pt);
+        } else {
+            ops.mode = MTD_OOB_RAW;
+            ops.ooblen = mtd->oobsize;
+        }
+        ops.len = dev->nBytesPerChunk;
+        ops.ooboffs = 0;
+        ops.datbuf = (__u8 *)data;
+        ops.oobbuf = (void *)&pt;
+        retval = mtd->write_oob(mtd, addr, &ops);
+    } else
+        BUG(); /* shouldn't ever write tags without data */


     if (retval == 0)
         return YAFFS_OK;
@@ -81,6 +80,7 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
                        __u8 * data, yaffs_ExtendedTags * tags)
 {
     struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
+    struct mtd_oob_ops ops;
     size_t dummy;
     int retval = 0;


@@ -93,27 +93,23 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
        ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p"
         TENDSTR), chunkInNAND, data, tags));


-    if (data && tags) {
+    if (data && !tags)
+        retval = mtd->read(mtd, addr, dev->nBytesPerChunk,
+                &dummy, data);
+    else if (tags) {
         if (dev->useNANDECC) {
-            retval =
-                mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
-                      &dummy, data, dev->spareBuffer,
-                      NULL);
+            ops.mode = MTD_OOB_AUTO;
+            ops.ooblen = sizeof(pt);
+            ops.len = data ? dev->nBytesPerChunk : sizeof(pt);
         } else {
-            retval =
-                mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
-                      &dummy, data, dev->spareBuffer,
-                      NULL);
+            ops.mode = MTD_OOB_RAW;
+            ops.ooblen = mtd->oobsize;
+            ops.len = data ? dev->nBytesPerChunk : mtd->oobsize;
         }
-    } else {
-        if (data)
-            retval =
-                mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy,
-                      data);
-        if (tags)
-            retval =
-                mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
-                      dev->spareBuffer);
+        ops.ooboffs = 0;
+        ops.datbuf = data;
+        ops.oobbuf = dev->spareBuffer;
+        retval = mtd->read_oob(mtd, addr, &ops);
     }


     memcpy(&pt, dev->spareBuffer, sizeof(pt));
Index: linux-2.6.git/fs/yaffs2/yaffs_packedtags2.h
===================================================================
--- linux-2.6.git.orig/fs/yaffs2/yaffs_packedtags2.h
+++ linux-2.6.git/fs/yaffs2/yaffs_packedtags2.h
@@ -6,14 +6,14 @@
 #include "yaffs_guts.h"
 #include "yaffs_ecc.h"


-typedef struct {
+typedef struct __attribute__((packed)) {
     unsigned sequenceNumber;
-    unsigned objectId;
-    unsigned chunkId;
+    unsigned short objectId;
+    unsigned short chunkId;
     unsigned byteCount;
 } yaffs_PackedTags2TagsPart;


-typedef struct {
+typedef struct __attribute__((packed)) {
     yaffs_PackedTags2TagsPart t;
     yaffs_ECCOther ecc;
 } yaffs_PackedTags2;