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

📄 dir.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/nfs/dir.c * *  Copyright (C) 1992  Rick Sladkey * *  nfs directory handling functions */#include <linux/sched.h>#include <linux/errno.h>#include <linux/stat.h>#include <linux/nfs_fs.h>#include <linux/fcntl.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/malloc.h>#include <linux/mm.h>#include <asm/segment.h>	/* for fs functions */static int nfs_dir_read(struct inode *, struct file *filp, char *buf,			int count);static int nfs_readdir(struct inode *, struct file *, struct dirent *, int);static int nfs_lookup(struct inode *dir, const char *name, int len,		      struct inode **result);static int nfs_create(struct inode *dir, const char *name, int len, int mode,		      struct inode **result);static int nfs_mkdir(struct inode *dir, const char *name, int len, int mode);static int nfs_rmdir(struct inode *dir, const char *name, int len);static int nfs_unlink(struct inode *dir, const char *name, int len);static int nfs_symlink(struct inode *inode, const char *name, int len,		       const char *symname);static int nfs_link(struct inode *oldinode, struct inode *dir,		    const char *name, int len);static int nfs_mknod(struct inode *dir, const char *name, int len, int mode,		     int rdev);static int nfs_rename(struct inode *old_dir, const char *old_name,		      int old_len, struct inode *new_dir, const char *new_name,		      int new_len);static struct file_operations nfs_dir_operations = {	NULL,			/* lseek - default */	nfs_dir_read,		/* read - bad */	NULL,			/* write - bad */	nfs_readdir,		/* readdir */	NULL,			/* select - default */	NULL,			/* ioctl - default */	NULL,			/* mmap */	NULL,			/* no special open code */	NULL,			/* no special release code */	NULL			/* fsync */};struct inode_operations nfs_dir_inode_operations = {	&nfs_dir_operations,	/* default directory file-ops */	nfs_create,		/* create */	nfs_lookup,		/* lookup */	nfs_link,		/* link */	nfs_unlink,		/* unlink */	nfs_symlink,		/* symlink */	nfs_mkdir,		/* mkdir */	nfs_rmdir,		/* rmdir */	nfs_mknod,		/* mknod */	nfs_rename,		/* rename */	NULL,			/* readlink */	NULL,			/* follow_link */	NULL,			/* bmap */	NULL,			/* truncate */	NULL			/* permission */};static int nfs_dir_read(struct inode *inode, struct file *filp, char *buf,			int count){	return -EISDIR;}/* * We need to do caching of directory entries to prevent an * incredible amount of RPC traffic.  Only the most recent open * directory is cached.  This seems sufficient for most purposes. * Technically, we ought to flush the cache on close but this is * not a problem in practice. */static int nfs_readdir(struct inode *inode, struct file *filp,		       struct dirent *dirent, int count){	static int c_dev = 0;	static int c_ino;	static int c_size;	static struct nfs_entry *c_entry = NULL;	int result;	int i;	struct nfs_entry *entry;	if (!inode || !S_ISDIR(inode->i_mode)) {		printk("nfs_readdir: inode is NULL or not a directory\n");		return -EBADF;	}	/* initialize cache memory if it hasn't been used before */	if (c_entry == NULL) {		i = sizeof (struct nfs_entry)*NFS_READDIR_CACHE_SIZE;		c_entry = (struct nfs_entry *) kmalloc(i, GFP_KERNEL);		for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++) {			c_entry[i].name = (char *) kmalloc(NFS_MAXNAMLEN + 1,				GFP_KERNEL);		}	}	entry = NULL;	/* try to find it in the cache */	if (inode->i_dev == c_dev && inode->i_ino == c_ino) {		for (i = 0; i < c_size; i++) {			if (filp->f_pos == c_entry[i].cookie) {				if (i == c_size - 1) {					if (c_entry[i].eof)						return 0;				}				else					entry = c_entry + i + 1;				break;			}		}	}	/* if we didn't find it in the cache, revert to an nfs call */	if (!entry) {		result = nfs_proc_readdir(NFS_SERVER(inode), NFS_FH(inode),			filp->f_pos, NFS_READDIR_CACHE_SIZE, c_entry);		if (result < 0) {			c_dev = 0;			return result;		}		if (result > 0) {			c_dev = inode->i_dev;			c_ino = inode->i_ino;			c_size = result;			entry = c_entry + 0;		}	}	/* if we found it in the cache or from an nfs call, return results */	if (entry) {		i = strlen(entry->name);		memcpy_tofs(dirent->d_name, entry->name, i + 1);		put_fs_long(entry->fileid, &dirent->d_ino);		put_fs_word(i, &dirent->d_reclen);		filp->f_pos = entry->cookie;		return i;	}	return 0;}/* * Lookup caching is a big win for performance but this is just * a trial to see how well it works on a small scale. * For example, bash does a lookup on ".." 13 times for each path * element when running pwd.  Yes, hard to believe but true. * Try pwd in a filesystem mounted with noac. * * It trades a little cpu time and memory for a lot of network bandwidth. * Since the cache is not hashed yet, it is a good idea not to make it too * large because every lookup looks through the entire cache even * though most of them will fail. */static struct nfs_lookup_cache_entry {	int dev;	int inode;	char filename[NFS_MAXNAMLEN + 1];	struct nfs_fh fhandle;	struct nfs_fattr fattr;	int expiration_date;} nfs_lookup_cache[NFS_LOOKUP_CACHE_SIZE];static struct nfs_lookup_cache_entry *nfs_lookup_cache_index(struct inode *dir,							     const char *filename){	struct nfs_lookup_cache_entry *entry;	int i;	for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {		entry = nfs_lookup_cache + i;		if (entry->dev == dir->i_dev && entry->inode == dir->i_ino		    && !strncmp(filename, entry->filename, NFS_MAXNAMLEN))			return entry;	}	return NULL;}static int nfs_lookup_cache_lookup(struct inode *dir, const char *filename,				   struct nfs_fh *fhandle,				   struct nfs_fattr *fattr){	static int nfs_lookup_cache_in_use = 0;	struct nfs_lookup_cache_entry *entry;	if (!nfs_lookup_cache_in_use) {		memset(nfs_lookup_cache, 0, sizeof(nfs_lookup_cache));		nfs_lookup_cache_in_use = 1;	}	if ((entry = nfs_lookup_cache_index(dir, filename))) {		if (jiffies > entry->expiration_date) {			entry->dev = 0;			return 0;		}		*fhandle = entry->fhandle;		*fattr = entry->fattr;		return 1;	}	return 0;}static void nfs_lookup_cache_add(struct inode *dir, const char *filename,				 struct nfs_fh *fhandle,				 struct nfs_fattr *fattr){	static int nfs_lookup_cache_pos = 0;	struct nfs_lookup_cache_entry *entry;	/* compensate for bug in SGI NFS server */	if (fattr->size == -1 || fattr->uid == -1 || fattr->gid == -1	    || fattr->atime.seconds == -1 || fattr->mtime.seconds == -1)		return;	if (!(entry = nfs_lookup_cache_index(dir, filename))) {		entry = nfs_lookup_cache + nfs_lookup_cache_pos++;		if (nfs_lookup_cache_pos == NFS_LOOKUP_CACHE_SIZE)			nfs_lookup_cache_pos = 0;	}	entry->dev = dir->i_dev;	entry->inode = dir->i_ino;	strcpy(entry->filename, filename);	entry->fhandle = *fhandle;	entry->fattr = *fattr;	entry->expiration_date = jiffies + (S_ISDIR(fattr->mode)		? NFS_SERVER(dir)->acdirmax : NFS_SERVER(dir)->acregmax);}static void nfs_lookup_cache_remove(struct inode *dir, struct inode *inode,				    const char *filename){	struct nfs_lookup_cache_entry *entry;	int dev;	int fileid;	int i;	if (inode) {		dev = inode->i_dev;		fileid = inode->i_ino;	}	else if ((entry = nfs_lookup_cache_index(dir, filename))) {		dev = entry->dev;		fileid = entry->fattr.fileid;	}	else		return;	for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {		entry = nfs_lookup_cache + i;		if (entry->dev == dev && entry->fattr.fileid == fileid)			entry->dev = 0;	}}static void nfs_lookup_cache_refresh(struct inode *file,				     struct nfs_fattr *fattr){	struct nfs_lookup_cache_entry *entry;	int dev = file->i_dev;	int fileid = file->i_ino;	int i;	for (i = 0; i < NFS_LOOKUP_CACHE_SIZE; i++) {		entry = nfs_lookup_cache + i;		if (entry->dev == dev && entry->fattr.fileid == fileid)			entry->fattr = *fattr;	}}static int nfs_lookup(struct inode *dir, const char *__name, int len,		      struct inode **result){	struct nfs_fh fhandle;	struct nfs_fattr fattr;	char name[len > NFS_MAXNAMLEN? 1 : len+1];	int error;	*result = NULL;	if (!dir || !S_ISDIR(dir->i_mode)) {		printk("nfs_lookup: inode is NULL or not a directory\n");		iput(dir);		return -ENOENT;	}	if (len > NFS_MAXNAMLEN) {		iput(dir);		return -ENAMETOOLONG;	}

⌨️ 快捷键说明

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