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

📄 super.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  linux/fs/nfs/super.c * *  Copyright (C) 1992  Rick Sladkey * *  nfs 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 * *  Split from inode.c by David Howells <dhowells@redhat.com> * * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a *   particular server are held in the same superblock * - NFS superblocks can have several effective roots to the dentry tree * - directory type roots are spliced into the tree when a path from one root reaches the root *   of another (see nfs_lookup()) */#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/sunrpc/metrics.h>#include <linux/sunrpc/xprtsock.h>#include <linux/sunrpc/xprtrdma.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 <linux/inet.h>#include <linux/nfs_xdr.h>#include <linux/magic.h>#include <linux/parser.h>#include <asm/system.h>#include <asm/uaccess.h>#include "nfs4_fs.h"#include "callback.h"#include "delegation.h"#include "iostat.h"#include "internal.h"#define NFSDBG_FACILITY		NFSDBG_VFSenum {	/* Mount options that take no arguments */	Opt_soft, Opt_hard,	Opt_intr, Opt_nointr,	Opt_posix, Opt_noposix,	Opt_cto, Opt_nocto,	Opt_ac, Opt_noac,	Opt_lock, Opt_nolock,	Opt_v2, Opt_v3,	Opt_udp, Opt_tcp, Opt_rdma,	Opt_acl, Opt_noacl,	Opt_rdirplus, Opt_nordirplus,	Opt_sharecache, Opt_nosharecache,	/* Mount options that take integer arguments */	Opt_port,	Opt_rsize, Opt_wsize, Opt_bsize,	Opt_timeo, Opt_retrans,	Opt_acregmin, Opt_acregmax,	Opt_acdirmin, Opt_acdirmax,	Opt_actimeo,	Opt_namelen,	Opt_mountport,	Opt_mountprog, Opt_mountvers,	Opt_nfsprog, Opt_nfsvers,	/* Mount options that take string arguments */	Opt_sec, Opt_proto, Opt_mountproto,	Opt_addr, Opt_mountaddr, Opt_clientaddr,	/* Mount options that are ignored */	Opt_userspace, Opt_deprecated,	Opt_err};static match_table_t nfs_mount_option_tokens = {	{ Opt_userspace, "bg" },	{ Opt_userspace, "fg" },	{ Opt_soft, "soft" },	{ Opt_hard, "hard" },	{ Opt_intr, "intr" },	{ Opt_nointr, "nointr" },	{ Opt_posix, "posix" },	{ Opt_noposix, "noposix" },	{ Opt_cto, "cto" },	{ Opt_nocto, "nocto" },	{ Opt_ac, "ac" },	{ Opt_noac, "noac" },	{ Opt_lock, "lock" },	{ Opt_nolock, "nolock" },	{ Opt_v2, "v2" },	{ Opt_v3, "v3" },	{ Opt_udp, "udp" },	{ Opt_tcp, "tcp" },	{ Opt_rdma, "rdma" },	{ Opt_acl, "acl" },	{ Opt_noacl, "noacl" },	{ Opt_rdirplus, "rdirplus" },	{ Opt_nordirplus, "nordirplus" },	{ Opt_sharecache, "sharecache" },	{ Opt_nosharecache, "nosharecache" },	{ Opt_port, "port=%u" },	{ Opt_rsize, "rsize=%u" },	{ Opt_wsize, "wsize=%u" },	{ Opt_bsize, "bsize=%u" },	{ Opt_timeo, "timeo=%u" },	{ Opt_retrans, "retrans=%u" },	{ Opt_acregmin, "acregmin=%u" },	{ Opt_acregmax, "acregmax=%u" },	{ Opt_acdirmin, "acdirmin=%u" },	{ Opt_acdirmax, "acdirmax=%u" },	{ Opt_actimeo, "actimeo=%u" },	{ Opt_userspace, "retry=%u" },	{ Opt_namelen, "namlen=%u" },	{ Opt_mountport, "mountport=%u" },	{ Opt_mountprog, "mountprog=%u" },	{ Opt_mountvers, "mountvers=%u" },	{ Opt_nfsprog, "nfsprog=%u" },	{ Opt_nfsvers, "nfsvers=%u" },	{ Opt_nfsvers, "vers=%u" },	{ Opt_sec, "sec=%s" },	{ Opt_proto, "proto=%s" },	{ Opt_mountproto, "mountproto=%s" },	{ Opt_addr, "addr=%s" },	{ Opt_clientaddr, "clientaddr=%s" },	{ Opt_userspace, "mounthost=%s" },	{ Opt_mountaddr, "mountaddr=%s" },	{ Opt_err, NULL }};enum {	Opt_xprt_udp, Opt_xprt_tcp, Opt_xprt_rdma,	Opt_xprt_err};static match_table_t nfs_xprt_protocol_tokens = {	{ Opt_xprt_udp, "udp" },	{ Opt_xprt_tcp, "tcp" },	{ Opt_xprt_rdma, "rdma" },	{ Opt_xprt_err, NULL }};enum {	Opt_sec_none, Opt_sec_sys,	Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p,	Opt_sec_lkey, Opt_sec_lkeyi, Opt_sec_lkeyp,	Opt_sec_spkm, Opt_sec_spkmi, Opt_sec_spkmp,	Opt_sec_err};static match_table_t nfs_secflavor_tokens = {	{ Opt_sec_none, "none" },	{ Opt_sec_none, "null" },	{ Opt_sec_sys, "sys" },	{ Opt_sec_krb5, "krb5" },	{ Opt_sec_krb5i, "krb5i" },	{ Opt_sec_krb5p, "krb5p" },	{ Opt_sec_lkey, "lkey" },	{ Opt_sec_lkeyi, "lkeyi" },	{ Opt_sec_lkeyp, "lkeyp" },	{ Opt_sec_err, NULL }};static void nfs_umount_begin(struct vfsmount *, int);static int  nfs_statfs(struct dentry *, struct kstatfs *);static int  nfs_show_options(struct seq_file *, struct vfsmount *);static int  nfs_show_stats(struct seq_file *, struct vfsmount *);static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *);static int nfs_xdev_get_sb(struct file_system_type *fs_type,		int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);static void nfs_kill_super(struct super_block *);static struct file_system_type nfs_fs_type = {	.owner		= THIS_MODULE,	.name		= "nfs",	.get_sb		= nfs_get_sb,	.kill_sb	= nfs_kill_super,	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,};struct file_system_type nfs_xdev_fs_type = {	.owner		= THIS_MODULE,	.name		= "nfs",	.get_sb		= nfs_xdev_get_sb,	.kill_sb	= nfs_kill_super,	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,};static const struct super_operations nfs_sops = {	.alloc_inode	= nfs_alloc_inode,	.destroy_inode	= nfs_destroy_inode,	.write_inode	= nfs_write_inode,	.statfs		= nfs_statfs,	.clear_inode	= nfs_clear_inode,	.umount_begin	= nfs_umount_begin,	.show_options	= nfs_show_options,	.show_stats	= nfs_show_stats,};#ifdef CONFIG_NFS_V4static int nfs4_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);static int nfs4_xdev_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);static int nfs4_referral_get_sb(struct file_system_type *fs_type,	int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt);static void nfs4_kill_super(struct super_block *sb);static struct file_system_type nfs4_fs_type = {	.owner		= THIS_MODULE,	.name		= "nfs4",	.get_sb		= nfs4_get_sb,	.kill_sb	= nfs4_kill_super,	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,};struct file_system_type nfs4_xdev_fs_type = {	.owner		= THIS_MODULE,	.name		= "nfs4",	.get_sb		= nfs4_xdev_get_sb,	.kill_sb	= nfs4_kill_super,	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,};struct file_system_type nfs4_referral_fs_type = {	.owner		= THIS_MODULE,	.name		= "nfs4",	.get_sb		= nfs4_referral_get_sb,	.kill_sb	= nfs4_kill_super,	.fs_flags	= FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA,};static const struct super_operations nfs4_sops = {	.alloc_inode	= nfs_alloc_inode,	.destroy_inode	= nfs_destroy_inode,	.write_inode	= nfs_write_inode,	.statfs		= nfs_statfs,	.clear_inode	= nfs4_clear_inode,	.umount_begin	= nfs_umount_begin,	.show_options	= nfs_show_options,	.show_stats	= nfs_show_stats,};#endifstatic struct shrinker acl_shrinker = {	.shrink		= nfs_access_cache_shrinker,	.seeks		= DEFAULT_SEEKS,};/* * Register the NFS filesystems */int __init register_nfs_fs(void){	int ret;        ret = register_filesystem(&nfs_fs_type);	if (ret < 0)		goto error_0;	ret = nfs_register_sysctl();	if (ret < 0)		goto error_1;#ifdef CONFIG_NFS_V4	ret = register_filesystem(&nfs4_fs_type);	if (ret < 0)		goto error_2;#endif	register_shrinker(&acl_shrinker);	return 0;#ifdef CONFIG_NFS_V4error_2:	nfs_unregister_sysctl();#endiferror_1:	unregister_filesystem(&nfs_fs_type);error_0:	return ret;}/* * Unregister the NFS filesystems */void __exit unregister_nfs_fs(void){	unregister_shrinker(&acl_shrinker);#ifdef CONFIG_NFS_V4	unregister_filesystem(&nfs4_fs_type);#endif	nfs_unregister_sysctl();	unregister_filesystem(&nfs_fs_type);}/* * Deliver file system statistics to userspace */static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf){	struct nfs_server *server = NFS_SB(dentry->d_sb);	unsigned char blockbits;	unsigned long blockres;	struct nfs_fh *fh = NFS_FH(dentry->d_inode);	struct nfs_fattr fattr;	struct nfs_fsstat res = {			.fattr = &fattr,	};	int error;	lock_kernel();	error = server->nfs_client->rpc_ops->statfs(server, fh, &res);	if (error < 0)		goto out_err;	buf->f_type = NFS_SUPER_MAGIC;	/*	 * Current versions of glibc do not correctly handle the	 * case where f_frsize != f_bsize.  Eventually we want to	 * report the value of wtmult in this field.	 */	buf->f_frsize = dentry->d_sb->s_blocksize;	/*	 * On most *nix systems, f_blocks, f_bfree, and f_bavail	 * are reported in units of f_frsize.  Linux hasn't had	 * an f_frsize field in its statfs struct until recently,	 * thus historically Linux's sys_statfs reports these	 * fields in units of f_bsize.	 */	buf->f_bsize = dentry->d_sb->s_blocksize;	blockbits = dentry->d_sb->s_blocksize_bits;	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;	buf->f_namelen = server->namelen;	unlock_kernel();	return 0; out_err:	dprintk("%s: statfs error = %d\n", __FUNCTION__, -error);	unlock_kernel();	return error;}/* * Map the security flavour number to a name */static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour){	static const struct {		rpc_authflavor_t flavour;		const char *str;	} sec_flavours[] = {		{ RPC_AUTH_NULL, "null" },		{ RPC_AUTH_UNIX, "sys" },		{ RPC_AUTH_GSS_KRB5, "krb5" },		{ RPC_AUTH_GSS_KRB5I, "krb5i" },		{ RPC_AUTH_GSS_KRB5P, "krb5p" },		{ RPC_AUTH_GSS_LKEY, "lkey" },		{ RPC_AUTH_GSS_LKEYI, "lkeyi" },		{ RPC_AUTH_GSS_LKEYP, "lkeyp" },		{ RPC_AUTH_GSS_SPKM, "spkm" },		{ RPC_AUTH_GSS_SPKMI, "spkmi" },		{ RPC_AUTH_GSS_SPKMP, "spkmp" },		{ UINT_MAX, "unknown" }	};	int i;	for (i = 0; sec_flavours[i].flavour != UINT_MAX; i++) {		if (sec_flavours[i].flavour == flavour)			break;	}	return sec_flavours[i].str;}/* * Describe the mount options in force on this server representation */static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults){	static const struct proc_nfs_info {		int flag;		const char *str;		const char *nostr;	} nfs_info[] = {		{ NFS_MOUNT_SOFT, ",soft", ",hard" },		{ NFS_MOUNT_INTR, ",intr", ",nointr" },		{ NFS_MOUNT_NOCTO, ",nocto", "" },		{ NFS_MOUNT_NOAC, ",noac", "" },		{ NFS_MOUNT_NONLM, ",nolock", "" },		{ NFS_MOUNT_NOACL, ",noacl", "" },		{ NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" },		{ NFS_MOUNT_UNSHARED, ",nosharecache", ""},		{ 0, NULL, NULL }	};	const struct proc_nfs_info *nfs_infop;	struct nfs_client *clp = nfss->nfs_client;	seq_printf(m, ",vers=%d", clp->rpc_ops->version);	seq_printf(m, ",rsize=%d", nfss->rsize);	seq_printf(m, ",wsize=%d", nfss->wsize);	if (nfss->acregmin != 3*HZ || showdefaults)		seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);	if (nfss->acregmax != 60*HZ || showdefaults)		seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);	if (nfss->acdirmin != 30*HZ || showdefaults)		seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);	if (nfss->acdirmax != 60*HZ || showdefaults)		seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {		if (nfss->flags & nfs_infop->flag)			seq_puts(m, nfs_infop->str);		else			seq_puts(m, nfs_infop->nostr);	}	seq_printf(m, ",proto=%s",		   rpc_peeraddr2str(nfss->client, RPC_DISPLAY_PROTO));	seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ);	seq_printf(m, ",retrans=%u", clp->retrans_count);	seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor));}/* * Describe the mount options on this VFS mountpoint */static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt){	struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);	nfs_show_mount_options(m, nfss, 0);	seq_printf(m, ",addr="NIPQUAD_FMT,		NIPQUAD(nfss->nfs_client->cl_addr.sin_addr));	return 0;}/* * Present statistical information for this VFS mountpoint */static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt){	int i, cpu;	struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);

⌨️ 快捷键说明

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