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

📄 inode.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/fs/nfs/inode.c * *  Copyright (C) 1992  Rick Sladkey * *  nfs inode and superblock handling functions * *  Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some *  experimental NFS changes. Modularisation taken straight from SYS5 fs. * *  Change to nfs_read_super() to permit NFS mounts to multi-homed hosts. *  J.S.Peatfield@damtp.cam.ac.uk * */#include <linux/config.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/locks.h>#include <linux/unistd.h>#include <linux/sunrpc/clnt.h>#include <linux/sunrpc/stats.h>#include <linux/nfs_fs.h>#include <linux/nfs_mount.h>#include <linux/nfs_flushd.h>#include <linux/lockd/bind.h>#include <linux/smp_lock.h>#include <asm/system.h>#include <asm/uaccess.h>#define CONFIG_NFS_SNAPSHOT 1#define NFSDBG_FACILITY		NFSDBG_VFS#define NFS_PARANOIA 1static struct inode * __nfs_fhget(struct super_block *, struct nfs_fh *, struct nfs_fattr *);void nfs_zap_caches(struct inode *);static void nfs_invalidate_inode(struct inode *);static void nfs_read_inode(struct inode *);static void nfs_delete_inode(struct inode *);static void nfs_put_super(struct super_block *);static void nfs_umount_begin(struct super_block *);static int  nfs_statfs(struct super_block *, struct statfs *);static struct super_operations nfs_sops = { 	read_inode:	nfs_read_inode,	put_inode:	force_delete,	delete_inode:	nfs_delete_inode,	put_super:	nfs_put_super,	statfs:		nfs_statfs,	umount_begin:	nfs_umount_begin,};/* * RPC cruft for NFS */struct rpc_stat			nfs_rpcstat = { &nfs_program };static struct rpc_version *	nfs_version[] = {	NULL,	NULL,	&nfs_version2,#ifdef CONFIG_NFS_V3	&nfs_version3,#endif};struct rpc_program		nfs_program = {	"nfs",	NFS_PROGRAM,	sizeof(nfs_version) / sizeof(nfs_version[0]),	nfs_version,	&nfs_rpcstat,};static inline unsigned longnfs_fattr_to_ino_t(struct nfs_fattr *fattr){	return nfs_fileid_to_ino_t(fattr->fileid);}/* * The "read_inode" function doesn't actually do anything: * the real data is filled in later in nfs_fhget. Here we * just mark the cache times invalid, and zero out i_mode * (the latter makes "nfs_refresh_inode" do the right thing * wrt pipe inodes) */static voidnfs_read_inode(struct inode * inode){	inode->i_blksize = inode->i_sb->s_blocksize;	inode->i_mode = 0;	inode->i_rdev = 0;	NFS_FILEID(inode) = 0;	NFS_FSID(inode) = 0;	INIT_LIST_HEAD(&inode->u.nfs_i.read);	INIT_LIST_HEAD(&inode->u.nfs_i.dirty);	INIT_LIST_HEAD(&inode->u.nfs_i.commit);	INIT_LIST_HEAD(&inode->u.nfs_i.writeback);	inode->u.nfs_i.nread = 0;	inode->u.nfs_i.ndirty = 0;	inode->u.nfs_i.ncommit = 0;	inode->u.nfs_i.npages = 0;	NFS_CACHEINV(inode);	NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);	NFS_ATTRTIMEO_UPDATE(inode) = jiffies;}static voidnfs_delete_inode(struct inode * inode){	dprintk("NFS: delete_inode(%x/%ld)\n", inode->i_dev, inode->i_ino);	/*	 * The following can never actually happen...	 */	if (nfs_have_writebacks(inode) || nfs_have_read(inode)) {		printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino);	}	clear_inode(inode);}voidnfs_put_super(struct super_block *sb){	struct nfs_server *server = &sb->u.nfs_sb.s_server;	struct rpc_clnt	*rpc;	/*	 * First get rid of the request flushing daemon.	 * Relies on rpc_shutdown_client() waiting on all	 * client tasks to finish.	 */	nfs_reqlist_exit(server);	if ((rpc = server->client) != NULL)		rpc_shutdown_client(rpc);	nfs_reqlist_free(server);	if (!(server->flags & NFS_MOUNT_NONLM))		lockd_down();	/* release rpc.lockd */	rpciod_down();		/* release rpciod */	kfree(server->hostname);}voidnfs_umount_begin(struct super_block *sb){	struct nfs_server *server = &sb->u.nfs_sb.s_server;	struct rpc_clnt	*rpc;	/* -EIO all pending I/O */	if ((rpc = server->client) != NULL)		rpc_killall_tasks(rpc);}static inline unsigned longnfs_block_bits(unsigned long bsize, unsigned char *nrbitsp){	/* make sure blocksize is a power of two */	if ((bsize & (bsize - 1)) || nrbitsp) {		unsigned char	nrbits;		for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--)			;		bsize = 1 << nrbits;		if (nrbitsp)			*nrbitsp = nrbits;	}	return bsize;}/* * Calculate the number of 512byte blocks used. */static inline unsigned longnfs_calc_block_size(u64 tsize){	loff_t used = (tsize + 511) >> 9;	return (used > ULONG_MAX) ? ULONG_MAX : used;}/* * Compute and set NFS server blocksize */static inline unsigned longnfs_block_size(unsigned long bsize, unsigned char *nrbitsp){	if (bsize < 1024)		bsize = NFS_DEF_FILE_IO_BUFFER_SIZE;	else if (bsize >= NFS_MAX_FILE_IO_BUFFER_SIZE)		bsize = NFS_MAX_FILE_IO_BUFFER_SIZE;	return nfs_block_bits(bsize, nrbitsp);}/* * Obtain the root inode of the file system. */static struct inode *nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh){	struct nfs_server	*server = &sb->u.nfs_sb.s_server;	struct nfs_fattr	fattr;	struct inode		*inode;	int			error;	if ((error = server->rpc_ops->getroot(server, rootfh, &fattr)) < 0) {		printk(KERN_NOTICE "nfs_get_root: getattr error = %d\n", -error);		return NULL;	}	inode = __nfs_fhget(sb, rootfh, &fattr);	return inode;}/* * The way this works is that the mount process passes a structure * in the data argument which contains the server's IP address * and the root file handle obtained from the server's mount * daemon. We stash these away in the private superblock fields. */struct super_block *nfs_read_super(struct super_block *sb, void *raw_data, int silent){	struct nfs_mount_data	*data = (struct nfs_mount_data *) raw_data;	struct nfs_server	*server;	struct rpc_xprt		*xprt = NULL;	struct rpc_clnt		*clnt = NULL;	struct nfs_fh		*root = &data->root, fh;	struct inode		*root_inode = NULL;	unsigned int		authflavor;	struct sockaddr_in	srvaddr;	struct rpc_timeout	timeparms;	struct nfs_fsinfo	fsinfo;	int			tcp, version, maxlen;	memset(&sb->u.nfs_sb, 0, sizeof(sb->u.nfs_sb));	if (!data)		goto out_miss_args;	memset(&fh, 0, sizeof(fh));	if (data->version != NFS_MOUNT_VERSION) {		printk("nfs warning: mount version %s than kernel\n",			data->version < NFS_MOUNT_VERSION ? "older" : "newer");		if (data->version < 2)			data->namlen = 0;		if (data->version < 3)			data->bsize  = 0;		if (data->version < 4) {			data->flags &= ~NFS_MOUNT_VER3;			root = &fh;			root->size = NFS2_FHSIZE;			memcpy(root->data, data->old_root.data, NFS2_FHSIZE);		}	}	/* We now require that the mount process passes the remote address */	memcpy(&srvaddr, &data->addr, sizeof(srvaddr));	if (srvaddr.sin_addr.s_addr == INADDR_ANY)		goto out_no_remote;	sb->s_magic      = NFS_SUPER_MAGIC;	sb->s_op         = &nfs_sops;	sb->s_blocksize_bits = 0;	sb->s_blocksize  = nfs_block_size(data->bsize, &sb->s_blocksize_bits);	server           = &sb->u.nfs_sb.s_server;	server->rsize    = nfs_block_size(data->rsize, NULL);	server->wsize    = nfs_block_size(data->wsize, NULL);	server->flags    = data->flags & NFS_MOUNT_FLAGMASK;	if (data->flags & NFS_MOUNT_NOAC) {		data->acregmin = data->acregmax = 0;		data->acdirmin = data->acdirmax = 0;	}	server->acregmin = data->acregmin*HZ;	server->acregmax = data->acregmax*HZ;	server->acdirmin = data->acdirmin*HZ;	server->acdirmax = data->acdirmax*HZ;	server->namelen  = data->namlen;	server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);	if (!server->hostname)		goto out_unlock;	strcpy(server->hostname, data->hostname); nfsv3_try_again:	/* Check NFS protocol revision and initialize RPC op vector	 * and file handle pool. */	if (data->flags & NFS_MOUNT_VER3) {#ifdef CONFIG_NFS_V3		server->rpc_ops = &nfs_v3_clientops;		version = 3;		if (data->version < 4) {			printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");			goto out_unlock;		}#else		printk(KERN_NOTICE "NFS: NFSv3 not supported.\n");		goto out_unlock;#endif	} else {		server->rpc_ops = &nfs_v2_clientops;		version = 2;        }	/* Which protocol do we use? */	tcp   = (data->flags & NFS_MOUNT_TCP);	/* Initialize timeout values */	timeparms.to_initval = data->timeo * HZ / 10;	timeparms.to_retries = data->retrans;	timeparms.to_maxval  = tcp? RPC_MAX_TCP_TIMEOUT : RPC_MAX_UDP_TIMEOUT;	timeparms.to_exponential = 1;	if (!timeparms.to_initval)		timeparms.to_initval = (tcp ? 600 : 11) * HZ / 10;	if (!timeparms.to_retries)		timeparms.to_retries = 5;	/* Now create transport and client */	xprt = xprt_create_proto(tcp? IPPROTO_TCP : IPPROTO_UDP,						&srvaddr, &timeparms);	if (xprt == NULL)		goto out_no_xprt;	/* Choose authentication flavor */	authflavor = RPC_AUTH_UNIX;	if (data->flags & NFS_MOUNT_SECURE)		authflavor = RPC_AUTH_DES;	else if (data->flags & NFS_MOUNT_KERBEROS)		authflavor = RPC_AUTH_KRB;	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,				 version, authflavor);	if (clnt == NULL)		goto out_no_client;	clnt->cl_intr     = (data->flags & NFS_MOUNT_INTR)? 1 : 0;	clnt->cl_softrtry = (data->flags & NFS_MOUNT_SOFT)? 1 : 0;	clnt->cl_droppriv = (data->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;	clnt->cl_chatty   = 1;	server->client    = clnt;	/* Fire up rpciod if not yet running */	if (rpciod_up() != 0)		goto out_no_iod;	/*	 * Keep the super block locked while we try to get 	 * the root fh attributes.	 */	/* Did getting the root inode fail? */	if (!(root_inode = nfs_get_root(sb, root))	    && (data->flags & NFS_MOUNT_VER3)) {		data->flags &= ~NFS_MOUNT_VER3;		rpciod_down();		rpc_shutdown_client(server->client);		goto nfsv3_try_again;	}	if (!root_inode)		goto out_no_root;	sb->s_root = d_alloc_root(root_inode);	if (!sb->s_root)		goto out_no_root;	sb->s_root->d_op = &nfs_dentry_operations;	/* Get some general file system info */        if (server->rpc_ops->statfs(server, root, &fsinfo) >= 0) {		if (server->namelen == 0)			server->namelen = fsinfo.namelen;	} else {		printk(KERN_NOTICE "NFS: cannot retrieve file system info.\n");		goto out_no_root;        }	/* Work out a lot of parameters */	if (data->rsize == 0)		server->rsize = nfs_block_size(fsinfo.rtpref, NULL);	if (data->wsize == 0)		server->wsize = nfs_block_size(fsinfo.wtpref, NULL);	/* NFSv3: we don't have bsize, but rather rtmult and wtmult... */	if (!fsinfo.bsize)		fsinfo.bsize = (fsinfo.rtmult>fsinfo.wtmult) ? fsinfo.rtmult : fsinfo.wtmult;	/* Also make sure we don't go below rsize/wsize since	 * RPC calls are expensive */	if (fsinfo.bsize < server->rsize)		fsinfo.bsize = server->rsize;	if (fsinfo.bsize < server->wsize)		fsinfo.bsize = server->wsize;	if (data->bsize == 0)		sb->s_blocksize = nfs_block_bits(fsinfo.bsize, &sb->s_blocksize_bits);	if (server->rsize > fsinfo.rtmax)		server->rsize = fsinfo.rtmax;	if (server->wsize > fsinfo.wtmax)		server->wsize = fsinfo.wtmax;	server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;	if (server->rpages > NFS_READ_MAXIOV) {		server->rpages = NFS_READ_MAXIOV;		server->rsize = server->rpages << PAGE_CACHE_SHIFT;	}	server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;        if (server->wpages > NFS_WRITE_MAXIOV) {		server->wpages = NFS_WRITE_MAXIOV;                server->wsize = server->wpages << PAGE_CACHE_SHIFT;	}	server->dtsize = nfs_block_size(fsinfo.dtpref, NULL);	if (server->dtsize > PAGE_CACHE_SIZE)		server->dtsize = PAGE_CACHE_SIZE;	if (server->dtsize > server->rsize)		server->dtsize = server->rsize;        maxlen = (version == 2) ? NFS2_MAXNAMLEN : NFS3_MAXNAMLEN;        if (server->namelen == 0 || server->namelen > maxlen)                server->namelen = maxlen;	/* Fire up the writeback cache */	if (nfs_reqlist_alloc(server) < 0) {		printk(KERN_NOTICE "NFS: cannot initialize writeback cache.\n");		goto failure_kill_reqlist;	}	/* We're airborne */	/* Check whether to start the lockd process */	if (!(server->flags & NFS_MOUNT_NONLM))		lockd_up();	return sb;	/* Yargs. It didn't work out. */ failure_kill_reqlist:	nfs_reqlist_exit(server);out_no_root:	printk("nfs_read_super: get root inode failed\n");	iput(root_inode);	rpciod_down();	goto out_shutdown;out_no_iod:	printk(KERN_WARNING "NFS: couldn't start rpciod!\n");out_shutdown:	rpc_shutdown_client(server->client);	goto out_free_host;out_no_client:	printk(KERN_WARNING "NFS: cannot create RPC client.\n");	xprt_destroy(xprt);	goto out_free_host;out_no_xprt:	printk(KERN_WARNING "NFS: cannot create RPC transport.\n");out_free_host:	nfs_reqlist_free(server);	kfree(server->hostname);out_unlock:	goto out_fail;out_no_remote:	printk("NFS: mount program didn't pass remote address!\n");	goto out_fail;out_miss_args:	printk("nfs_read_super: missing data argument\n");out_fail:	return NULL;}static intnfs_statfs(struct super_block *sb, struct statfs *buf){	struct nfs_server *server = &sb->u.nfs_sb.s_server;	unsigned char blockbits;	unsigned long blockres;	struct nfs_fsinfo res;	int error;	error = server->rpc_ops->statfs(server, NFS_FH(sb->s_root->d_inode), &res);	buf->f_type = NFS_SUPER_MAGIC;	if (error < 0)		goto out_err;	if (res.bsize == 0)		res.bsize = sb->s_blocksize;	buf->f_bsize = nfs_block_bits(res.bsize, &blockbits);	blockres = (1 << blockbits) - 1;	buf->f_blocks = (res.tbytes + blockres) >> blockbits;	buf->f_bfree = (res.fbytes + blockres) >> blockbits;	buf->f_bavail = (res.abytes + blockres) >> blockbits;	buf->f_files = res.tfiles;	buf->f_ffree = res.afiles;	if (res.namelen == 0 || res.namelen > server->namelen)		res.namelen = server->namelen;	buf->f_namelen = res.namelen;	return 0; out_err:	printk("nfs_statfs: statfs error = %d\n", -error);	buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;	return 0;}/* * Invalidate the local caches */voidnfs_zap_caches(struct inode *inode){	NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);	NFS_ATTRTIMEO_UPDATE(inode) = jiffies;	invalidate_inode_pages(inode);	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));	NFS_CACHEINV(inode);}/* * Invalidate, but do not unhash, the inode */static voidnfs_invalidate_inode(struct inode *inode){	umode_t save_mode = inode->i_mode;	make_bad_inode(inode);	inode->i_mode = save_mode;	nfs_zap_caches(inode);}/* * Fill in inode information from the fattr.

⌨️ 快捷键说明

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