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

📄 nfsctl.c

📁 《嵌入式系统设计与实例开发实验教材二源码》Linux内核移植与编译实验
💻 C
字号:
/* * linux/fs/nfsd/nfsctl.c * * Syscall interface to knfsd. * * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> */#include <linux/config.h>#include <linux/module.h>#include <linux/version.h>#include <linux/linkage.h>#include <linux/sched.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/fcntl.h>#include <linux/net.h>#include <linux/in.h>#include <linux/unistd.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/nfs.h>#include <linux/sunrpc/svc.h>#include <linux/nfsd/nfsd.h>#include <linux/nfsd/cache.h>#include <linux/nfsd/xdr.h>#include <linux/nfsd/syscall.h>#include <asm/uaccess.h>#include <linux/smp.h>#include <linux/smp_lock.h>static int	nfsctl_svc(struct nfsctl_svc *data);static int	nfsctl_addclient(struct nfsctl_client *data);static int	nfsctl_delclient(struct nfsctl_client *data);static int	nfsctl_export(struct nfsctl_export *data);static int	nfsctl_unexport(struct nfsctl_export *data);static int	nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);static int	nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);static int	nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);#ifdef notyetstatic int	nfsctl_ugidupdate(struct nfsctl_ugidmap *data);#endifstatic int	initialized;int exp_procfs_exports(char *buffer, char **start, off_t offset,                             int length, int *eof, void *data);void proc_export_init(void){	if (!proc_mkdir("fs/nfs", 0))		return;	create_proc_read_entry("fs/nfs/exports", 0, 0, exp_procfs_exports,NULL);}/* * Initialize nfsd */static voidnfsd_init(void){	nfsd_stat_init();	/* Statistics */	nfsd_cache_init();	/* RPC reply cache */	nfsd_export_init();	/* Exports table */	nfsd_lockd_init();	/* lockd->nfsd callbacks */	proc_export_init();	initialized = 1;}static inline intnfsctl_svc(struct nfsctl_svc *data){	return nfsd_svc(data->svc_port, data->svc_nthreads);}static inline intnfsctl_addclient(struct nfsctl_client *data){	return exp_addclient(data);}static inline intnfsctl_delclient(struct nfsctl_client *data){	return exp_delclient(data);}static inline intnfsctl_export(struct nfsctl_export *data){	return exp_export(data);}static inline intnfsctl_unexport(struct nfsctl_export *data){	return exp_unexport(data);}#ifdef notyetstatic inline intnfsctl_ugidupdate(nfs_ugidmap *data){	return -EINVAL;}#endifstatic inline intnfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res){	struct sockaddr_in	*sin;	struct svc_client	*clp;	int			err = 0;	if (data->gd_addr.sa_family != AF_INET)		return -EPROTONOSUPPORT;	sin = (struct sockaddr_in *)&data->gd_addr;	if (data->gd_maxlen > NFS3_FHSIZE)		data->gd_maxlen = NFS3_FHSIZE;	exp_readlock();	if (!(clp = exp_getclient(sin)))		err = -EPERM;	else		err = exp_rootfh(clp, 0, 0, data->gd_path, res, data->gd_maxlen);	exp_unlock();	return err;}static inline intnfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res){	struct sockaddr_in	*sin;	struct svc_client	*clp;	int			err = 0;	struct	knfsd_fh	fh;	if (data->gd_addr.sa_family != AF_INET)		return -EPROTONOSUPPORT;	if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)		return -EINVAL;	sin = (struct sockaddr_in *)&data->gd_addr;	exp_readlock();	if (!(clp = exp_getclient(sin)))		err = -EPERM;	else		err = exp_rootfh(clp, 0, 0, data->gd_path, &fh, NFS_FHSIZE);	exp_unlock();	if (err == 0) {		if (fh.fh_size > NFS_FHSIZE)			err = -EINVAL;		else {			memset(res,0, NFS_FHSIZE);			memcpy(res, &fh.fh_base, fh.fh_size);		}	}	return err;}static inline intnfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res){	struct sockaddr_in	*sin;	struct svc_client	*clp;	int			err = 0;	struct knfsd_fh		fh;	if (data->gf_addr.sa_family != AF_INET)		return -EPROTONOSUPPORT;	if (data->gf_version < 2 || data->gf_version > NFSSVC_MAXVERS)		return -EINVAL;	sin = (struct sockaddr_in *)&data->gf_addr;	exp_readlock();	if (!(clp = exp_getclient(sin)))		err = -EPERM;	else		err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);	exp_unlock();	if (err == 0) {		if (fh.fh_size > NFS_FHSIZE)			err = -EINVAL;		else {			memset(res,0, NFS_FHSIZE);			memcpy(res, &fh.fh_base, fh.fh_size);		}	}	return err;}#ifdef CONFIG_NFSD#define handle_sys_nfsservctl sys_nfsservctl#endifstatic struct {	int argsize, respsize;}  sizes[] = {	/* NFSCTL_SVC        */ { sizeof(struct nfsctl_svc), 0 },	/* NFSCTL_ADDCLIENT  */ { sizeof(struct nfsctl_client), 0},	/* NFSCTL_DELCLIENT  */ { sizeof(struct nfsctl_client), 0},	/* NFSCTL_EXPORT     */ { sizeof(struct nfsctl_export), 0},	/* NFSCTL_UNEXPORT   */ { sizeof(struct nfsctl_export), 0},	/* NFSCTL_UGIDUPDATE */ { sizeof(struct nfsctl_uidmap), 0},	/* NFSCTL_GETFH      */ { sizeof(struct nfsctl_fhparm), NFS_FHSIZE},	/* NFSCTL_GETFD      */ { sizeof(struct nfsctl_fdparm), NFS_FHSIZE},	/* NFSCTL_GETFS      */ { sizeof(struct nfsctl_fsparm), sizeof(struct knfsd_fh)},};#define CMD_MAX (sizeof(sizes)/sizeof(sizes[0])-1)longasmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp){	struct nfsctl_arg *	argp = opaque_argp;	union nfsctl_res *	resp = opaque_resp;	struct nfsctl_arg *	arg = NULL;	union nfsctl_res *	res = NULL;	int			err;	int			argsize, respsize;	MOD_INC_USE_COUNT;	lock_kernel ();	if (!initialized)		nfsd_init();	err = -EPERM;	if (!capable(CAP_SYS_ADMIN)) {		goto done;	}	err = -EINVAL;	if (cmd<0 || cmd > CMD_MAX)		goto done;	err = -EFAULT;	argsize = sizes[cmd].argsize + (int)&((struct nfsctl_arg *)0)->u;	respsize = sizes[cmd].respsize;	/* maximum */	if (!access_ok(VERIFY_READ, argp, argsize)	 || (resp && !access_ok(VERIFY_WRITE, resp, respsize))) {		goto done;	}	err = -ENOMEM;	/* ??? */	if (!(arg = kmalloc(sizeof(*arg), GFP_USER)) ||	    (resp && !(res = kmalloc(sizeof(*res), GFP_USER)))) {		goto done;	}	err = -EINVAL;	copy_from_user(arg, argp, argsize);	if (arg->ca_version != NFSCTL_VERSION) {		printk(KERN_WARNING "nfsd: incompatible version in syscall.\n");		goto done;	}	switch(cmd) {	case NFSCTL_SVC:		err = nfsctl_svc(&arg->ca_svc);		break;	case NFSCTL_ADDCLIENT:		err = nfsctl_addclient(&arg->ca_client);		break;	case NFSCTL_DELCLIENT:		err = nfsctl_delclient(&arg->ca_client);		break;	case NFSCTL_EXPORT:		err = nfsctl_export(&arg->ca_export);		break;	case NFSCTL_UNEXPORT:		err = nfsctl_unexport(&arg->ca_export);		break;#ifdef notyet	case NFSCTL_UGIDUPDATE:		err = nfsctl_ugidupdate(&arg->ca_umap);		break;#endif	case NFSCTL_GETFH:		err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);		break;	case NFSCTL_GETFD:		err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);		break;	case NFSCTL_GETFS:		err = nfsctl_getfs(&arg->ca_getfs, &res->cr_getfs);		respsize = res->cr_getfs.fh_size+ (int)&((struct knfsd_fh*)0)->fh_base;		break;	default:		err = -EINVAL;	}	if (!err && resp && respsize)		copy_to_user(resp, res, respsize);done:	if (arg)		kfree(arg);	if (res)		kfree(res);	unlock_kernel ();	MOD_DEC_USE_COUNT;	return err;}#ifdef MODULE/* New-style module support since 2.1.18 */EXPORT_NO_SYMBOLS;MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");MODULE_LICENSE("GPL");struct nfsd_linkage nfsd_linkage_s = {	do_nfsservctl: handle_sys_nfsservctl,};/* * Initialize the module */intinit_module(void){	printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");	nfsd_linkage = &nfsd_linkage_s;	return 0;}/* * Clean up the mess before unloading the module */voidcleanup_module(void){	nfsd_linkage = NULL;	nfsd_export_shutdown();	nfsd_cache_shutdown();	remove_proc_entry("fs/nfs/exports", NULL);	remove_proc_entry("fs/nfs", NULL);	nfsd_stat_shutdown();	nfsd_lockd_shutdown();}#endif

⌨️ 快捷键说明

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