Re: [Yaffs] [PATCH/RFC] yaffs2: don't write ECCOther if low …

Top Page
Attachments:
Message as email
+ (text/plain)
Delete this message
Reply to this message
Author: Charles Manning
Date:  
To: yaffs
Subject: Re: [Yaffs] [PATCH/RFC] yaffs2: don't write ECCOther if low on OOB space
On Tuesday 13 March 2007 01:57, Vitaly Wool wrote:
> Hello folks,
>
> currently yaffs2 can not be used on some 2k page NAND flashes where the
> controller reserves a lot of OOB space for ECC, due to PackedTags not
> fitting into one page's free OOB space, and on OneNAND, for roughly the
> same reason.
>
> OTOH, on these types of flashes/controllers the ECC capabilities are strong
> enough to just not calculate/save ECC by filesystem (e. g. yaffs). So, the
> patch inlined below just suppresses ECCOther reading/writing/calculation in
> case we anyway don't have space to write it.


This is one wayy to address the problem although it does lose ECC on the tags
if the controller does not provide it. AFAIK (unconfirmed, so I could very
well be wrong) OneNAND etc provide ECC on the data area only and not on the
free oob bytes.

There are some experimental mods that I have added to yaffs which are not yet
checked in. These allow the use of inband tags and store a yaffs_Packedtags2
structure (without ECC on the tags) in the data area. This would give the
benefits of this patch as well as allowing people to use yaffs in
circumstances where they cannot at present (eg. devices with no oob, block
devices such as USB mass storage devices, etc).


>
>  fs/yaffs2/yaffs_mtdif2.c      |   30 +++++++++++++++++++-----------
>  fs/yaffs2/yaffs_packedtags2.c |   22 ++++++++++++----------
>  fs/yaffs2/yaffs_packedtags2.h |    4 ++--
>  3 files changed, 33 insertions(+), 23 deletions(-)

>
> Signed-off-by: Vitaly Wool <>
>
> diff --git a/fs/yaffs2/yaffs_mtdif2.c b/fs/yaffs2/yaffs_mtdif2.c
> index 5a18725..12b5ce3 100644
> --- a/fs/yaffs2/yaffs_mtdif2.c
> +++ b/fs/yaffs2/yaffs_mtdif2.c
> @@ -38,10 +38,14 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
>      size_t dummy;
>  #endif
>      int retval = 0;
> +    /* low on OOB space? write only tags then */
> +    int do_ecc = mtd->oobavail < sizeof(yaffs_PackedTags2) ? 0 : 1;

>
>      loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;

>
>      yaffs_PackedTags2 pt;
> +    void *oob = do_ecc ? (void *)&pt : (void *)&pt.t;
> +    int ooblen = do_ecc ? sizeof(yaffs_PackedTags2) :
> sizeof(yaffs_PackedTags2TagsPart);

>
>      T(YAFFS_TRACE_MTD,
>        (TSTR
> @@ -50,34 +54,34 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya

>
>  #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
>      if (tags)
> -        yaffs_PackTags2(&pt, tags);
> +        yaffs_PackTags2(&pt, tags, do_ecc);
>      else
>          BUG(); /* both tags and data should always be present */

>
>      if (data) {
>          ops.mode = MTD_OOB_AUTO;
> -        ops.ooblen = sizeof(pt);
> +        ops.ooblen = ooblen;
>          ops.len = dev->nDataBytesPerChunk;
>          ops.ooboffs = 0;
>          ops.datbuf = (__u8 *)data;
> -        ops.oobbuf = (void *)&pt;
> +        ops.oobbuf = oob;
>          retval = mtd->write_oob(mtd, addr, &ops);
>      } else
>          BUG(); /* both tags and data should always be present */
>  #else
>      if (tags) {
> -        yaffs_PackTags2(&pt, tags);
> +        yaffs_PackTags2(&pt, tags, do_ecc);
>      }

>
>      if (data && tags) {
>          if (dev->useNANDECC)
>              retval =
>                  mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
> -                       &dummy, data, (__u8 *) & pt, NULL);
> +                       &dummy, data, oob, NULL);
>          else
>              retval =
>                  mtd->write_ecc(mtd, addr, dev->nDataBytesPerChunk,
> -                       &dummy, data, (__u8 *) & pt, NULL);
> +                       &dummy, data, oob, NULL);
>      } else {
>          if (data)
>              retval =
> @@ -86,7 +90,7 @@ int nandmtd2_WriteChunkWithTagsToNAND(ya
>          if (tags)
>              retval =
>                  mtd->write_oob(mtd, addr, mtd->oobsize, &dummy,
> -                       (__u8 *) & pt);
> +                       oob);

>
>      }
>  #endif
> @@ -106,10 +110,14 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
>  #endif
>      size_t dummy;
>      int retval = 0;
> +    /* low on OOB space? write only tags then */
> +    int do_ecc = mtd->oobavail < sizeof(yaffs_PackedTags2) ? 0 : 1;

>
>      loff_t addr = ((loff_t) chunkInNAND) * dev->nDataBytesPerChunk;

>
>      yaffs_PackedTags2 pt;
> +    void *oob = do_ecc ? (void *)&pt : (void *)&pt.t;
> +    int ooblen = do_ecc ? sizeof(yaffs_PackedTags2) :
> sizeof(yaffs_PackedTags2TagsPart);

>
>      T(YAFFS_TRACE_MTD,
>        (TSTR
> @@ -122,8 +130,8 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
>                  &dummy, data);
>      else if (tags) {
>          ops.mode = MTD_OOB_AUTO;
> -        ops.ooblen = sizeof(pt);
> -        ops.len = data ? dev->nDataBytesPerChunk : sizeof(pt);
> +        ops.ooblen = ooblen;
> +        ops.len = data ? dev->nDataBytesPerChunk : ooblen;
>          ops.ooboffs = 0;
>          ops.datbuf = data;
>          ops.oobbuf = dev->spareBuffer;
> @@ -154,10 +162,10 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y
>      }
>  #endif

>
> -    memcpy(&pt, dev->spareBuffer, sizeof(pt));
> +    memcpy(oob, dev->spareBuffer, ooblen);

>
>      if (tags)
> -        yaffs_UnpackTags2(tags, &pt);
> +        yaffs_UnpackTags2(tags, &pt, do_ecc);

>
>      if(tags && retval == -EBADMSG && tags->eccResult ==
> YAFFS_ECC_RESULT_NO_ERROR) tags->eccResult = YAFFS_ECC_RESULT_UNFIXED;
> diff --git a/fs/yaffs2/yaffs_packedtags2.c b/fs/yaffs2/yaffs_packedtags2.c
> index 6860876..55e5149 100644
> --- a/fs/yaffs2/yaffs_packedtags2.c
> +++ b/fs/yaffs2/yaffs_packedtags2.c
> @@ -57,7 +57,8 @@ static void yaffs_DumpTags2(const yaffs_

>
> }
>
> -void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t)
> +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags * t,
> +        int do_ecc)
>  {
>      pt->t.chunkId = t->chunkId;
>      pt->t.sequenceNumber = t->sequenceNumber;
> @@ -93,7 +94,7 @@ void yaffs_PackTags2(yaffs_PackedTags2 *
>      yaffs_DumpTags2(t);

>
>  #ifndef YAFFS_IGNORE_TAGS_ECC
> -    {
> +    if (do_ecc) {
>          yaffs_ECCCalculateOther((unsigned char *)&pt->t,
>                      sizeof(yaffs_PackedTags2TagsPart),
>                      &pt->ecc);
> @@ -101,7 +102,8 @@ void yaffs_PackTags2(yaffs_PackedTags2 *
>  #endif
>  }

>
> -void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt)
> +void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 * pt,
> +        int do_ecc)
>  {

>
>      memset(t, 0, sizeof(yaffs_ExtendedTags));
> @@ -110,12 +112,8 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag

>
>      if (pt->t.sequenceNumber != 0xFFFFFFFF) {
>          /* Page is in use */
> -#ifdef YAFFS_IGNORE_TAGS_ECC
> -        {
> -            t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
> -        }
> -#else
> -        {
> +#ifndef YAFFS_IGNORE_TAGS_ECC
> +        if (do_ecc) {
>              yaffs_ECCOther ecc;
>              int result;
>              yaffs_ECCCalculateOther((unsigned char *)&pt->t,
> @@ -140,8 +138,12 @@ void yaffs_UnpackTags2(yaffs_ExtendedTag
>                  default:
>                      t->eccResult = YAFFS_ECC_RESULT_UNKNOWN;
>              }
> -        }
> +        } else
>  #endif
> +        {
> +            t->eccResult = YAFFS_ECC_RESULT_NO_ERROR;
> +        }
> +
>          t->blockBad = 0;
>          t->chunkUsed = 1;
>          t->objectId = pt->t.objectId;
> diff --git a/fs/yaffs2/yaffs_packedtags2.h b/fs/yaffs2/yaffs_packedtags2.h
> index 7c4a72c..b2e8d6b 100644
> --- a/fs/yaffs2/yaffs_packedtags2.h
> +++ b/fs/yaffs2/yaffs_packedtags2.h
> @@ -33,6 +33,6 @@ typedef struct {
>      yaffs_ECCOther ecc;
>  } yaffs_PackedTags2;

>
> -void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags *
> t); -void yaffs_UnpackTags2(yaffs_ExtendedTags * t, yaffs_PackedTags2 *
> pt); +void yaffs_PackTags2(yaffs_PackedTags2 * pt, const yaffs_ExtendedTags
> * t, int); +void yaffs_UnpackTags2(yaffs_ExtendedTags * t,
> yaffs_PackedTags2 * pt, int); #endif
>
>
>
>
> _______________________________________________
> yaffs mailing list
>
> http://lists.aleph1.co.uk/cgi-bin/mailman/listinfo/yaffs