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

📄 inode.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  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/init.h>#include <linux/time.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/string.h>#include <linux/stat.h>#include <linux/errno.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/nfs4_mount.h>#include <linux/lockd/bind.h>#include <linux/smp_lock.h>#include <linux/seq_file.h>#include <linux/mount.h>#include <linux/nfs_idmap.h>#include <linux/vfs.h>#include <asm/system.h>#include <asm/uaccess.h>#include "delegation.h"#define NFSDBG_FACILITY		NFSDBG_VFS#define NFS_PARANOIA 1/* Maximum number of readahead requests * FIXME: this should really be a sysctl so that users may tune it to suit *        their needs. People that do NFS over a slow network, might for *        instance want to reduce it to something closer to 1 for improved *        interactive response. */#define NFS_MAX_READAHEAD	(RPC_DEF_SLOT_TABLE - 1)static void nfs_invalidate_inode(struct inode *);static int nfs_update_inode(struct inode *, struct nfs_fattr *, unsigned long);static struct inode *nfs_alloc_inode(struct super_block *sb);static void nfs_destroy_inode(struct inode *);static int nfs_write_inode(struct inode *,int);static void nfs_delete_inode(struct inode *);static void nfs_clear_inode(struct inode *);static void nfs_umount_begin(struct super_block *);static int  nfs_statfs(struct super_block *, struct kstatfs *);static int  nfs_show_options(struct seq_file *, struct vfsmount *);static struct super_operations nfs_sops = { 	.alloc_inode	= nfs_alloc_inode,	.destroy_inode	= nfs_destroy_inode,	.write_inode	= nfs_write_inode,	.delete_inode	= nfs_delete_inode,	.statfs		= nfs_statfs,	.clear_inode	= nfs_clear_inode,	.umount_begin	= nfs_umount_begin,	.show_options	= nfs_show_options,};/* * RPC cruft for NFS */struct rpc_stat			nfs_rpcstat = {	.program		= &nfs_program};static struct rpc_version *	nfs_version[] = {	NULL,	NULL,	&nfs_version2,#if defined(CONFIG_NFS_V3)	&nfs_version3,#elif defined(CONFIG_NFS_V4)	NULL,#endif#if defined(CONFIG_NFS_V4)	&nfs_version4,#endif};struct rpc_program		nfs_program = {	.name			= "nfs",	.number			= NFS_PROGRAM,	.nrvers			= sizeof(nfs_version) / sizeof(nfs_version[0]),	.version		= nfs_version,	.stats			= &nfs_rpcstat,	.pipe_dir_name		= "/nfs",};static inline unsigned longnfs_fattr_to_ino_t(struct nfs_fattr *fattr){	return nfs_fileid_to_ino_t(fattr->fileid);}static intnfs_write_inode(struct inode *inode, int sync){	int flags = sync ? FLUSH_WAIT : 0;	int ret;	ret = nfs_commit_inode(inode, 0, 0, flags);	if (ret < 0)		return ret;	return 0;}static voidnfs_delete_inode(struct inode * inode){	dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino);	nfs_wb_all(inode);	/*	 * The following should never happen...	 */	if (nfs_have_writebacks(inode)) {		printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino);	}	clear_inode(inode);}/* * For the moment, the only task for the NFS clear_inode method is to * release the mmap credential */static voidnfs_clear_inode(struct inode *inode){	struct nfs_inode *nfsi = NFS_I(inode);	struct rpc_cred *cred;	nfs_wb_all(inode);	BUG_ON (!list_empty(&nfsi->open_files));	cred = nfsi->cache_access.cred;	if (cred)		put_rpccred(cred);	BUG_ON(atomic_read(&nfsi->data_updates) != 0);}voidnfs_umount_begin(struct super_block *sb){	struct nfs_server *server = NFS_SB(sb);	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_fsinfo *fsinfo){	struct nfs_server	*server = NFS_SB(sb);	struct inode *rooti;	int			error;	error = server->rpc_ops->getroot(server, rootfh, fsinfo);	if (error < 0) {		dprintk("nfs_get_root: getattr error = %d\n", -error);		return ERR_PTR(error);	}	rooti = nfs_fhget(sb, rootfh, fsinfo->fattr);	if (!rooti)		return ERR_PTR(-ENOMEM);	return rooti;}/* * Do NFS version-independent mount processing, and sanity checking */static intnfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor){	struct nfs_server	*server;	struct inode		*root_inode;	struct nfs_fattr	fattr;	struct nfs_fsinfo	fsinfo = {					.fattr = &fattr,				};	struct nfs_pathconf pathinfo = {			.fattr = &fattr,	};	int no_root_error = 0;	/* We probably want something more informative here */	snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));	server = NFS_SB(sb);	sb->s_magic      = NFS_SUPER_MAGIC;	root_inode = nfs_get_root(sb, &server->fh, &fsinfo);	/* Did getting the root inode fail? */	if (IS_ERR(root_inode)) {		no_root_error = PTR_ERR(root_inode);		goto out_no_root;	}	sb->s_root = d_alloc_root(root_inode);	if (!sb->s_root) {		no_root_error = -ENOMEM;		goto out_no_root;	}	sb->s_root->d_op = server->rpc_ops->dentry_ops;	/* Get some general file system info */	if (server->namelen == 0 &&	    server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0)		server->namelen = pathinfo.max_namelen;	/* Work out a lot of parameters */	if (server->rsize == 0)		server->rsize = nfs_block_size(fsinfo.rtpref, NULL);	if (server->wsize == 0)		server->wsize = nfs_block_size(fsinfo.wtpref, NULL);	if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax)		server->rsize = nfs_block_size(fsinfo.rtmax, NULL);	if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)		server->wsize = nfs_block_size(fsinfo.wtmax, NULL);	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;	}	if (sb->s_blocksize == 0)		sb->s_blocksize = nfs_block_bits(server->wsize,							 &sb->s_blocksize_bits);	server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL);	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;	if (server->flags & NFS_MOUNT_NOAC) {		server->acregmin = server->acregmax = 0;		server->acdirmin = server->acdirmax = 0;		sb->s_flags |= MS_SYNCHRONOUS;	}	server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD;	sb->s_maxbytes = fsinfo.maxfilesize;	if (sb->s_maxbytes > MAX_LFS_FILESIZE) 		sb->s_maxbytes = MAX_LFS_FILESIZE; 	/* We're airborne Set socket buffersize */	rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);	return 0;	/* Yargs. It didn't work out. */out_no_root:	dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error);	if (!IS_ERR(root_inode))		iput(root_inode);	return no_root_error;}/* * Create an RPC client handle. */static struct rpc_clnt *nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data){	struct rpc_timeout	timeparms;	struct rpc_xprt		*xprt = NULL;	struct rpc_clnt		*clnt = NULL;	int			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;	/* create transport and client */	xprt = xprt_create_proto(tcp ? IPPROTO_TCP : IPPROTO_UDP,				 &server->addr, &timeparms);	if (IS_ERR(xprt)) {		printk(KERN_WARNING "NFS: cannot create RPC transport.\n");		return (struct rpc_clnt *)xprt;	}	clnt = rpc_create_client(xprt, server->hostname, &nfs_program,				 server->rpc_ops->version, data->pseudoflavor);	if (IS_ERR(clnt)) {		printk(KERN_WARNING "NFS: cannot create RPC client.\n");		goto out_fail;	}	clnt->cl_intr     = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;	clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;	clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;	clnt->cl_chatty   = 1;	return clnt;out_fail:	xprt_destroy(xprt);	return clnt;}/* * 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. */static intnfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent){	struct nfs_server	*server;	rpc_authflavor_t	authflavor;	server           = NFS_SB(sb);	sb->s_blocksize_bits = 0;	sb->s_blocksize = 0;	if (data->bsize)		sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits);	if (data->rsize)		server->rsize = nfs_block_size(data->rsize, NULL);	if (data->wsize)		server->wsize = nfs_block_size(data->wsize, NULL);	server->flags    = data->flags & NFS_MOUNT_FLAGMASK;	server->acregmin = data->acregmin*HZ;	server->acregmax = data->acregmax*HZ;	server->acdirmin = data->acdirmin*HZ;	server->acdirmax = data->acdirmax*HZ;	/* Start lockd here, before we might error out */	if (!(server->flags & NFS_MOUNT_NONLM))		lockd_up();	server->namelen  = data->namlen;	server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL);	if (!server->hostname)		return -ENOMEM;	strcpy(server->hostname, data->hostname);	/* Check NFS protocol revision and initialize RPC op vector	 * and file handle pool. */	if (server->flags & NFS_MOUNT_VER3) {#ifdef CONFIG_NFS_V3		server->rpc_ops = &nfs_v3_clientops;		server->caps |= NFS_CAP_READDIRPLUS;		if (data->version < 4) {			printk(KERN_NOTICE "NFS: NFSv3 not supported by mount program.\n");			return -EIO;		}#else		printk(KERN_NOTICE "NFS: NFSv3 not supported.\n");		return -EIO;#endif	} else {		server->rpc_ops = &nfs_v2_clientops;	}	/* Fill in pseudoflavor for mount version < 5 */	if (!(data->flags & NFS_MOUNT_SECFLAVOUR))		data->pseudoflavor = RPC_AUTH_UNIX;	authflavor = data->pseudoflavor;	/* save for sb_init() */	/* XXX maybe we want to add a server->pseudoflavor field */	/* Create RPC client handles */	server->client = nfs_create_client(server, data);	if (IS_ERR(server->client))		return PTR_ERR(server->client);	/* RFC 2623, sec 2.3.2 */	if (authflavor != RPC_AUTH_UNIX) {		server->client_sys = rpc_clone_client(server->client);		if (IS_ERR(server->client_sys))			return PTR_ERR(server->client_sys);		if (!rpcauth_create(RPC_AUTH_UNIX, server->client_sys))			return -ENOMEM;	} else {		atomic_inc(&server->client->cl_count);		server->client_sys = server->client;	}	if (server->flags & NFS_MOUNT_VER3) {		if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN)			server->namelen = NFS3_MAXNAMLEN;	} else {		if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN)			server->namelen = NFS2_MAXNAMLEN;	}	sb->s_op = &nfs_sops;	return nfs_sb_init(sb, authflavor);}static intnfs_statfs(struct super_block *sb, struct kstatfs *buf){	struct nfs_server *server = NFS_SB(sb);	unsigned char blockbits;	unsigned long blockres;	struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode);	struct nfs_fattr fattr;	struct nfs_fsstat res = {			.fattr = &fattr,	};	int error;	lock_kernel();	error = server->rpc_ops->statfs(server, rootfh, &res);	buf->f_type = NFS_SUPER_MAGIC;	if (error < 0)		goto out_err;

⌨️ 快捷键说明

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