⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yaffs_fs.c

📁 Yaffs(Yet Another Flash File System)文件系统是专门针对NAND闪存设计的嵌入式文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
 * 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;	uid_t uid = current->fsuid;	gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;	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, uid, gid, symname);	yaffs_GrossUnlock(dev);	if (obj) {		struct inode *inode;		inode = yaffs_get_inode(dir->i_sb, obj->yst_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;	yaffs_Object *target;        T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_rename\n"));	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)) {	    	        T(YAFFS_TRACE_OS, (KERN_DEBUG "target is non-empty dir\n"));		retVal = YAFFS_FAIL;	} else {		/* Now does unlinking internally using shadowing mechanism */	        T(YAFFS_TRACE_OS, (KERN_DEBUG "calling yaffs_RenameObject\n"));				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(target) {			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);		if (!error)			error = inode_setattr(inode, attr);	}	return error;}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))static int yaffs_statfs(struct dentry *dentry, struct kstatfs *buf){	yaffs_Device *dev = yaffs_DentryToObject(dentry)->myDev;	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, (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->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, (KERN_DEBUG "yaffs_do_sync_fs\n"));	if(sb->s_dirt) {		yaffs_GrossLock(dev);		if(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, (KERN_DEBUG "yaffs_write_super\n"));#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18))	return 0; /* yaffs_do_sync_fs(sb);*/#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, (KERN_DEBUG "yaffs_sync_fs\n"));		return 0; /* yaffs_do_sync_fs(sb);*/	}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);#if 0 // not usedstatic 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,			(KERN_DEBUG "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, 			(KERN_DEBUG "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, (KERN_DEBUG "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 */	list_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, (KERN_DEBUG "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;	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));	T(YAFFS_TRACE_OS, (" size %d\n", mtd->size));	#ifdef CONFIG_YAFFS_AUTO_YAFFS2	if (yaffsVersion == 1 && #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))	    mtd->writesize >= 2048) {#else	    mtd->oobblock >= 2048) {#endif	    T(YAFFS_TRACE_ALWAYS,("yaffs: auto selecting yaffs2\n"));	    yaffsVersion = 2;	}			/* Added NCB 26/5/2006 for completeness */	if (yaffsVersion == 2 && #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))	    mtd->writesize == 512) {#else	    mtd->oobblock == 512) {#endif	    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 (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))		if (mtd->writesize < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||#else		if (mtd->oobblock < YAFFS_MIN_YAFFS2_CHUNK_SIZE ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -