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

📄 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/time.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/stat.h>#include <linux/errno.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 "coda_int.h"/* dir inode-ops */static int coda_create(struct inode *dir, struct dentry *new, int mode, struct nameidata *nd);static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd);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 *buf, filldir_t filldir);/* dentry ops */static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);static int coda_dentry_delete(struct dentry *);/* support routines */static int coda_venus_readdir(struct file *coda_file, void *buf,			      filldir_t filldir);/* same as fs/bad_inode.c */static int coda_return_EIO(void){	return -EIO;}#define CODA_EIO_ERROR ((void *) (coda_return_EIO))static struct dentry_operations coda_dentry_operations ={	.d_revalidate	= coda_dentry_revalidate,	.d_delete	= coda_dentry_delete,};const 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_EIO_ERROR,	.rename		= coda_rename,	.permission	= coda_permission,	.getattr	= coda_getattr,	.setattr	= coda_setattr,};const struct file_operations coda_dir_operations = {	.llseek		= generic_file_llseek,	.read		= generic_read_dir,	.readdir	= coda_readdir,	.open		= coda_open,	.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 nameidata *nd){	struct inode *inode = NULL;	struct CodaFid resfid = { { 0, } };	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(KERN_ERR "name too long: lookup, %s (%*s)\n",		       coda_i2s(dir), (int)length, name);		return ERR_PTR(-ENAMETOOLONG);	}	/* control object, create inode on the fly */	if (coda_isroot(dir) && coda_iscontrol(name, length)) {		error = coda_cnode_makectl(&inode, dir->i_sb);		type = CODA_NOCACHE;		goto exit;	}	lock_kernel();	error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,			     &type, &resfid);	if (!error)		error = coda_cnode_make(&inode, &resfid, dir->i_sb);	unlock_kernel();	if (error && error != -ENOENT)		return ERR_PTR(error);exit:	entry->d_op = &coda_dentry_operations;	if (inode && (type & CODA_NOCACHE))		coda_flag_inode(inode, C_VATTR | C_PURGE);	return d_splice_alias(inode, entry);}int coda_permission(struct inode *inode, int mask, struct nameidata *nd){        int error = 0; 	if (!mask)		return 0; 	lock_kernel();	if (coda_cache_check(inode, mask))		goto out;         error = venus_access(inode->i_sb, coda_i2f(inode), mask);    	if (!error)		coda_cache_enter(inode, mask); out:	unlock_kernel();	return error;}static inline void coda_dir_update_mtime(struct inode *dir){#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_SEC;#endif}/* we have to wrap inc_nlink/drop_nlink because sometimes userspace uses a * trick to fool GNU find's optimizations. If we can't be sure of the link * (because of volume mount points) we set i_nlink to 1 which forces find * to consider every child as a possible directory. We should also never * see an increment or decrement for deleted directories where i_nlink == 0 */static inline void coda_dir_inc_nlink(struct inode *dir){	if (dir->i_nlink >= 2)		inc_nlink(dir);}static inline void coda_dir_drop_nlink(struct inode *dir){	if (dir->i_nlink > 2)		drop_nlink(dir);}/* creation routines: create, mknod, mkdir, link, symlink */static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd){        int error=0;	const char *name=de->d_name.name;	int length=de->d_name.len;	struct inode *inode;	struct CodaFid newfid;	struct coda_vattr attrs;	lock_kernel();	if (coda_isroot(dir) && coda_iscontrol(name, length)) {		unlock_kernel();		return -EPERM;	}	error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 				0, mode, &newfid, &attrs);        if ( error ) {		unlock_kernel();		d_drop(de);		return error;	}	inode = coda_iget(dir->i_sb, &newfid, &attrs);	if ( IS_ERR(inode) ) {		unlock_kernel();		d_drop(de);		return PTR_ERR(inode);	}	/* invalidate the directory cnode's attributes */	coda_dir_update_mtime(dir);	unlock_kernel();	d_instantiate(de, inode);	return 0;}static int coda_mkdir(struct inode *dir, struct dentry *de, int mode){	struct inode *inode;	struct coda_vattr attrs;	const char *name = de->d_name.name;	int len = de->d_name.len;	int error;	struct CodaFid newfid;	lock_kernel();	if (coda_isroot(dir) && coda_iscontrol(name, len)) {		unlock_kernel();		return -EPERM;	}	attrs.va_mode = mode;	error = venus_mkdir(dir->i_sb, coda_i2f(dir), 			       name, len, &newfid, &attrs);                if ( error ) {		unlock_kernel();		d_drop(de);		return error;        }         	inode = coda_iget(dir->i_sb, &newfid, &attrs);	if ( IS_ERR(inode) ) {		unlock_kernel();		d_drop(de);		return PTR_ERR(inode);	}	/* invalidate the directory cnode's attributes */	coda_dir_inc_nlink(dir);	coda_dir_update_mtime(dir);	unlock_kernel();	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;	lock_kernel();	if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {		unlock_kernel();		return -EPERM;	}	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_update_mtime(dir_inode);	atomic_inc(&inode->i_count);	d_instantiate(de, inode);	inc_nlink(inode);out:	unlock_kernel();	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;	lock_kernel();	if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {		unlock_kernel();		return -EPERM;	}	symlen = strlen(symname);	if ( symlen > CODA_MAXPATHLEN ) {		unlock_kernel();		return -ENAMETOOLONG;	}	/*	 * This entry is now negative. Since we do not create	 * an inode for the entry we have to drop it.	 */	d_drop(de);	error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len,			      symname, symlen);	/* mtime is no good anymore */	if ( !error )		coda_dir_update_mtime(dir_inode);	unlock_kernel();	return error;}/* destruction routines: unlink, rmdir */int coda_unlink(struct inode *dir, struct dentry *de){        int error;

⌨️ 快捷键说明

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