Hi folks, inlined is the patch that make YAFFS2 work for me with the Linus's git version of the MTD tree. Please note that I've made YAFFS2 structures smaller -- that's just because I wouldn't have succeeded otherwise, I have only 23 bytes spare OOB area out of 2k page. Any comments/remarks are welcome. 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,25 +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) + retval = mtd->write(mtd, addr, dev->nBytesPerChunk, + &dummy, data); + if (tags) { + if (dev->useNANDECC) { + ops.mode = MTD_OOB_AUTO; + ops.len = sizeof(pt); + ops.ooblen = sizeof(pt); + } else { + ops.mode = MTD_OOB_RAW; + ops.len = mtd->oobsize; + ops.ooblen = mtd->oobsize; + } + ops.ooboffs = 0; + ops.datbuf = NULL; + ops.oobbuf = (void *)&pt; + retval = mtd->write_oob(mtd, addr, &ops); } if (retval == 0) @@ -81,6 +81,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 +94,24 @@ int nandmtd2_ReadChunkWithTagsFromNAND(y ("nandmtd2_ReadChunkWithTagsFromNAND chunk %d data %p tags %p" TENDSTR), chunkInNAND, data, tags)); - if (data && tags) { + if (data) + retval = mtd->read(mtd, addr, dev->nBytesPerChunk, + &dummy, data); + + 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 = 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 = 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 = NULL; + 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;