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

📄 yaffs_fs.c

📁 Yaffs(Yet Another Flash File System)文件系统是专门针对NAND闪存设计的嵌入式文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	kunmap(pg);	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_readpage done\n"));	return ret;}static int yaffs_readpage_unlock(struct file *f, struct page *pg){	int ret = yaffs_readpage_nolock(f, pg);	UnlockPage(pg);	return ret;}static int yaffs_readpage(struct file *f, struct page *pg){	return yaffs_readpage_unlock(f, pg);}/* writepage inspired by/stolen from smbfs */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))static int yaffs_writepage(struct page *page, struct writeback_control *wbc)#elsestatic int yaffs_writepage(struct page *page)#endif{	struct address_space *mapping = page->mapping;	loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT;	struct inode *inode;	unsigned long end_index;	char *buffer;	yaffs_Object *obj;	int nWritten = 0;	unsigned nBytes;	if (!mapping)		BUG();	inode = mapping->host;	if (!inode)		BUG();	if (offset > inode->i_size) {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG		   "yaffs_writepage at %08x, inode size = %08x!!!\n",		   (unsigned)(page->index << PAGE_CACHE_SHIFT),		   (unsigned)inode->i_size));		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "                -> don't care!!\n"));		unlock_page(page);		return 0;	}	end_index = inode->i_size >> PAGE_CACHE_SHIFT;	/* easy case */	if (page->index < end_index) {		nBytes = PAGE_CACHE_SIZE;	} else {		nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1);	}	get_page(page);	buffer = kmap(page);	obj = yaffs_InodeToObject(inode);	yaffs_GrossLock(obj->myDev);	T(YAFFS_TRACE_OS,	  (KERN_DEBUG "yaffs_writepage at %08x, size %08x\n",	   (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes));	T(YAFFS_TRACE_OS,	  (KERN_DEBUG "writepag0: obj = %05x, ino = %05x\n",	   (int)obj->variant.fileVariant.fileSize, (int)inode->i_size));	nWritten =	    yaffs_WriteDataToFile(obj, buffer, page->index << PAGE_CACHE_SHIFT,				  nBytes, 0);	T(YAFFS_TRACE_OS,	  (KERN_DEBUG "writepag1: obj = %05x, ino = %05x\n",	   (int)obj->variant.fileVariant.fileSize, (int)inode->i_size));	yaffs_GrossUnlock(obj->myDev);	kunmap(page);	SetPageUptodate(page);	UnlockPage(page);	put_page(page);	return (nWritten == nBytes) ? 0 : -ENOSPC;}static int yaffs_prepare_write(struct file *f, struct page *pg,			       unsigned offset, unsigned to){	T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_prepair_write\n"));	if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE))		return yaffs_readpage_nolock(f, pg);	return 0;}static int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset,			      unsigned to){	void *addr = page_address(pg) + offset;	loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset;	int nBytes = to - offset;	int nWritten;	unsigned spos = pos;	unsigned saddr = (unsigned)addr;	T(YAFFS_TRACE_OS,	  (KERN_DEBUG "yaffs_commit_write addr %x pos %x nBytes %d\n", saddr,	   spos, nBytes));	nWritten = yaffs_file_write(f, addr, nBytes, &pos);	if (nWritten != nBytes) {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG		   "yaffs_commit_write not same size nWritten %d  nBytes %d\n",		   nWritten, nBytes));		SetPageError(pg);		ClearPageUptodate(pg);	} else {		SetPageUptodate(pg);	}	T(YAFFS_TRACE_OS,	  (KERN_DEBUG "yaffs_commit_write returning %d\n",	   nWritten == nBytes ? 0 : nWritten));	return nWritten == nBytes ? 0 : nWritten;}static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj){	if (inode && obj) {		/* Check mode against the variant type and attempt to repair if broken. */ 		__u32 mode = obj->yst_mode; 		switch( obj->variantType ){ 		case YAFFS_OBJECT_TYPE_FILE : 		        if( ! S_ISREG(mode) ){ 			        obj->yst_mode &= ~S_IFMT; 			        obj->yst_mode |= S_IFREG; 			}  			break; 		case YAFFS_OBJECT_TYPE_SYMLINK : 		        if( ! S_ISLNK(mode) ){ 			        obj->yst_mode &= ~S_IFMT; 				obj->yst_mode |= S_IFLNK; 			}  			break; 		case YAFFS_OBJECT_TYPE_DIRECTORY : 		        if( ! S_ISDIR(mode) ){ 			        obj->yst_mode &= ~S_IFMT; 			        obj->yst_mode |= S_IFDIR; 			}  			break; 		case YAFFS_OBJECT_TYPE_UNKNOWN : 		case YAFFS_OBJECT_TYPE_HARDLINK : 		case YAFFS_OBJECT_TYPE_SPECIAL : 		default: 		        /* TODO? */ 		        break; 		}		inode->i_ino = obj->objectId;		inode->i_mode = obj->yst_mode;		inode->i_uid = obj->yst_uid;		inode->i_gid = obj->yst_gid;#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))		inode->i_blksize = inode->i_sb->s_blocksize;#endif#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))		inode->i_rdev = old_decode_dev(obj->yst_rdev);		inode->i_atime.tv_sec = (time_t) (obj->yst_atime);		inode->i_atime.tv_nsec = 0;		inode->i_mtime.tv_sec = (time_t) obj->yst_mtime;		inode->i_mtime.tv_nsec = 0;		inode->i_ctime.tv_sec = (time_t) obj->yst_ctime;		inode->i_ctime.tv_nsec = 0;#else		inode->i_rdev = obj->yst_rdev;		inode->i_atime = obj->yst_atime;		inode->i_mtime = obj->yst_mtime;		inode->i_ctime = obj->yst_ctime;#endif		inode->i_size = yaffs_GetObjectFileLength(obj);		inode->i_blocks = (inode->i_size + 511) >> 9;		inode->i_nlink = yaffs_GetObjectLinkCount(obj);		T(YAFFS_TRACE_OS,		  (KERN_DEBUG		   "yaffs_FillInode mode %x uid %d gid %d size %d count %d\n",		   inode->i_mode, inode->i_uid, inode->i_gid,		   (int)inode->i_size, atomic_read(&inode->i_count)));		switch (obj->yst_mode & S_IFMT) {		default:	/* fifo, device or socket */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))			init_special_inode(inode, obj->yst_mode,					   old_decode_dev(obj->yst_rdev));#else			init_special_inode(inode, obj->yst_mode,					   (dev_t) (obj->yst_rdev));#endif			break;		case S_IFREG:	/* file */			inode->i_op = &yaffs_file_inode_operations;			inode->i_fop = &yaffs_file_operations;			inode->i_mapping->a_ops =			    &yaffs_file_address_operations;			break;		case S_IFDIR:	/* directory */			inode->i_op = &yaffs_dir_inode_operations;			inode->i_fop = &yaffs_dir_operations;			break;		case S_IFLNK:	/* symlink */			inode->i_op = &yaffs_symlink_inode_operations;			break;		}		yaffs_InodeToObjectLV(inode) = obj;		obj->myInode = inode;	} else {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_FileInode invalid parameters\n"));	}}struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev,			      yaffs_Object * obj){	struct inode *inode;	if (!sb) {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_get_inode for NULL super_block!!\n"));		return NULL;	}	if (!obj) {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_get_inode for NULL object!!\n"));		return NULL;	}	T(YAFFS_TRACE_OS,	  (KERN_DEBUG "yaffs_get_inode for object %d\n", obj->objectId));	inode = iget(sb, obj->objectId);	/* NB Side effect: iget calls back to yaffs_read_inode(). */	/* iget also increments the inode's i_count */	/* NB You can't be holding grossLock or deadlock will happen! */	return inode;}static ssize_t yaffs_file_write(struct file *f, const char *buf, size_t n,				loff_t * pos){	yaffs_Object *obj;	int nWritten, ipos;	struct inode *inode;	yaffs_Device *dev;	obj = yaffs_DentryToObject(f->f_dentry);	dev = obj->myDev;	yaffs_GrossLock(dev);	inode = f->f_dentry->d_inode;	if (!S_ISBLK(inode->i_mode) && f->f_flags & O_APPEND) {		ipos = inode->i_size;	} else {		ipos = *pos;	}	if (!obj) {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_file_write: hey obj is null!\n"));	} else {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG		   "yaffs_file_write about to write writing %d bytes"		   "to object %d at %d\n",		   n, obj->objectId, ipos));	}	nWritten = yaffs_WriteDataToFile(obj, buf, ipos, n, 0);	T(YAFFS_TRACE_OS,	  (KERN_DEBUG "yaffs_file_write writing %d bytes, %d written at %d\n",	   n, nWritten, ipos));	if (nWritten > 0) {		ipos += nWritten;		*pos = ipos;		if (ipos > inode->i_size) {			inode->i_size = ipos;			inode->i_blocks = (ipos + 511) >> 9;			T(YAFFS_TRACE_OS,			  (KERN_DEBUG			   "yaffs_file_write size updated to %d bytes, "			   "%d blocks\n",			   ipos, (int)(inode->i_blocks)));		}	}	yaffs_GrossUnlock(dev);	return nWritten == 0 ? -ENOSPC : nWritten;}static int yaffs_readdir(struct file *f, void *dirent, filldir_t filldir){	yaffs_Object *obj;	yaffs_Device *dev;	struct inode *inode = f->f_dentry->d_inode;	unsigned long offset, curoffs;	struct list_head *i;	yaffs_Object *l;	char name[YAFFS_MAX_NAME_LENGTH + 1];	obj = yaffs_DentryToObject(f->f_dentry);	dev = obj->myDev;	yaffs_GrossLock(dev);	offset = f->f_pos;	T(YAFFS_TRACE_OS, ("yaffs_readdir: starting at %d\n", (int)offset));	if (offset == 0) {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_readdir: entry . ino %d \n",		   (int)inode->i_ino));		if (filldir(dirent, ".", 1, offset, inode->i_ino, DT_DIR)		    < 0) {			goto out;		}		offset++;		f->f_pos++;	}	if (offset == 1) {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_readdir: entry .. ino %d \n",		   (int)f->f_dentry->d_parent->d_inode->i_ino));		if (filldir		    (dirent, "..", 2, offset,		     f->f_dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) {			goto out;		}		offset++;		f->f_pos++;	}	curoffs = 1;	/* If the directory has changed since the open or last call to	   readdir, rewind to after the 2 canned entries. */	if (f->f_version != inode->i_version) {		offset = 2;		f->f_pos = offset;		f->f_version = inode->i_version;	}	list_for_each(i, &obj->variant.directoryVariant.children) {		curoffs++;		if (curoffs >= offset) {			l = list_entry(i, yaffs_Object, siblings);			yaffs_GetObjectName(l, name,					    YAFFS_MAX_NAME_LENGTH + 1);			T(YAFFS_TRACE_OS,			  (KERN_DEBUG "yaffs_readdir: %s inode %d\n", name,			   yaffs_GetObjectInode(l)));			if (filldir(dirent,				    name,				    strlen(name),				    offset,				    yaffs_GetObjectInode(l),				    yaffs_GetObjectType(l))			    < 0) {				goto up_and_out;			}			offset++;			f->f_pos++;		}	}      up_and_out:      out:	yaffs_GrossUnlock(dev);	return 0;}/* * File creation. Allocate an inode, and we're done.. */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))static int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,		       dev_t rdev)#elsestatic int yaffs_mknod(struct inode *dir, struct dentry *dentry, int mode,		       int rdev)#endif{	struct inode *inode;	yaffs_Object *obj = NULL;	yaffs_Device *dev;	yaffs_Object *parent = yaffs_InodeToObject(dir);	int error = -ENOSPC;	uid_t uid = current->fsuid;	gid_t gid = (dir->i_mode & S_ISGID) ? dir->i_gid : current->fsgid;		if((dir->i_mode & S_ISGID) && S_ISDIR(mode))		mode |= S_ISGID;	if (parent) {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_mknod: parent object %d type %d\n",		   parent->objectId, parent->variantType));	} else {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_mknod: could not get parent object\n"));		return -EPERM;	}	T(YAFFS_TRACE_OS, ("yaffs_mknod: making oject for %s, "			   "mode %x dev %x\n",			   dentry->d_name.name, mode, rdev));	dev = parent->myDev;	yaffs_GrossLock(dev);	switch (mode & S_IFMT) {	default:		/* Special (socket, fifo, device...) */		T(YAFFS_TRACE_OS, (KERN_DEBUG				   "yaffs_mknod: making special\n"));#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))		obj =		    yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid,				       gid, old_encode_dev(rdev));#else		obj =		    yaffs_MknodSpecial(parent, dentry->d_name.name, mode, uid,				       gid, rdev);#endif		break;	case S_IFREG:		/* file          */		T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n"));		obj =		    yaffs_MknodFile(parent, dentry->d_name.name, mode, uid,				    gid);		break;	case S_IFDIR:		/* directory */		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_mknod: making directory\n"));		obj =		    yaffs_MknodDirectory(parent, dentry->d_name.name, mode,					 uid, gid);		break;	case S_IFLNK:		/* symlink */		T(YAFFS_TRACE_OS, (KERN_DEBUG "yaffs_mknod: making file\n"));		obj = NULL;	/* Do we ever get here? */		break;	}		/* Can not call yaffs_get_inode() with gross lock held */	yaffs_GrossUnlock(dev);	if (obj) {		inode = yaffs_get_inode(dir->i_sb, mode, rdev, obj);		d_instantiate(dentry, inode);		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_mknod created object %d count = %d\n",		   obj->objectId, atomic_read(&inode->i_count)));		error = 0;	} else {		T(YAFFS_TRACE_OS,		  (KERN_DEBUG "yaffs_mknod failed making object\n"));		error = -ENOMEM;	}	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 (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);	if (retVal == YAFFS_OK) {		dentry->d_inode->i_nlink--;		dir->i_version++;		yaffs_GrossUnlock(dev);		mark_inode_dirty(dentry->d_inode);		return 0;	}	yaffs_GrossUnlock(dev);	return -ENOTEMPTY;}/*

⌨️ 快捷键说明

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