📄 yaffs_fs.c
字号:
return error;}static int yaffs_mkdir(struct inode * dir, struct dentry * dentry, int mode){ int retVal; T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_mkdir\n")); retVal = yaffs_mknod(dir, dentry, mode | S_IFDIR, 0);#if 0 // attempt to fix dir bug - didn't work if(!retVal) { dget(dentry); }#endif return retVal;}//#if defined(CONFIG_KERNEL_2_5) /* Added NCB 185-8-2003 */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))static int yaffs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *n)#elsestatic int yaffs_create(struct inode *dir, struct dentry *dentry, int mode)#endif{ T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_create\n")); return yaffs_mknod(dir, dentry, mode | S_IFREG, 0);}static int yaffs_unlink(struct inode * dir, struct dentry *dentry){ int retVal; yaffs_Device *dev; T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_unlink %d:%s\n",(int)(dir->i_ino),dentry->d_name.name)); dev = yaffs_InodeToObject(dir)->myDev; yaffs_GrossLock(dev); retVal = yaffs_Unlink(yaffs_InodeToObject(dir),dentry->d_name.name); yaffs_GrossUnlock(dev); if( retVal == YAFFS_OK) { dentry->d_inode->i_nlink--; mark_inode_dirty(dentry->d_inode); return 0; } else { return -ENOTEMPTY; }}/* * 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; yaffs_Device *dev; T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_link\n")); obj = yaffs_InodeToObject(inode); dev = obj->myDev; yaffs_GrossLock(dev); if (!S_ISDIR(inode->i_mode)) // Don't link directories { link = yaffs_Link(yaffs_InodeToObject(dir),dentry->d_name.name,obj); } if(link) { old_dentry->d_inode->i_nlink = yaffs_GetObjectLinkCount(obj); d_instantiate(dentry, old_dentry->d_inode); atomic_inc(&old_dentry->d_inode->i_count); T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_link link count %d i_count %d\n", old_dentry->d_inode->i_nlink,atomic_read(&old_dentry->d_inode->i_count))); } yaffs_GrossUnlock(dev); if(link) { return 0; } return -EPERM; }static int yaffs_symlink(struct inode * dir, struct dentry *dentry, const char * symname){ yaffs_Object *obj; yaffs_Device *dev; T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_symlink\n")); dev = yaffs_InodeToObject(dir)->myDev; yaffs_GrossLock(dev); obj = yaffs_MknodSymLink(yaffs_InodeToObject(dir), dentry->d_name.name, S_IFLNK | S_IRWXUGO, current->uid, current->gid, symname); yaffs_GrossUnlock(dev); if(obj) { struct inode* inode; inode = yaffs_get_inode(dir->i_sb, obj->st_mode, 0, obj); d_instantiate(dentry, inode); T(YAFFS_TRACE_OS,(KERN_DEBUG"symlink created OK\n")); return 0; } else { T(YAFFS_TRACE_OS,(KERN_DEBUG"symlink not created\n")); } return -ENOMEM;}static int yaffs_sync_object(struct file * file, struct dentry *dentry, int datasync){ yaffs_Object *obj; yaffs_Device *dev; obj = yaffs_DentryToObject(dentry); dev = obj->myDev; T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_sync_object\n")); yaffs_GrossLock(dev); yaffs_FlushFile(obj,1); yaffs_GrossUnlock(dev); return 0;}/* * The VFS layer already does all the dentry stuff for rename. * * NB: POSIX says you can rename an object over an old object of the same name */static int yaffs_rename(struct inode * old_dir, struct dentry *old_dentry, struct inode * new_dir,struct dentry *new_dentry){ yaffs_Device *dev; int retVal = YAFFS_FAIL; int removed = 0; yaffs_Object *target; dev = yaffs_InodeToObject(old_dir)->myDev; yaffs_GrossLock(dev); // Check if the target is an existing directory that is not empty. target = yaffs_FindObjectByName(yaffs_InodeToObject(new_dir),new_dentry->d_name.name); if(target && target->variantType == YAFFS_OBJECT_TYPE_DIRECTORY && !list_empty(&target->variant.directoryVariant.children)) { retVal = YAFFS_FAIL; } else { // Unlink the target if it exists removed = yaffs_Unlink(yaffs_InodeToObject(new_dir),new_dentry->d_name.name); retVal = yaffs_RenameObject(yaffs_InodeToObject(old_dir),old_dentry->d_name.name, yaffs_InodeToObject(new_dir),new_dentry->d_name.name); } yaffs_GrossUnlock(dev); if(retVal == YAFFS_OK) { if(removed == YAFFS_OK) { new_dentry->d_inode->i_nlink--; mark_inode_dirty(new_dentry->d_inode); } return 0; } else { return -ENOTEMPTY; } }static int yaffs_setattr(struct dentry *dentry, struct iattr *attr){ struct inode *inode = dentry->d_inode; int error; yaffs_Device *dev; T(YAFFS_TRACE_OS,(KERN_DEBUG"yaffs_setattr of object %d\n",yaffs_InodeToObject(inode)->objectId)); if((error = inode_change_ok(inode,attr)) == 0) { dev = yaffs_InodeToObject(inode)->myDev; yaffs_GrossLock(dev); if(yaffs_SetAttributes(yaffs_InodeToObject(inode),attr) == YAFFS_OK) { error = 0; } else { error = -EPERM; } yaffs_GrossUnlock(dev); inode_setattr(inode,attr); } return error;}//#if defined(CONFIG_KERNEL_2_5) /* Added NCB 185-8-2003 */#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; buf->f_blocks = (dev->endBlock - dev->startBlock + 1) * YAFFS_CHUNKS_PER_BLOCK/ (sb->s_blocksize/YAFFS_BYTES_PER_CHUNK); buf->f_files = 0; buf->f_ffree = 0; buf->f_bfree = yaffs_GetNumberOfFreeChunks(dev)/ (sb->s_blocksize/YAFFS_BYTES_PER_CHUNK); 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 and // thus gross locking should always be in place already. 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)); obj = yaffs_FindObjectByNumber(dev,inode->i_ino); yaffs_FillInodeFromObject(inode,obj);}// Todo// Currently we only can report a single partition. Need to use lists herestatic yaffs_Device *yaffs_dev;static yaffs_Device *yaffsram_dev;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); if(dev == yaffs_dev) yaffs_dev = NULL; if(dev == yaffsram_dev) yaffsram_dev = NULL; kfree(dev);}#ifdef CONFIG_YAFFS_MTD_ENABLEDstatic 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);}#endifstatic struct super_block *yaffs_internal_read_super(int yaffsVersion,int useRam, struct super_block * sb, void * data, int silent){ int nBlocks; struct inode * inode = NULL; struct dentry * root; yaffs_Device *dev; 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(! kdevname(sb->s_dev)) printk(KERN_INFO"yaffs: kdevname is NULL\n"); else 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_TRACE_OS,("yaffs_read_super: Using yaffs%d\n",yaffsVersion)); T(YAFFS_TRACE_OS,("yaffs_read_super: %s block size %d\n", useRam ? "RAM" : "MTD",(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 if(useRam) {#ifdef CONFIG_YAFFS_RAM_ENABLED // Set the yaffs_Device up for ram emulation sb->u.generic_sbp = dev = kmalloc(sizeof(yaffs_Device),GFP_KERNEL); if(!dev) { // Deep shit could not allocate device structure T(YAFFS_TRACE_OS,("yaffs_read_super: Failed trying to allocate yaffs_Device.\n")); return NULL; } memset(dev,0,sizeof(yaffs_Device)); dev->genericDevice = NULL; // Not used for RAM emulation. nBlocks = YAFFS_RAM_EMULATION_SIZE / (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK); dev->startBlock = 1; // Don't use block 0 dev->endBlock = nBlocks - 1; dev->nChunksPerBlock = YAFFS_CHUNKS_PER_BLOCK; dev->nBytesPerChunk = YAFFS_BYTES_PER_CHUNK; dev->nReservedBlocks = 5; if(yaffsVersion == 2) { dev->writeChunkWithTagsToNAND = nandemul2k_WriteChunkWithTagsToNAND; dev->readChunkWithTagsFromNAND = nandemul2k_ReadChunkWithTagsFromNAND; dev->markNANDBlockBad = nandemul2k_MarkNANDBlockBad; dev->queryNANDBlock = nandemul2k_QueryNANDBlock; dev->eraseBlockInNAND = nandemul2k_EraseBlockInNAND; dev->initialiseNAND = nandemul2k_InitialiseNAND; dev->isYaffs2 = 1; dev->nChunksPerBlock = nandemul2k_GetChunksPerBlock(); dev->nBytesPerChunk = nandemul2k_GetBytesPerChunk();; nBlocks = nandemul2k_GetNumberOfBlocks(); dev->startBlock = 1; // Don't use block 0 dev->endBlock = nBlocks - 1; } else { dev->writeChunkToNAND = nandemul_WriteChunkToNAND; dev->readChunkFromNAND = nandemul_ReadChunkFromNAND; dev->eraseBlockInNAND = nandemul_EraseBlockInNAND; dev->initialiseNAND = nandemul_InitialiseNAND; dev->isYaffs2 = 0; } yaffsram_dev = dev; #endif } else { #ifdef CONFIG_YAFFS_MTD_ENABLED struct mtd_info *mtd; T(YAFFS_TRACE_ALWAYS,("yaffs: Attempting MTD mount on %u.%u, \"%s\"\n", MAJOR(sb->s_dev),MINOR(sb->s_dev),kdevname(sb->s_dev))); // 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 %x\n",mtd->erase)); T(YAFFS_TRACE_OS,(" read %x\n",mtd->read)); T(YAFFS_TRACE_OS,(" write %x\n",mtd->write)); T(YAFFS_TRACE_OS,(" readoob %x\n",mtd->read_oob)); T(YAFFS_TRACE_OS,(" writeoob %x\n",mtd->write_oob)); T(YAFFS_TRACE_OS,(" block_isbad %x\n",mtd->block_isbad)); T(YAFFS_TRACE_OS,(" block_markbad %x\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)); if(yaffsVersion == 2) { // Check for version 2 style functions if(!mtd->erase || !mtd->block_isbad || !mtd->block_markbad || !mtd->read || !mtd->write ||#ifndef CONFIG_YAFFS_USE_OLD_MTD !mtd->write_ecc || !mtd->read_ecc ||#endif !mtd->read_oob || !mtd->write_oob ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -