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

📄 yaffs_fs.c

📁 YAFFS
💻 C
📖 第 1 页 / 共 3 页
字号:
}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 : -1));	return nWritten == nBytes ? 0 : -1;}static void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object * obj){	if (inode && obj) {		inode->i_ino = obj->objectId;		inode->i_mode = obj->yst_mode;		inode->i_uid = obj->yst_uid;		inode->i_gid = obj->yst_gid;		inode->i_blksize = inode->i_sb->s_blocksize;#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;		}		inode->u.generic_ip = 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 != n ? -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;	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 (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);	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;	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) ==

⌨️ 快捷键说明

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