📄 yaffs_fs.c
字号:
dev->inbandTags = options.inband_tags; /* ... 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;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) dev->totalBytesPerChunk = mtd->writesize; dev->nChunksPerBlock = mtd->erasesize / mtd->writesize;#else dev->totalBytesPerChunk = mtd->oobblock; dev->nChunksPerBlock = mtd->erasesize / mtd->oobblock;#endif nBlocks = YCALCBLOCKS(mtd->size, mtd->erasesize); dev->startBlock = 0; dev->endBlock = nBlocks - 1; } else {#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) /* use the MTD interface in yaffs_mtdif1.c */ dev->writeChunkWithTagsToNAND = nandmtd1_WriteChunkWithTagsToNAND; dev->readChunkWithTagsFromNAND = nandmtd1_ReadChunkWithTagsFromNAND; dev->markNANDBlockBad = nandmtd1_MarkNANDBlockBad; dev->queryNANDBlock = nandmtd1_QueryNANDBlock;#else dev->writeChunkToNAND = nandmtd_WriteChunkToNAND; dev->readChunkFromNAND = nandmtd_ReadChunkFromNAND;#endif dev->isYaffs2 = 0; } /* ... and common functions */ dev->eraseBlockInNAND = nandmtd_EraseBlockInNAND; dev->initialiseNAND = nandmtd_InitialiseNAND; dev->putSuperFunc = yaffs_MTDPutSuper; dev->superBlock = (void *)sb; dev->markSuperBlockDirty = yaffs_MarkSuperBlockDirty;#ifndef CONFIG_YAFFS_DOES_ECC dev->useNANDECC = 1;#endif#ifdef CONFIG_YAFFS_DISABLE_WIDE_TNODES dev->wideTnodesDisabled = 1;#endif dev->skipCheckpointRead = options.skip_checkpoint_read; dev->skipCheckpointWrite = options.skip_checkpoint_write; /* we assume this is protected by lock_kernel() in mount/umount */ ylist_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; sb->s_dirt = !dev->isCheckpointed; T(YAFFS_TRACE_ALWAYS, ("yaffs_read_super: isCheckpointed %d\n", dev->isCheckpointed)); 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;}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))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);}#elsestatic 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);}#endifstatic 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;}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))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);}#elsestatic 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);}#endifstatic 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, "totalBytesPerChunk. %d\n", dev->totalBytesPerChunk); buf += sprintf(buf, "nDataBytesPerChunk. %d\n", dev->nDataBytesPerChunk); 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, "nReservedBlocks.... %d\n", dev->nReservedBlocks); buf += sprintf(buf, "blocksInCheckpoint. %d\n", dev->blocksInCheckpoint); 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, "nShortOpCaches..... %d\n", dev->nShortOpCaches); 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); buf += sprintf(buf, "inbandTags......... %d\n", dev->inbandTags); return buf;}static int yaffs_proc_read(char *page, char **start, off_t offset, int count, int *eof, void *data){ struct ylist_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. */ ylist_for_each(item, &yaffs_dev_list) { yaffs_Device *dev = ylist_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;}/** * Set the verbosity of the warnings and error messages. * * Note that the names can only be a..z or _ with the current code. */static struct { char *mask_name; unsigned mask_bitfield;} mask_flags[] = { {"allocate", YAFFS_TRACE_ALLOCATE}, {"always", YAFFS_TRACE_ALWAYS}, {"bad_blocks", YAFFS_TRACE_BAD_BLOCKS}, {"buffers", YAFFS_TRACE_BUFFERS}, {"bug", YAFFS_TRACE_BUG}, {"checkpt", YAFFS_TRACE_CHECKPOINT}, {"deletion", YAFFS_TRACE_DELETION}, {"erase", YAFFS_TRACE_ERASE}, {"error", YAFFS_TRACE_ERROR}, {"gc_detail", YAFFS_TRACE_GC_DETAIL}, {"gc", YAFFS_TRACE_GC}, {"mtd", YAFFS_TRACE_MTD}, {"nandaccess", YAFFS_TRACE_NANDACCESS}, {"os", YAFFS_TRACE_OS}, {"scan_debug", YAFFS_TRACE_SCAN_DEBUG}, {"scan", YAFFS_TRACE_SCAN}, {"tracing", YAFFS_TRACE_TRACING}, {"verify", YAFFS_TRACE_VERIFY}, {"verify_nand", YAFFS_TRACE_VERIFY_NAND}, {"verify_full", YAFFS_TRACE_VERIFY_FULL}, {"verify_all", YAFFS_TRACE_VERIFY_ALL}, {"write", YAFFS_TRACE_WRITE}, {"all", 0xffffffff}, {"none", 0}, {NULL, 0},};#define MAX_MASK_NAME_LENGTH 40static int yaffs_proc_write(struct file *file, const char *buf, unsigned long count, void *data){ unsigned rg = 0, mask_bitfield; char *end; char *mask_name; const char *x; char substring[MAX_MASK_NAME_LENGTH + 1]; int i; int done = 0; int add, len = 0; int pos = 0; rg = yaffs_traceMask; while (!done && (pos < count)) { done = 1; while ((pos < count) && isspace(buf[pos])) pos++; switch (buf[pos]) { case '+': case '-': case '=': add = buf[pos]; pos++; break; default: add = ' '; break; } mask_name = NULL; mask_bitfield = simple_strtoul(buf + pos, &end, 0); if (end > buf + pos) { mask_name = "numeral"; len = end - (buf + pos); pos += len; done = 0; } else { for (x = buf + pos, i = 0; (*x == '_' || (*x >= 'a' && *x <= 'z')) && i < MAX_MASK_NAME_LENGTH; x++, i++, pos++) substring[i] = *x; substring[i] = '\0'; for (i = 0; mask_flags[i].mask_name != NULL; i++) { if (strcmp(substring, mask_flags[i].mask_name) == 0) { mask_name = mask_flags[i].mask_name; mask_bitfield = mask_flags[i].mask_bitfield; done = 0; break; } } } if (mask_name != NULL) { done = 0; switch (add) { case '-': rg &= ~mask_bitfield; break; case '+': rg |= mask_bitfield; break; case '=': rg = mask_bitfield; break; default: rg |= mask_bitfield; break; } } } yaffs_traceMask = rg | YAFFS_TRACE_ALWAYS; printk(KERN_DEBUG "new trace = 0x%08X\n", yaffs_traceMask); if (rg & YAFFS_TRACE_ALWAYS) { for (i = 0; mask_flags[i].mask_name != NULL; i++) { char flag; flag = ((rg & mask_flags[i].mask_bitfield) == mask_flags[i].mask_bitfield) ? '+' : '-'; printk(KERN_DEBUG "%c%s\n", flag, mask_flags[i].mask_name); } } return 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[] = { {&yaffs_fs_type, 0}, {&yaffs2_fs_type, 0}, {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_entry("yaffs", S_IRUGO | S_IFREG, YPROC_ROOT); if (my_proc_entry) { my_proc_entry->write_proc = yaffs_proc_write; my_proc_entry->read_proc = yaffs_proc_read; my_proc_entry->data = NULL; } else 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", YPROC_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-2006");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -