X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=yaffs_fs.c;h=d669793752559559e71b3083f781b01927ae5c93;hb=daffb0c61b90abbfc5fd8c335c5b79b0feeff2ab;hp=125d66913b100b019b15cc7f132b4cda178896e6;hpb=dcb63a21673a72cd6d7df32e3c3e9b692e49f586;p=yaffs%2F.git diff --git a/yaffs_fs.c b/yaffs_fs.c index 125d669..d669793 100644 --- a/yaffs_fs.c +++ b/yaffs_fs.c @@ -17,6 +17,12 @@ * Special notes: * >> sb->u.generic_sbp points to the yaffs_Device associated with this superblock * >> inode->u.generic_ip points to the associated yaffs_Object. + * + * + * Acknowledgements: + * * Luc van OostenRyck for numerous patches. + * * Nick Bane for patches marked NCB. + * * Some code bodily lifted from JFFS2. */ @@ -39,16 +45,16 @@ #include "yaffs_guts.h" -#ifdef YAFFS_RAM_ENABLED +#ifdef CONFIG_YAFFS_RAM_ENABLED #include "yaffs_nandemul.h" // 2 MB of RAM for emulation #define YAFFS_RAM_EMULATION_SIZE 0x200000 -#endif // YAFFS_RAM_ENABLED +#endif //CONFIG_YAFFS_RAM_ENABLED -#ifdef YAFFS_MTD_ENABLED +#ifdef CONFIG_YAFFS_MTD_ENABLED #include #include "yaffs_mtdif.h" -#endif //YAFFS_MTD_ENABLED +#endif //CONFIG_YAFFS_MTD_ENABLED #define T(x) printk x @@ -60,8 +66,11 @@ +static void yaffs_put_super(struct super_block *sb); + static ssize_t yaffs_file_read(struct file *f, char *buf, size_t n, loff_t *pos); 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_sync_object(struct file * file, struct dentry *dentry, int datasync); @@ -81,20 +90,35 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf); static void yaffs_read_inode (struct inode *inode); static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent); static void yaffs_put_inode (struct inode *inode); +static int yaffs_readpage(struct file *file, struct page * page); + +static int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to); +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to); + +static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen); +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd); + -//static int yaffs_readpage(struct file*,struct page * -static struct address_space_operations yaffs_address_ops = { -// readpage: yaffs_readpage, -// prepare_write: yaffs_prepare_write, -// commit_write: yaffs_commit_write + + +static struct address_space_operations yaffs_file_address_operations = { + readpage: yaffs_readpage, + prepare_write: yaffs_prepare_write, + commit_write: yaffs_commit_write }; static struct file_operations yaffs_file_operations = { +#ifdef CONFIG_YAFFS_USE_GENERIC_RW + read: generic_file_read, + write: generic_file_write, +#else read: yaffs_file_read, write: yaffs_file_write, -// mmap: generic_file_mmap, +#endif + mmap: generic_file_mmap, + flush: yaffs_file_flush, fsync: yaffs_sync_object, }; @@ -104,11 +128,11 @@ static struct inode_operations yaffs_file_inode_operations = { }; - -static struct file_operations yaffs_dir_operations = { - read: generic_read_dir, - readdir: yaffs_readdir, - fsync: yaffs_sync_object, +struct inode_operations yaffs_symlink_inode_operations = +{ + readlink: yaffs_readlink, + follow_link: yaffs_follow_link, + setattr: yaffs_setattr }; static struct inode_operations yaffs_dir_inode_operations = { @@ -124,16 +148,57 @@ static struct inode_operations yaffs_dir_inode_operations = { setattr: yaffs_setattr, }; +static struct file_operations yaffs_dir_operations = { + read: generic_read_dir, + readdir: yaffs_readdir, + fsync: yaffs_sync_object, +}; + + static struct super_operations yaffs_super_ops = { statfs: yaffs_statfs, read_inode: yaffs_read_inode, put_inode: yaffs_put_inode, + put_super: yaffs_put_super, // read_inode: // remount_fs: // clear_inode: }; + + + +static int yaffs_readlink(struct dentry *dentry, char *buffer, int buflen) +{ + unsigned char *alias; + int ret; + + alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry)); + + if(!alias) + return -ENOMEM; + + ret = vfs_readlink(dentry, buffer, buflen, alias); + kfree(alias); + return ret; +} + +static int yaffs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + unsigned char *alias; + int ret; + alias = yaffs_GetSymlinkAlias(yaffs_DentryToObject(dentry)); + + if(!alias) + return -ENOMEM; + + ret = vfs_follow_link(nd,alias); + kfree(alias); + return ret; +} + + struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,yaffs_Object *obj); /* @@ -149,6 +214,8 @@ static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry) obj = yaffs_FindObjectByName(yaffs_InodeToObject(dir),dentry->d_name.name); + obj = yaffs_GetEquivalentObject(obj); // in case it was a hardlink + if(obj) { T((KERN_DEBUG"yaffs_lookup found %d\n",obj->objectId)); @@ -177,37 +244,126 @@ static struct dentry * yaffs_lookup(struct inode *dir, struct dentry *dentry) static void yaffs_put_inode(struct inode *inode) { T(("yaffs_put_inode: ino %d, count %d\n",(int)inode->i_ino, atomic_read(&inode->i_count))); + + // yaffs_FlushFile(yaffs_InodeToObject(inode)); + } -#ifdef YAFFS_ADDRESS_OPS -static int yaffs_readpage(struct file *file, struct page * page) + +static int yaffs_file_flush(struct file* file) { - T((KERN_DEBUG"yaffs_readpage\n")); + yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry); + + T((KERN_DEBUG"yaffs_file_flush object %d (%s)\n",obj->objectId, + obj->dirty ? "dirty" : "clean")); - // TODO - return 0; + yaffs_FlushFile(obj); + + return 0; } -static int yaffs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) + + +static int yaffs_readpage_nolock(struct file *f, struct page * pg) { - T((KERN_DEBUG"yaffs_prepare_write\n")); + // Lifted from jffs2 + + yaffs_Object *obj; + unsigned char *pg_buf; + int ret; + + T((KERN_DEBUG"yaffs_readpage at %08x, size %08x\n", + pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE)); - //TODO - return 0; + obj = yaffs_DentryToObject(f->f_dentry); + + //down(obj->sem); + + if (!PageLocked(pg)) + PAGE_BUG(pg); + + pg_buf = kmap(pg); + /* FIXME: Can kmap fail? */ + + ret = yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE); + + if(ret >= 0) ret = 0; + + if (ret) { + ClearPageUptodate(pg); + SetPageError(pg); + } else { + SetPageUptodate(pg); + ClearPageError(pg); + } + + flush_dcache_page(pg); + kunmap(pg); + + + + //up(&obj->sem); + + T((KERN_DEBUG"yaffs_readpage done\n")); + return ret; } -static int yaffs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) +static int yaffs_readpage_unlock(struct file *f, struct page *pg) { + int ret = yaffs_readpage_nolock(f,pg); + UnlockPage(pg); + return ret; +} + +static int yaffs_readpage(struct file *f, struct page * pg) +{ + return yaffs_readpage_unlock(f,pg); +} + - struct inode *inode = page->mapping->host; - loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to; +static int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to) +{ - T((KERN_DEBUG"yaffs_commit_write\n")); + T((KERN_DEBUG"yaffs_prepair_write\n")); + if(!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) + return yaffs_readpage_nolock(f,pg); return 0; + +} + +static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to) +{ + + void *addr = page_address(pg) + offset; + loff_t pos = (((loff_t)pg->index) << PAGE_CACHE_SHIFT) + offset; + int nBytes = to - offset; + int nWritten; + + unsigned spos = pos; + unsigned saddr = addr; + + T((KERN_DEBUG"yaffs_commit_write addr %x pos %x nBytes %d\n",saddr,spos,nBytes)); + + nWritten = yaffs_file_write(f,addr, nBytes, &pos); + + if(nWritten != nBytes) + { + T((KERN_DEBUG"yaffs_commit_write not same size nWritten %d nBytes %d\n",nWritten,nBytes)); + SetPageError(pg); + ClearPageUptodate(pg); + } + else + { + SetPageUptodate(pg); + } + + T((KERN_DEBUG"yaffs_commit_write returning %d\n",nWritten)); + + return nWritten; + } -#endif //YAFFS_ADDRESS_OPS static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj) @@ -218,10 +374,9 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj) inode->i_mode = obj->st_mode; inode->i_uid = obj->st_uid; inode->i_gid = obj->st_gid; - inode->i_blksize = YAFFS_BYTES_PER_CHUNK; + inode->i_blksize = inode->i_sb->s_blocksize; inode->i_blocks = 0; - inode->i_rdev = NODEV; - inode->i_mapping->a_ops = &yaffs_address_ops; + inode->i_rdev = obj->st_rdev;; inode->i_atime = obj->st_atime; inode->i_mtime = obj->st_mtime; inode->i_ctime = obj->st_ctime; @@ -233,19 +388,20 @@ static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj) switch (obj->st_mode & S_IFMT) { - default: - // init_special_inode(inode, mode, dev); + default: // fifo, device or socket + init_special_inode(inode, obj->st_mode, obj->st_rdev); break; case S_IFREG: // file inode->i_op = &yaffs_file_inode_operations; inode->i_fop = &yaffs_file_operations; + inode->i_mapping->a_ops = &yaffs_file_address_operations; break; case S_IFDIR: // directory inode->i_op = &yaffs_dir_inode_operations; inode->i_fop = &yaffs_dir_operations; break; case S_IFLNK: // symlink - inode->i_op = &page_symlink_inode_operations; + inode->i_op = &yaffs_symlink_inode_operations; break; } @@ -308,6 +464,7 @@ static ssize_t yaffs_file_read(struct file *f, char *buf, size_t n, loff_t *pos) } + static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_t *pos) { yaffs_Object *obj; @@ -316,21 +473,43 @@ static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n, loff_ obj = yaffs_DentryToObject(f->f_dentry); inode = f->f_dentry->d_inode; - nWritten = yaffs_WriteDataToFile(obj,buf,*pos,n); - ipos = *pos; + + if(!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) + { + ipos = inode->i_size; + } + else + { + ipos = *pos; + } + + + if(!obj) + { + T((KERN_DEBUG"yaffs_file_write: hey obj is null!\n")); + } + else + { + T((KERN_DEBUG"yaffs_file_write about to write writing %d bytes to object %d at %d\n",n,obj->objectId,ipos)); + } + + nWritten = yaffs_WriteDataToFile(obj,buf,ipos,n); + T((KERN_DEBUG"yaffs_file_write writing %d bytes, %d written at %d\n",n,nWritten,ipos)); if(nWritten > 0) { - *pos += nWritten; - ipos = *pos; - if(*pos > inode->i_size) + ipos += nWritten; + *pos = ipos; + if(ipos > inode->i_size) { - inode->i_size = *pos; - T((KERN_DEBUG"yaffs_file_write size updated to %d\n",ipos)); + inode->i_size = ipos; + inode->i_blocks = (ipos + inode->i_blksize - 1)/ inode->i_blksize; + + T((KERN_DEBUG"yaffs_file_write size updated to %d bytes, %d blocks\n",ipos,inode->i_blocks)); } } - return nWritten; + return nWritten != n ? -ENOSPC : nWritten; } @@ -434,13 +613,15 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int d return -EPERM; } - T(("yaffs_mknod: making oject for %s, mode %x\n", - dentry->d_name.name, mode)); + T(("yaffs_mknod: making oject for %s, mode %x dev %x\n", + dentry->d_name.name, mode,dev)); switch (mode & S_IFMT) { default: - + // Special (socket, fifo, device...) + T((KERN_DEBUG"yaffs_mknod: making special\n")); + obj = yaffs_MknodSpecial(parent,dentry->d_name.name,mode,current->uid, current->gid,dev); break; case S_IFREG: // file T((KERN_DEBUG"yaffs_mknod: making file\n")); @@ -452,16 +633,13 @@ static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode, int d break; case S_IFLNK: // symlink T((KERN_DEBUG"yaffs_mknod: making file\n")); - obj = NULL; // Todo + obj = NULL; // Do we ever get here? break; } if(obj) { inode = yaffs_get_inode(dir->i_sb, mode, dev, obj); - -// did not fix dir bug if((mode & S_IFMT) == S_IFDIR) atomic_inc(&inode->i_count); - d_instantiate(dentry, inode); T((KERN_DEBUG"yaffs_mknod created object %d count = %d\n",obj->objectId,atomic_read(&inode->i_count))); error = 0; @@ -501,7 +679,7 @@ static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode) static int yaffs_unlink(struct inode * dir, struct dentry *dentry) { - T((KERN_DEBUG"yaffs_unlink\n")); + T((KERN_DEBUG"yaffs_unlink %d:%s\n",dir->i_ino,dentry->d_name.name)); if(yaffs_Unlink(yaffs_InodeToObject(dir),dentry->d_name.name) == YAFFS_OK) { @@ -515,36 +693,52 @@ static int yaffs_unlink(struct inode * dir, struct dentry *dentry) /* - * Link a file.. + * Create a link... */ static int yaffs_link(struct dentry *old_dentry, struct inode * dir, struct dentry * dentry) { struct inode *inode = old_dentry->d_inode; + yaffs_Object *obj = NULL; + yaffs_Object *link=NULL; T((KERN_DEBUG"yaffs_link\n")); - return -EPERM; //Todo + obj = yaffs_InodeToObject(inode); - - if (S_ISDIR(inode->i_mode)) - return -EPERM; - - - return 0; + link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj); + + if(link) + { + return 0; + } + + + return -EPERM; } static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname) { - int error; + yaffs_Object *obj; T((KERN_DEBUG"yaffs_symlink\n")); - - return -ENOMEM; //Todo + obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, + S_IFLNK | S_IRWXUGO, current->uid, current->gid, + symname); - error = yaffs_mknod(dir, dentry, S_IFLNK | S_IRWXUGO, 0); - return error; + if(obj) + { + T((KERN_DEBUG"symlink created OK\n")); + return 0; + } + else + { + T((KERN_DEBUG"symlink not created\n")); + + } + + return -ENOMEM; } static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync) @@ -580,7 +774,7 @@ static int yaffs_setattr(struct dentry *dentry, struct iattr *attr) struct inode *inode = dentry->d_inode; int error; - T((KERN_DEBUG"yaffs_setattr\n")); + T((KERN_DEBUG"yaffs_setattr of object %d\n",yaffs_InodeToObject(inode)->objectId)); if((error = inode_change_ok(inode,attr)) == 0) { @@ -604,12 +798,15 @@ static int yaffs_statfs(struct super_block *sb, struct statfs *buf) T((KERN_DEBUG"yaffs_statfs\n")); buf->f_type = YAFFS_MAGIC; - buf->f_bsize = YAFFS_BYTES_PER_CHUNK; + buf->f_bsize = sb->s_blocksize; buf->f_namelen = 255; - buf->f_blocks = yaffs_SuperToDevice(sb)->nBlocks * YAFFS_CHUNKS_PER_BLOCK; + buf->f_blocks = yaffs_SuperToDevice(sb)->nBlocks * YAFFS_CHUNKS_PER_BLOCK/ + (sb->s_blocksize/YAFFS_BYTES_PER_CHUNK); buf->f_files = 0; buf->f_ffree = 0; - buf->f_bavail = yaffs_GetNumberOfFreeChunks(yaffs_SuperToDevice(sb)); + buf->f_bfree = yaffs_GetNumberOfFreeChunks(yaffs_SuperToDevice(sb))/ + (sb->s_blocksize/YAFFS_BYTES_PER_CHUNK); + buf->f_bavail = buf->f_bfree; return 0; } @@ -626,16 +823,42 @@ static void yaffs_read_inode (struct inode *inode) } +static void yaffs_put_super(struct super_block *sb) +{ + yaffs_Device *dev = yaffs_SuperToDevice(sb); + + if(dev->putSuperFunc) + { + dev->putSuperFunc(sb); + } + yaffs_Deinitialise(dev); + kfree(dev); +} + + +#ifdef CONFIG_YAFFS_MTD_ENABLED + +static void yaffs_MTDPutSuper(struct super_block *sb) +{ + + struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; + + if(mtd->sync) + { + mtd->sync(mtd); + } + + put_mtd_device(mtd); +} + +#endif + static struct super_block *yaffs_internal_read_super(int useRam, struct super_block * sb, void * data, int silent) { struct inode * inode; struct dentry * root; yaffs_Device *dev; - - T(("yaffs_read_super: %s\n", useRam ? "RAM" : "MTD")); - sb->s_blocksize = YAFFS_BYTES_PER_CHUNK; - sb->s_blocksize_bits = YAFFS_CHUNK_SIZE_SHIFT; sb->s_magic = YAFFS_MAGIC; sb->s_op = &yaffs_super_ops; @@ -649,11 +872,26 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl printk(KERN_INFO"yaffs: dev is %d name is \"%s\"\n", sb->s_dev, kdevname(sb->s_dev)); + +#ifdef CONFIG_YAFFS_USE_CHUNK_SIZE + sb->s_blocksize = YAFFS_BYTES_PER_CHUNK; + sb->s_blocksize_bits = YAFFS_CHUNK_SIZE_SHIFT; +#else + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; +#endif + T(("yaffs_read_super: %s block size %d\n", useRam ? "RAM" : "MTD",sb->s_blocksize)); + +#ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY + T(("yaffs: Write verification disabled. All guarantees null and void\n"); +#endif + + if(useRam) { -#if YAFFS_RAM_ENABLED +#ifdef CONFIG_YAFFS_RAM_ENABLED // Set the yaffs_Device up for ram emulation sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL); @@ -675,12 +913,13 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl dev->readChunkFromNAND = nandemul_ReadChunkFromNAND; dev->eraseBlockInNAND = nandemul_EraseBlockInNAND; dev->initialiseNAND = nandemul_InitialiseNAND; + #endif } else { -#ifdef YAFFS_MTD_ENABLED +#ifdef CONFIG_YAFFS_MTD_ENABLED struct mtd_info *mtd; printk(KERN_DEBUG "yaffs: Attempting MTD mount on %u.%u, \"%s\"\n", @@ -755,6 +994,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND; dev->initialiseNAND = nandmtd_InitialiseNAND; + dev->putSuperFunc = yaffs_MTDPutSuper; #endif } @@ -785,7 +1025,7 @@ static struct super_block *yaffs_internal_read_super(int useRam, struct super_bl return sb; } -#ifdef YAFFS_MTD_ENABLED +#ifdef CONFIG_YAFFS_MTD_ENABLED static struct super_block *yaffs_read_super(struct super_block * sb, void * data, int silent) { return yaffs_internal_read_super(0,sb,data,silent); @@ -794,7 +1034,7 @@ static struct super_block *yaffs_read_super(struct super_block * sb, void * data static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV); #endif -#ifdef YAFFS_RAM_ENABLED +#ifdef CONFIG_YAFFS_RAM_ENABLED static struct super_block *yaffs_ram_read_super(struct super_block * sb, void * data, int silent) { @@ -802,7 +1042,7 @@ static struct super_block *yaffs_ram_read_super(struct super_block * sb, void * } static DECLARE_FSTYPE(yaffs_ram_fs_type, "yaffsram", yaffs_ram_read_super, FS_SINGLE); -#endif // YAFFS_RAM_ENABLED +#endif // CONFIG_YAFFS_RAM_ENABLED static struct proc_dir_entry *my_proc_entry; @@ -837,6 +1077,13 @@ static int __init init_yaffs_fs(void) int error = 0; printk(KERN_DEBUG "yaffs " __DATE__ " " __TIME__ " Initialisation\n"); +#ifdef CONFIG_YAFFS_USE_GENERIC_RW + printk(KERN_DEBUG "yaffs is using generic read/write (caching)\n"); +#else + printk(KERN_DEBUG "yaffs is using direct read/write (uncached)\n"); +#endif + + /* Install the proc_fs entry */ my_proc_entry = create_proc_read_entry("yaffs", S_IRUGO | S_IFREG, @@ -848,24 +1095,24 @@ static int __init init_yaffs_fs(void) return -ENOMEM; } -#ifdef YAFFS_RAM_ENABLED +#ifdef CONFIG_YAFFS_RAM_ENABLED error = register_filesystem(&yaffs_ram_fs_type); if(error) { return error; } -#endif //YAFFS_RAM_ENABLED +#endif //CONFIG_YAFFS_RAM_ENABLED -#ifdef YAFFS_MTD_ENABLED +#ifdef CONFIG_YAFFS_MTD_ENABLED error = register_filesystem(&yaffs_fs_type); if(error) { -#ifdef YAFFS_RAM_ENABLED +#ifdef CONFIG_YAFFS_RAM_ENABLED unregister_filesystem(&yaffs_ram_fs_type); -#endif //YAFFS_RAM_ENABLED +#endif //CONFIG_YAFFS_RAM_ENABLED } -#endif // YAFFS_MTD_ENABLED +#endif // CONFIG_YAFFS_MTD_ENABLED return error; } @@ -876,12 +1123,10 @@ static void __exit exit_yaffs_fs(void) remove_proc_entry("yaffs",&proc_root); -#ifdef YAFFS_RAM_ENABLED -// NCB unregister_filesystem(&yaffs_fs_type); +#ifdef CONFIG_YAFFS_RAM_ENABLED unregister_filesystem(&yaffs_ram_fs_type); #endif -#ifdef YAFFS_MTD_ENABLED -// NCB unregister_filesystem(&yaffs_ram_fs_type); +#ifdef CONFIG_YAFFS_MTD_ENABLED unregister_filesystem(&yaffs_fs_type); #endif