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

📄 yaffs_fs.c

📁 YAFFS
💻 C
📖 第 1 页 / 共 3 页
字号:
		    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 + -