📄 yaffs_fs.c
字号:
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);#elsestatic int yaffs_statfs(struct super_block *sb, struct statfs *buf){ yaffs_Device *dev = yaffs_SuperToDevice(sb);#endif T(YAFFS_TRACE_OS, ("yaffs_statfs\n")); yaffs_GrossLock(dev); buf->f_type = YAFFS_MAGIC; buf->f_bsize = sb->s_blocksize; buf->f_namelen = 255; if (dev->nDataBytesPerChunk & (dev->nDataBytesPerChunk - 1)) { /* Do this if chunk size is not a power of 2 */ uint64_t bytesInDev; uint64_t bytesFree; bytesInDev = ((uint64_t)((dev->endBlock - dev->startBlock + 1))) * ((uint64_t)(dev->nChunksPerBlock * dev->nDataBytesPerChunk)); do_div(bytesInDev, sb->s_blocksize); /* bytesInDev becomes the number of blocks */ buf->f_blocks = bytesInDev; bytesFree = ((uint64_t)(yaffs_GetNumberOfFreeChunks(dev))) * ((uint64_t)(dev->nDataBytesPerChunk)); do_div(bytesFree, sb->s_blocksize); buf->f_bfree = bytesFree; } else if (sb->s_blocksize > dev->nDataBytesPerChunk) { buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * dev->nChunksPerBlock / (sb->s_blocksize / dev->nDataBytesPerChunk); buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev) / (sb->s_blocksize / dev->nDataBytesPerChunk); } else { buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * dev->nChunksPerBlock * (dev->nDataBytesPerChunk / sb->s_blocksize); buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev) * (dev->nDataBytesPerChunk / sb->s_blocksize); } buf->f_files = 0; buf->f_ffree = 0; buf->f_bavail = buf->f_bfree; yaffs_GrossUnlock(dev); return 0;}static int yaffs_do_sync_fs(struct super_block *sb){ yaffs_Device *dev = yaffs_SuperToDevice(sb); T(YAFFS_TRACE_OS, ("yaffs_do_sync_fs\n")); if (sb->s_dirt) { yaffs_GrossLock(dev); if (dev) { yaffs_FlushEntireDeviceCache(dev); yaffs_CheckpointSave(dev); } yaffs_GrossUnlock(dev); sb->s_dirt = 0; } return 0;}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))static void yaffs_write_super(struct super_block *sb)#elsestatic int yaffs_write_super(struct super_block *sb)#endif{ T(YAFFS_TRACE_OS, ("yaffs_write_super\n")); if (yaffs_auto_checkpoint >= 2) yaffs_do_sync_fs(sb);#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) return 0;#endif}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))static int yaffs_sync_fs(struct super_block *sb, int wait)#elsestatic int yaffs_sync_fs(struct super_block *sb)#endif{ T(YAFFS_TRACE_OS, ("yaffs_sync_fs\n")); if (yaffs_auto_checkpoint >= 1) yaffs_do_sync_fs(sb); return 0;}#ifdef YAFFS_USE_OWN_IGETstatic struct inode *yaffs_iget(struct super_block *sb, unsigned long ino){ struct inode *inode; yaffs_Object *obj; yaffs_Device *dev = yaffs_SuperToDevice(sb); T(YAFFS_TRACE_OS, ("yaffs_iget for %lu\n", ino)); inode = iget_locked(sb, ino); if (!inode) return ERR_PTR(-ENOMEM); if (!(inode->i_state & I_NEW)) return 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_GrossLock(dev); obj = yaffs_FindObjectByNumber(dev, inode->i_ino); yaffs_FillInodeFromObject(inode, obj); yaffs_GrossUnlock(dev); unlock_new_inode(inode); return inode;}#elsestatic 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, ("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);}#endifstatic YLIST_HEAD(yaffs_dev_list);#if 0 /* not used */static int yaffs_remount_fs(struct super_block *sb, int *flags, char *data){ yaffs_Device *dev = yaffs_SuperToDevice(sb); if (*flags & MS_RDONLY) { struct mtd_info *mtd = yaffs_SuperToDevice(sb)->genericDevice; T(YAFFS_TRACE_OS, ("yaffs_remount_fs: %s: RO\n", dev->name)); yaffs_GrossLock(dev); yaffs_FlushEntireDeviceCache(dev); yaffs_CheckpointSave(dev); if (mtd->sync) mtd->sync(mtd); yaffs_GrossUnlock(dev); } else { T(YAFFS_TRACE_OS, ("yaffs_remount_fs: %s: RW\n", dev->name)); } return 0;}#endifstatic void yaffs_put_super(struct super_block *sb){ yaffs_Device *dev = yaffs_SuperToDevice(sb); T(YAFFS_TRACE_OS, ("yaffs_put_super\n")); yaffs_GrossLock(dev); yaffs_FlushEntireDeviceCache(dev); yaffs_CheckpointSave(dev); if (dev->putSuperFunc) dev->putSuperFunc(sb); yaffs_Deinitialise(dev); yaffs_GrossUnlock(dev); /* we assume this is protected by lock_kernel() in mount/umount */ ylist_del(&dev->devList); if (dev->spareBuffer) { YFREE(dev->spareBuffer); dev->spareBuffer = NULL; } 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 void yaffs_MarkSuperBlockDirty(void *vsb){ struct super_block *sb = (struct super_block *)vsb; T(YAFFS_TRACE_OS, ("yaffs_MarkSuperBlockDirty() sb = %p\n", sb)); if (sb) sb->s_dirt = 1;}typedef struct { int inband_tags; int skip_checkpoint_read; int skip_checkpoint_write; int no_cache;} yaffs_options;#define MAX_OPT_LEN 20static int yaffs_parse_options(yaffs_options *options, const char *options_str){ char cur_opt[MAX_OPT_LEN + 1]; int p; int error = 0; /* Parse through the options which is a comma seperated list */ while (options_str && *options_str && !error) { memset(cur_opt, 0, MAX_OPT_LEN + 1); p = 0; while (*options_str && *options_str != ',') { if (p < MAX_OPT_LEN) { cur_opt[p] = *options_str; p++; } options_str++; } if (!strcmp(cur_opt, "inband-tags")) options->inband_tags = 1; else if (!strcmp(cur_opt, "no-cache")) options->no_cache = 1; else if (!strcmp(cur_opt, "no-checkpoint-read")) options->skip_checkpoint_read = 1; else if (!strcmp(cur_opt, "no-checkpoint-write")) options->skip_checkpoint_write = 1; else if (!strcmp(cur_opt, "no-checkpoint")) { options->skip_checkpoint_read = 1; options->skip_checkpoint_write = 1; } else { printk(KERN_INFO "yaffs: Bad mount option \"%s\"\n", cur_opt); error = 1; } } return error;}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; char *data_str = (char *)data; yaffs_options options; sb->s_magic = YAFFS_MAGIC; sb->s_op = &yaffs_super_ops; sb->s_flags |= MS_NOATIME; 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)); if (!data_str) data_str = ""; printk(KERN_INFO "yaffs: passed flags \"%s\"\n", data_str); memset(&options, 0, sizeof(options)); if (yaffs_parse_options(&options, data_str)) { /* Option parsing failed */ return NULL; } 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, (" %s %d\n", WRITE_SIZE_STR, WRITE_SIZE(mtd))); T(YAFFS_TRACE_OS, (" oobsize %d\n", mtd->oobsize)); T(YAFFS_TRACE_OS, (" erasesize %d\n", mtd->erasesize));#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29) T(YAFFS_TRACE_OS, (" size %u\n", mtd->size));#else T(YAFFS_TRACE_OS, (" size %lld\n", mtd->size));#endif#ifdef CONFIG_YAFFS_AUTO_YAFFS2 if (yaffsVersion == 1 && WRITE_SIZE(mtd) >= 2048) { T(YAFFS_TRACE_ALWAYS, ("yaffs: auto selecting yaffs2\n")); yaffsVersion = 2; } /* Added NCB 26/5/2006 for completeness */ if (yaffsVersion == 2 && !options.inband_tags && WRITE_SIZE(mtd) == 512) { T(YAFFS_TRACE_ALWAYS, ("yaffs: auto selecting yaffs1\n")); yaffsVersion = 1; }#endif if (yaffsVersion == 2) { /* Check for version 2 style functions */ if (!mtd->erase || !mtd->block_isbad || !mtd->block_markbad || !mtd->read || !mtd->write ||#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) !mtd->read_oob || !mtd->write_oob) {#else !mtd->write_ecc || !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {#endif T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not support required " "functions\n"));; return NULL; } if ((WRITE_SIZE(mtd) < YAFFS_MIN_YAFFS2_CHUNK_SIZE || mtd->oobsize < YAFFS_MIN_YAFFS2_SPARE_SIZE) && !options.inband_tags) { T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not have the " "right page sizes\n")); return NULL; } } else { /* Check for V1 style functions */ if (!mtd->erase || !mtd->read || !mtd->write ||#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17)) !mtd->read_oob || !mtd->write_oob) {#else !mtd->write_ecc || !mtd->read_ecc || !mtd->read_oob || !mtd->write_oob) {#endif T(YAFFS_TRACE_ALWAYS, ("yaffs: MTD device does not support required " "functions\n"));; return NULL; } if (WRITE_SIZE(mtd) < 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 = YCALCBLOCKS(mtd->size, (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK)); dev->startBlock = 0; dev->endBlock = nBlocks - 1; dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; dev->totalBytesPerChunk = YAFFS_BYTES_PER_CHUNK; dev->nReservedBlocks = 5; dev->nShortOpCaches = (options.no_cache) ? 0 : 10;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -