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

📄 dir.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Directory operations for Coda filesystem * Original version: (C) 1996 P. Braam and M. Callahan * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University *  * Carnegie Mellon encourages users to contribute improvements to * the Coda project. Contact Peter Braam (coda@cs.cmu.edu). */#include <linux/types.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/locks.h>#include <linux/string.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <linux/coda.h>#include <linux/coda_linux.h>#include <linux/coda_psdev.h>#include <linux/coda_fs_i.h>#include <linux/coda_cache.h>#include <linux/coda_proc.h>/* dir inode-ops */static int coda_create(struct inode *dir, struct dentry *new, int mode);static int coda_mknod(struct inode *dir, struct dentry *new, int mode, int rdev);static struct dentry *coda_lookup(struct inode *dir, struct dentry *target);static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, 		     struct dentry *entry);static int coda_unlink(struct inode *dir_inode, struct dentry *entry);static int coda_symlink(struct inode *dir_inode, struct dentry *entry,			const char *symname);static int coda_mkdir(struct inode *dir_inode, struct dentry *entry, int mode);static int coda_rmdir(struct inode *dir_inode, struct dentry *entry);static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,                        struct inode *new_inode, struct dentry *new_dentry);/* dir file-ops */static int coda_readdir(struct file *file, void *dirent, filldir_t filldir);/* dentry ops */static int coda_dentry_revalidate(struct dentry *de, int);static int coda_dentry_delete(struct dentry *);/* support routines */static void coda_prepare_fakefile(struct file *coda_file, 				  struct dentry *open_dentry,				  struct file *open_file);static int coda_venus_readdir(struct file *filp, void *dirent, 			      filldir_t filldir);int coda_fsync(struct file *, struct dentry *dentry, int datasync);int coda_hasmknod;struct dentry_operations coda_dentry_operations ={	d_revalidate:	coda_dentry_revalidate,	d_delete:	coda_dentry_delete,};struct inode_operations coda_dir_inode_operations ={	create:		coda_create,	lookup:		coda_lookup,	link:		coda_link,	unlink:		coda_unlink,	symlink:	coda_symlink,	mkdir:		coda_mkdir,	rmdir:		coda_rmdir,	mknod:		coda_mknod,	rename:		coda_rename,	permission:	coda_permission,        revalidate:	coda_revalidate_inode,	setattr:	coda_notify_change,};struct file_operations coda_dir_operations = {	read:		generic_read_dir,	readdir:	coda_readdir,	open:		coda_open,	flush:  	coda_flush,	release:	coda_release,	fsync:		coda_fsync,};/* inode operations for directories *//* access routines: lookup, readlink, permission */static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry){	struct inode *res_inode = NULL;	struct ViceFid resfid = {0,0,0};	int dropme = 0; /* to indicate entry should not be cached */	int type = 0;	int error = 0;	const char *name = entry->d_name.name;	size_t length = entry->d_name.len;		if ( length > CODA_MAXNAMLEN ) {	        printk("name too long: lookup, %s (%*s)\n", 		       coda_i2s(dir), (int)length, name);		return ERR_PTR(-ENAMETOOLONG);	}        CDEBUG(D_INODE, "name %s, len %ld in ino %ld, fid %s\n", 	       name, (long)length, dir->i_ino, coda_i2s(dir));        /* control object, create inode on the fly */        if (coda_isroot(dir) && coda_iscontrol(name, length)) {	        error = coda_cnode_makectl(&res_inode, dir->i_sb);		CDEBUG(D_SPECIAL, 		       "Lookup on CTL object; dir ino %ld, count %d\n", 		       dir->i_ino, atomic_read(&dir->i_count));		dropme = 1;                goto exit;        }	error = venus_lookup(dir->i_sb, coda_i2f(dir), 			     (const char *)name, length, &type, &resfid);	res_inode = NULL;	if (!error) {		if (type & CODA_NOCACHE) {			type &= (~CODA_NOCACHE);			CDEBUG(D_INODE, "dropme set for %s\n", 			       coda_f2s(&resfid));			dropme = 1;		}	    	error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);		if (error) return ERR_PTR(error);	} else if (error != -ENOENT) {	        CDEBUG(D_INODE, "error for %s(%*s)%d\n",		       coda_i2s(dir), (int)length, name, error);		return ERR_PTR(error);	}	CDEBUG(D_INODE, "lookup: %s is (%s), type %d result %d, dropme %d\n",	       name, coda_f2s(&resfid), type, error, dropme);exit:	entry->d_time = 0;	entry->d_op = &coda_dentry_operations;	d_add(entry, res_inode);	if ( dropme ) {		d_drop(entry);		coda_flag_inode(res_inode, C_VATTR);	}        return NULL;}int coda_permission(struct inode *inode, int mask){        int error; 	coda_vfs_stat.permission++;        if ( mask == 0 )                return 0;	if ( coda_access_cache ) {		coda_permission_stat.count++;		if ( coda_cache_check(inode, mask) ) {			coda_permission_stat.hit_count++;			return 0; 		}	}        CDEBUG(D_INODE, "mask is %o\n", mask);        error = venus_access(inode->i_sb, coda_i2f(inode), mask);            CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n", 	       coda_i2s(inode), inode->i_ino, mask, error);	if (!error)		coda_cache_enter(inode, mask);        return error; }static inline void coda_dir_changed(struct inode *dir, int link){#ifdef REQUERY_VENUS_FOR_MTIME	/* invalidate the directory cnode's attributes so we refetch the	 * attributes from venus next time the inode is referenced */	coda_flag_inode(dir, C_VATTR);#else	/* optimistically we can also act as if our nose bleeds. The         * granularity of the mtime is coarse anyways so we might actually be         * right most of the time. Note: we only do this for directories. */	dir->i_mtime = dir->i_ctime = CURRENT_TIME;#endif	if (link)		dir->i_nlink += link;}/* creation routines: create, mknod, mkdir, link, symlink */static int coda_create(struct inode *dir, struct dentry *de, int mode){        int error=0;	const char *name=de->d_name.name;	int length=de->d_name.len;	struct inode *inode = NULL;	struct ViceFid newfid;	struct coda_vattr attrs;	coda_vfs_stat.create++;	CDEBUG(D_INODE, "name: %s, length %d, mode %o\n", name, length, mode);	if (coda_isroot(dir) && coda_iscontrol(name, length))		return -EPERM;	error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 				0, mode, 0, &newfid, &attrs);        if ( error ) {		CDEBUG(D_INODE, "create: %s, result %d\n",		       coda_f2s(&newfid), error); 		d_drop(de);		return error;	}	inode = coda_iget(dir->i_sb, &newfid, &attrs);	if ( IS_ERR(inode) ) {		d_drop(de);		return PTR_ERR(inode);	}	/* invalidate the directory cnode's attributes */	coda_dir_changed(dir, 0);	d_instantiate(de, inode);        return 0;}static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev){        int error=0;	const char *name=de->d_name.name;	int length=de->d_name.len;	struct inode *result = NULL;	struct ViceFid newfid;	struct coda_vattr attrs;	if ( coda_hasmknod == 0 )		return -EIO;	coda_vfs_stat.create++;	CDEBUG(D_INODE, "name: %s, length %d, mode %o, rdev %x\n",	       name, length, mode, rdev);	if (coda_isroot(dir) && coda_iscontrol(name, length))		return -EPERM;	error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 				0, mode, rdev, &newfid, &attrs);        if ( error ) {		CDEBUG(D_INODE, "mknod: %s, result %d\n",		       coda_f2s(&newfid), error); 		d_drop(de);		return error;	}	error = coda_cnode_make(&result, &newfid, dir->i_sb);	if ( error ) {		d_drop(de);		result = NULL;		return error;	}	/* invalidate the directory cnode's attributes */	coda_dir_changed(dir, 0);	d_instantiate(de, result);        return 0;}			     static int coda_mkdir(struct inode *dir, struct dentry *de, int mode){	struct inode *inode;	struct coda_vattr attr;	const char *name = de->d_name.name;	int len = de->d_name.len;	int error;	struct ViceFid newfid;	coda_vfs_stat.mkdir++;	if (coda_isroot(dir) && coda_iscontrol(name, len))		return -EPERM;	CDEBUG(D_INODE, "mkdir %s (len %d) in %s, mode %o.\n", 	       name, len, coda_i2s(dir), mode);	attr.va_mode = mode;	error = venus_mkdir(dir->i_sb, coda_i2f(dir), 			       name, len, &newfid, &attr);                if ( error ) {	        CDEBUG(D_INODE, "mkdir error: %s result %d\n", 		       coda_f2s(&newfid), error); 		d_drop(de);                return error;        }         	CDEBUG(D_INODE, "mkdir: new dir has fid %s.\n", 	       coda_f2s(&newfid)); 	error = coda_cnode_make(&inode, &newfid, dir->i_sb);	if ( error ) {		d_drop(de);		return error;	}		/* invalidate the directory cnode's attributes */	coda_dir_changed(dir, 1);	d_instantiate(de, inode);        return 0;}/* try to make de an entry in dir_inodde linked to source_de */ static int coda_link(struct dentry *source_de, struct inode *dir_inode, 	  struct dentry *de){	struct inode *inode = source_de->d_inode;        const char * name = de->d_name.name;	int len = de->d_name.len;	int error;	coda_vfs_stat.link++;	if (coda_isroot(dir_inode) && coda_iscontrol(name, len))		return -EPERM;	CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode));	CDEBUG(D_INODE, "directory: %s\n", coda_i2s(dir_inode));	error = venus_link(dir_inode->i_sb, coda_i2f(inode),			   coda_i2f(dir_inode), (const char *)name, len);	if (error) { 		d_drop(de);		goto out;	}	coda_dir_changed(dir_inode, 0);	atomic_inc(&inode->i_count);	d_instantiate(de, inode);	inode->i_nlink++;        out:	CDEBUG(D_INODE, "link result %d\n",error);	return(error);}static int coda_symlink(struct inode *dir_inode, struct dentry *de,			const char *symname){        const char *name = de->d_name.name;	int len = de->d_name.len;	int symlen;        int error=0;        	coda_vfs_stat.symlink++;	if (coda_isroot(dir_inode) && coda_iscontrol(name, len))		return -EPERM;	symlen = strlen(symname);	if ( symlen > CODA_MAXPATHLEN )                return -ENAMETOOLONG;        CDEBUG(D_INODE, "symname: %s, length: %d\n", symname, symlen);	/*	 * This entry is now negative. Since we do not create	 * an inode for the entry we have to drop it. 	 */

⌨️ 快捷键说明

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