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

📄 dir.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/nfs/dir.c * *  Copyright (C) 1992  Rick Sladkey * *  nfs directory handling functions * * 10 Apr 1996	Added silly rename for unlink	--okir */#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_open(struct inode * inode, struct file * file);static int nfs_dir_read(struct inode *, struct file *, char *, int);static int nfs_readdir(struct inode *, struct file *, void *, filldir_t);static int nfs_lookup(struct inode *, const char *, int, struct inode **);static int nfs_create(struct inode *, const char *, int, int, struct inode **);static int nfs_mkdir(struct inode *, const char *, int, int);static int nfs_rmdir(struct inode *, const char *, int);static int nfs_unlink(struct inode *, const char *, int);static int nfs_symlink(struct inode *, const char *, int, const char *);static int nfs_link(struct inode *, struct inode *, const char *, int);static int nfs_mknod(struct inode *, const char *, int, int, int);static int nfs_rename(struct inode *, const char *, int,		      struct inode *, const char *, int, int);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 */	nfs_dir_open,		/* open - revalidate */	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,			/* readpage */	NULL,			/* writepage */	NULL,			/* bmap */	NULL,			/* truncate */	NULL			/* permission */};static inline void revalidate_dir(struct nfs_server * server, struct inode * dir){	struct nfs_fattr fattr;	if (jiffies - NFS_READTIME(dir) < NFS_ATTRTIMEO(dir))		return;	NFS_READTIME(dir) = jiffies;	if (nfs_proc_getattr(server, NFS_FH(dir), &fattr) == 0) {		nfs_refresh_inode(dir, &fattr);		if (fattr.mtime.seconds == NFS_OLDMTIME(dir)) {			if ((NFS_ATTRTIMEO(dir) <<= 1) > server->acdirmax)				NFS_ATTRTIMEO(dir) = server->acdirmax;			return;		}		NFS_OLDMTIME(dir) = fattr.mtime.seconds;	}	/* invalidate directory cache here when we _really_ start caching */}static int nfs_dir_open(struct inode * dir, struct file * file){	revalidate_dir(NFS_SERVER(dir), dir);	return 0;}static int nfs_dir_read(struct inode *inode, struct file *filp, char *buf,			int count){	return -EISDIR;}static struct nfs_entry *c_entry = NULL;/* * 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,		       void *dirent, filldir_t filldir){	static kdev_t c_dev = 0;	static int c_ino;	static int c_size;	int result;	int i, index = 0;	struct nfs_entry *entry;	if (!inode || !S_ISDIR(inode->i_mode)) {		printk("nfs_readdir: inode is NULL or not a directory\n");		return -EBADF;	}	revalidate_dir(NFS_SERVER(inode), inode);	/* 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);		if (c_entry == NULL) {			printk("nfs_readdir: no MEMORY for cache\n");			return -ENOMEM;		}		for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++) {			c_entry[i].name = (char *) kmalloc(NFS_MAXNAMLEN + 1,				GFP_KERNEL);			if (c_entry[i].name == NULL) {				printk("nfs_readdir: no MEMORY for cache\n");				while (--i>=0)					kfree(c_entry[i].name);				kfree(c_entry);				c_entry = NULL;				return -ENOMEM;			}		}	}	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 + (index = 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 + (index = 0);		}	}	/* if we found it in the cache or from an nfs call, return results */	if (!entry)		return 0;	while (index < c_size) {		int nextpos = entry->cookie;		if (filldir(dirent, entry->name, strlen(entry->name), filp->f_pos, entry->fileid) < 0)			break;		filp->f_pos = nextpos;		/* revalidate the cache if we slept in filldir() */		if (inode->i_dev != c_dev)			break;		if (inode->i_ino != c_ino)			break;		if (nextpos != entry->cookie)			break;		index++;		entry++;	}	return 0;}/* * free cache memory * called from cleanup_module */void nfs_kfree_cache(void){	int i;	if (c_entry == NULL)		return;	for (i = 0; i < NFS_READDIR_CACHE_SIZE; i++)		kfree(c_entry[i].name);	kfree(c_entry);	c_entry = NULL;} /* * 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 {	kdev_t 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)->acdirmin : NFS_SERVER(dir)->acregmin);}static void nfs_lookup_cache_remove(struct inode *dir, struct inode *inode,				    const char *filename){	struct nfs_lookup_cache_entry *entry;	kdev_t 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;	kdev_t 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;	}	memcpy(name,__name,len);	name[len] = '\0';	if (len == 1 && name[0] == '.') { /* cheat for "." */

⌨️ 快捷键说明

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