📄 yaffs_fs.c
字号:
YAFFS_OK) { error = 0; } else { error = -EPERM; } yaffs_GrossUnlock(dev); if (!error) error = inode_setattr(inode, attr); } return error;}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))static int yaffs_statfs(struct super_block *sb, struct kstatfs *buf)#elsestatic int yaffs_statfs(struct super_block *sb, struct statfs *buf)#endif{ yaffs_Device *dev = yaffs_SuperToDevice(sb); T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_statfs\n")); yaffs_GrossLock(dev); buf->f_type = YAFFS_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_namelen = 255; if (sb->s_blocksize > dev->nBytesPerChunk) { buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * dev->nChunksPerBlock / (sb->s_blocksize / dev->nBytesPerChunk); buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize / dev->nBytesPerChunk); } else { buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * dev->nChunksPerBlock * (dev->nBytesPerChunk / sb->s_blocksize); buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev) * (dev->nBytesPerChunk / sb->s_blocksize); } buf->f_files = 0; buf->f_ffree = 0; buf->f_bavail = buf->f_bfree; yaffs_GrossUnlock(dev); return 0;}static void yaffs_read_inode(struct inode *inode){ /* NB This is called as a side effect of other functions, but * we had to release the lock to prevent deadlocks, so * need to lock again. */ yaffs_Object *obj; yaffs_Device *dev = yaffs_SuperToDevice(inode->i_sb); T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_read_inode for %d\n", (int)inode->i_ino)); yaffs_GrossLock(dev); obj = yaffs_FindObjectByNumber(dev, inode->i_ino); yaffs_FillInodeFromObject(inode, obj); yaffs_GrossUnlock(dev);}static LIST_HEAD(yaffs_dev_list);static void yaffs_put_super(struct super_block *sb){ yaffs_Device *dev = yaffs_SuperToDevice(sb); yaffs_GrossLock(dev); if (dev->putSuperFunc) { dev->putSuperFunc(sb); } yaffs_Deinitialise(dev); yaffs_GrossUnlock(dev); /* we assume this is protected by lock_kernel() in mount/umount */ list_del(&dev->devList); kfree(dev);}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);}static struct super_block *yaffs_internal_read_super(int yaffsVersion, struct super_block *sb, void *data, int silent){ int nBlocks; struct inode *inode = NULL; struct dentry *root; yaffs_Device *dev = 0; char devname_buf[BDEVNAME_SIZE + 1]; struct mtd_info *mtd; int err; sb->s_magic = YAFFS_MAGIC; sb->s_op = &yaffs_super_ops; if (!sb) printk(KERN_INFO "yaffs: sb is NULL\n"); else if (!sb->s_dev) printk(KERN_INFO "yaffs: sb->s_dev is NULL\n"); else if (!yaffs_devname(sb, devname_buf)) printk(KERN_INFO "yaffs: devname is NULL\n"); else printk(KERN_INFO "yaffs: dev is %d name is \"%s\"\n", sb->s_dev, yaffs_devname(sb, devname_buf)); sb->s_blocksize = PAGE_CACHE_SIZE; sb->s_blocksize_bits = PAGE_CACHE_SHIFT; T(YAFFS_TRACE_OS, ("yaffs_read_super: Using yaffs%d\n", yaffsVersion)); T(YAFFS_TRACE_OS, ("yaffs_read_super: block size %d\n", (int)(sb->s_blocksize)));#ifdef CONFIG_YAFFS_DISABLE_WRITE_VERIFY T(YAFFS_TRACE_OS, ("yaffs: Write verification disabled. All guarantees " "null and void\n"));#endif T(YAFFS_TRACE_ALWAYS, ("yaffs: Attempting MTD mount on %u.%u, " "\"%s\"\n", MAJOR(sb->s_dev), MINOR(sb->s_dev), yaffs_devname(sb, devname_buf))); /* Check it's an mtd device..... */ if (MAJOR(sb->s_dev) != MTD_BLOCK_MAJOR) { return NULL; /* This isn't an mtd device */ } /* Get the device */ mtd = get_mtd_device(NULL, MINOR(sb->s_dev)); if (!mtd) { T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device #%u doesn't appear to exist\n", MINOR(sb->s_dev))); return NULL; } /* Check it's NAND */ if (mtd->type != MTD_NANDFLASH) { T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device is not NAND it's type %d\n", mtd->type)); return NULL; } T(YAFFS_TRACE_OS, (" erase %p\n", mtd->erase)); T(YAFFS_TRACE_OS, (" read %p\n", mtd->read)); T(YAFFS_TRACE_OS, (" write %p\n", mtd->write)); T(YAFFS_TRACE_OS, (" readoob %p\n", mtd->read_oob)); 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, (" oobsize %d\n", mtd->oobsize)); T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize)); T(YAFFS_TRACE_OS, (" size %d\n", mtd->size)); #ifdef CONFIG_YAFFS_AUTO_YAFFS2 if (yaffsVersion == 1 && mtd->oobblock >= 2048) { T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n")); yaffsVersion = 2; } #endif if (yaffsVersion == 2) { /* Check for version 2 style functions */ if (!mtd->erase || !mtd->block_isbad || !mtd->block_markbad || !mtd->read || !mtd->write || !mtd->write_ecc || !mtd->read_ecc || !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 || mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) { T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not support have the " "right page sizes\n")); return NULL; } } else { /* Check for V1 style functions */ if (!mtd->erase || !mtd->read || !mtd->write || !mtd->write_ecc || !mtd->read_ecc || !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 || mtd->oobsize != YAFFS_BYTES_PER_SPARE) { T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not support have the " "right page sizes\n")); return NULL; } } /* OK, so if we got here, we have an MTD that's NAND and looks * like it has the right capabilities * Set the yaffs_Device up for mtd */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) sb->s_fs_info = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);#else sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device), GFP_KERNEL);#endif if (!dev) { /* Deep shit could not allocate device structure */ T(YAFFS_TRACE_ALWAYS, ("yaffs_read_super: Failed trying to allocate " "yaffs_Device. \n")); return NULL; } memset(dev, 0, sizeof(yaffs_Device)); dev->genericDevice = mtd; dev->name = mtd->name; /* Set up the memory size parameters.... */ nBlocks = mtd->size / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); dev->startBlock = 0; dev->endBlock = nBlocks - 1; dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK; dev->nReservedBlocks = 5; dev->nShortOpCaches = 10; /* Enable short op caching */ /* ... and the functions. */ if (yaffsVersion == 2) { dev->writeChunkWithTagsToNAND = nandmtd2_WriteChunkWithTagsToNAND; dev->readChunkWithTagsFromNAND = nandmtd2_ReadChunkWithTagsFromNAND; dev->markNANDBlockBad = nandmtd2_MarkNANDBlockBad; dev->queryNANDBlock = nandmtd2_QueryNANDBlock; dev->spareBuffer = YMALLOC(mtd->oobsize); dev->isYaffs2 = 1; dev->nBytesPerChunk = mtd->oobblock; dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock; nBlocks = mtd->size / mtd->erasesize; dev->startBlock = 0; dev->endBlock = nBlocks - 1; } else { dev->writeChunkToNAND = nandmtd_WriteChunkToNAND; dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND; dev->isYaffs2 = 0; } /* ... and common functions */ dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND; dev->initialiseNAND = nandmtd_InitialiseNAND; dev->putSuperFunc = yaffs_MTDPutSuper;#ifndef CONFIG_YAFFS_DOES_ECC dev->useNANDECC = 1;#endif#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES dev->wideTnodesDisabled = 1;#endif /* we assume this is protected by lock_kernel() in mount/umount */ list_add_tail(&dev->devList, &yaffs_dev_list); init_MUTEX(&dev->grossLock); yaffs_GrossLock(dev); err = yaffs_GutsInitialise(dev); T(YAFFS_TRACE_OS, ("yaffs_read_super: guts initialised %s\n", (err == YAFFS_OK) ? "OK" : "FAILED")); /* Release lock before yaffs_get_inode() */ yaffs_GrossUnlock(dev); /* Create root inode */ if (err == YAFFS_OK) inode = yaffs_get_inode(sb, S_IFDIR | 0755, 0, yaffs_Root(dev)); if (!inode) return NULL; inode->i_op = &yaffs_dir_inode_operations; inode->i_fop = &yaffs_dir_operations; T(YAFFS_TRACE_OS, ("yaffs_read_super: got root inode\n")); root = d_alloc_root(inode); T(YAFFS_TRACE_OS, ("yaffs_read_super: d_alloc_root done\n")); if (!root) { iput(inode); return NULL; } sb->s_root = root; T(YAFFS_TRACE_OS, ("yaffs_read_super: done\n")); return sb;}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))static int yaffs_internal_read_super_mtd(struct super_block *sb, void *data, int silent){ return yaffs_internal_read_super(1, sb, data, silent) ? 0 : -EINVAL;}static struct super_block *yaffs_read_super(struct file_system_type *fs, int flags, const char *dev_name, void *data){ return get_sb_bdev(fs, flags, dev_name, data, yaffs_internal_read_super_mtd);}static struct file_system_type yaffs_fs_type = { .owner = THIS_MODULE, .name = "yaffs", .get_sb = yaffs_read_super, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV,};#elsestatic struct super_block *yaffs_read_super(struct super_block *sb, void *data, int silent){ return yaffs_internal_read_super(1, sb, data, silent);}static DECLARE_FSTYPE(yaffs_fs_type, "yaffs", yaffs_read_super, FS_REQUIRES_DEV);#endif#ifdef CONFIG_YAFFS_YAFFS2#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))static int yaffs2_internal_read_super_mtd(struct super_block *sb, void *data, int silent){ return yaffs_internal_read_super(2, sb, data, silent) ? 0 : -EINVAL;}static struct super_block *yaffs2_read_super(struct file_system_type *fs, int flags, const char *dev_name, void *data){ return get_sb_bdev(fs, flags, dev_name, data, yaffs2_internal_read_super_mtd);}static struct file_system_type yaffs2_fs_type = { .owner = THIS_MODULE, .name = "yaffs2", .get_sb = yaffs2_read_super, .kill_sb = kill_block_super, .fs_flags = FS_REQUIRES_DEV,};#elsestatic struct super_block *yaffs2_read_super(struct super_block *sb, void *data, int silent){ return yaffs_internal_read_super(2, sb, data, silent);}static DECLARE_FSTYPE(yaffs2_fs_type, "yaffs2", yaffs2_read_super, FS_REQUIRES_DEV);#endif#endif /* CONFIG_YAFFS_YAFFS2 */static struct proc_dir_entry *my_proc_entry;static char *yaffs_dump_dev(char *buf, yaffs_Device * dev){ buf += sprintf(buf, "startBlock......... %d\n", dev->startBlock); buf += sprintf(buf, "endBlock........... %d\n", dev->endBlock); buf += sprintf(buf, "chunkGroupBits..... %d\n", dev->chunkGroupBits); buf += sprintf(buf, "chunkGroupSize..... %d\n", dev->chunkGroupSize); buf += sprintf(buf, "nErasedBlocks...... %d\n", dev->nErasedBlocks); buf += sprintf(buf, "nTnodesCreated..... %d\n", dev->nTnodesCreated); buf += sprintf(buf, "nFreeTnodes........ %d\n", dev->nFreeTnodes); buf += sprintf(buf, "nObjectsCreated.... %d\n", dev->nObjectsCreated); buf += sprintf(buf, "nFreeObjects....... %d\n", dev->nFreeObjects); buf += sprintf(buf, "nFreeChunks........ %d\n", dev->nFreeChunks); buf += sprintf(buf, "nPageWrites........ %d\n", dev->nPageWrites); buf += sprintf(buf, "nPageReads......... %d\n", dev->nPageReads); buf += sprintf(buf, "nBlockErasures..... %d\n", dev->nBlockErasures); buf += sprintf(buf, "nGCCopies.......... %d\n", dev->nGCCopies); buf += sprintf(buf, "garbageCollections. %d\n", dev->garbageCollections); buf += sprintf(buf, "passiveGCs......... %d\n", dev->passiveGarbageCollections); buf += sprintf(buf, "nRetriedWrites..... %d\n", dev->nRetriedWrites); buf += sprintf(buf, "nRetireBlocks...... %d\n", dev->nRetiredBlocks); buf += sprintf(buf, "eccFixed........... %d\n", dev->eccFixed); buf += sprintf(buf, "eccUnfixed......... %d\n", dev->eccUnfixed); buf += sprintf(buf, "tagsEccFixed....... %d\n", dev->tagsEccFixed); buf += sprintf(buf, "tagsEccUnfixed..... %d\n", dev->tagsEccUnfixed); buf += sprintf(buf, "cacheHits.......... %d\n", dev->cacheHits); buf += sprintf(buf, "nDeletedFiles...... %d\n", dev->nDeletedFiles); buf += sprintf(buf, "nUnlinkedFiles..... %d\n", dev->nUnlinkedFiles); buf += sprintf(buf, "nBackgroudDeletions %d\n", dev->nBackgroundDeletions); buf += sprintf(buf, "useNANDECC......... %d\n", dev->useNANDECC); buf += sprintf(buf, "isYaffs2........... %d\n", dev->isYaffs2); return buf;}static int yaffs_proc_read(char *page, char **start, off_t offset, int count, int *eof, void *data){ struct list_head *item; char *buf = page; int step = offset; int n = 0; /* Get proc_file_read() to step 'offset' by one on each sucessive call. * We use 'offset' (*ppos) to indicate where we are in devList. * This also assumes the user has posted a read buffer large * enough to hold the complete output; but that's life in /proc. */ *(int *)start = 1; /* Print header first */ if (step == 0) { buf += sprintf(buf, "YAFFS built:" __DATE__ " " __TIME__ "\n%s\n%s\n", yaffs_fs_c_version, yaffs_guts_c_version); } /* hold lock_kernel while traversing yaffs_dev_list */ lock_kernel(); /* Locate and print the Nth entry. Order N-squared but N is small. */ list_for_each(item, &yaffs_dev_list) { yaffs_Device *dev = list_entry(item, yaffs_Device, devList); if (n < step) { n++; continue; } buf += sprintf(buf, "\nDevice %d \"%s\"\n", n, dev->name); buf = yaffs_dump_dev(buf, dev); break; } unlock_kernel(); return buf - page < count ? buf - page : count;}/* Stuff to handle installation of file systems */struct file_system_to_install { struct file_system_type *fst; int installed;};static struct file_system_to_install fs_to_install[] = {//#ifdef CONFIG_YAFFS_YAFFS1 {&yaffs_fs_type, 0},//#endif//#ifdef CONFIG_YAFFS_YAFFS2 {&yaffs2_fs_type, 0},//#endif {NULL, 0}};static int __init init_yaffs_fs(void){ int error = 0; struct file_system_to_install *fsinst; T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__ " Installing. \n")); /* Install the proc_fs entry */ my_proc_entry = create_proc_read_entry("yaffs", S_IRUGO | S_IFREG, &proc_root, yaffs_proc_read, NULL); if (!my_proc_entry) { return -ENOMEM; } /* Now add the file system entries */ fsinst = fs_to_install; while (fsinst->fst && !error) { error = register_filesystem(fsinst->fst); if (!error) { fsinst->installed = 1; } fsinst++; } /* Any errors? uninstall */ if (error) { fsinst = fs_to_install; while (fsinst->fst) { if (fsinst->installed) { unregister_filesystem(fsinst->fst); fsinst->installed = 0; } fsinst++; } } return error;}static void __exit exit_yaffs_fs(void){ struct file_system_to_install *fsinst; T(YAFFS_TRACE_ALWAYS, ("yaffs " __DATE__ " " __TIME__ " removing. \n")); remove_proc_entry("yaffs", &proc_root); fsinst = fs_to_install; while (fsinst->fst) { if (fsinst->installed) { unregister_filesystem(fsinst->fst); fsinst->installed = 0; } fsinst++; }}module_init(init_yaffs_fs)module_exit(exit_yaffs_fs)MODULE_DESCRIPTION("YAFFS2 - a NAND specific flash file system");MODULE_AUTHOR("Charles Manning, Aleph One Ltd., 2002,2003,2004");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -