2 * linux/fs/nfsd/nfsctl.c
4 * Syscall interface to knfsd.
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
10 #include <linux/config.h>
11 #include <linux/module.h>
12 #include <linux/version.h>
14 #include <linux/linkage.h>
15 #include <linux/sched.h>
16 #include <linux/errno.h>
18 #include <linux/fcntl.h>
19 #include <linux/net.h>
21 #include <linux/version.h>
22 #include <linux/unistd.h>
23 #include <linux/malloc.h>
24 #include <linux/proc_fs.h>
26 #include <linux/nfs.h>
27 #include <linux/sunrpc/svc.h>
28 #include <linux/nfsd/nfsd.h>
29 #include <linux/nfsd/cache.h>
30 #include <linux/nfsd/xdr.h>
31 #include <linux/nfsd/syscall.h>
33 #if LINUX_VERSION_CODE >= 0x020100
34 #include <asm/uaccess.h>
36 # define copy_from_user memcpy_fromfs
37 # define copy_to_user memcpy_tofs
38 # define access_ok !verify_area
40 #include <linux/smp.h>
41 #include <linux/smp_lock.h>
43 extern void nfsd_fh_init(void);
44 extern long sys_call_table
[];
46 static int nfsctl_svc(struct nfsctl_svc
*data
);
47 static int nfsctl_addclient(struct nfsctl_client
*data
);
48 static int nfsctl_delclient(struct nfsctl_client
*data
);
49 static int nfsctl_export(struct nfsctl_export
*data
);
50 static int nfsctl_unexport(struct nfsctl_export
*data
);
51 static int nfsctl_getfh(struct nfsctl_fhparm
*, struct knfs_fh
*);
52 static int nfsctl_getfd(struct nfsctl_fdparm
*, struct knfs_fh
*);
53 /* static int nfsctl_ugidupdate(struct nfsctl_ugidmap *data); */
55 static int initialized
= 0;
57 int exp_procfs_exports(char *buffer
, char **start
, off_t offset
,
58 int length
, int *eof
, void *data
);
60 void proc_export_init(void)
62 struct proc_dir_entry
*nfs_export_ent
= NULL
;
64 if (!(nfs_export_ent
= create_proc_entry("fs/nfs", S_IFDIR
, 0)))
66 if (!(nfs_export_ent
= create_proc_entry("fs/nfs/exports", 0, 0)))
68 nfs_export_ent
->read_proc
= exp_procfs_exports
;
78 nfsd_xdr_init(); /* XDR */
79 nfsd_stat_init(); /* Statistics */
80 nfsd_cache_init(); /* RPC reply cache */
81 nfsd_export_init(); /* Exports table */
82 nfsd_lockd_init(); /* lockd->nfsd callbacks */
83 nfsd_fh_init(); /* FH table */
89 nfsctl_svc(struct nfsctl_svc
*data
)
91 return nfsd_svc(data
->svc_port
, data
->svc_nthreads
);
95 nfsctl_addclient(struct nfsctl_client
*data
)
97 return exp_addclient(data
);
101 nfsctl_delclient(struct nfsctl_client
*data
)
103 return exp_delclient(data
);
107 nfsctl_export(struct nfsctl_export
*data
)
109 return exp_export(data
);
113 nfsctl_unexport(struct nfsctl_export
*data
)
115 return exp_unexport(data
);
120 nfsctl_ugidupdate(nfs_ugidmap
*data
)
127 nfsctl_getfd(struct nfsctl_fdparm
*data
, struct knfs_fh
*res
)
129 struct sockaddr_in
*sin
;
130 struct svc_client
*clp
;
133 if (data
->gd_addr
.sa_family
!= AF_INET
)
134 return -EPROTONOSUPPORT
;
135 if (data
->gd_version
< 2 || data
->gd_version
> NFSSVC_MAXVERS
)
137 sin
= (struct sockaddr_in
*)&data
->gd_addr
;
140 if (!(clp
= exp_getclient(sin
)))
143 err
= exp_rootfh(clp
, 0, 0, data
->gd_path
, res
);
150 nfsctl_getfh(struct nfsctl_fhparm
*data
, struct knfs_fh
*res
)
152 struct sockaddr_in
*sin
;
153 struct svc_client
*clp
;
156 if (data
->gf_addr
.sa_family
!= AF_INET
)
157 return -EPROTONOSUPPORT
;
158 if (data
->gf_version
< 2 || data
->gf_version
> NFSSVC_MAXVERS
)
160 sin
= (struct sockaddr_in
*)&data
->gf_addr
;
163 if (!(clp
= exp_getclient(sin
)))
166 err
= exp_rootfh(clp
, to_kdev_t(data
->gf_dev
), data
->gf_ino
, NULL
, res
);
173 #define handle_sys_nfsservctl sys_nfsservctl
177 asmlinkage
handle_sys_nfsservctl(int cmd
, void *opaque_argp
, void *opaque_resp
)
179 struct nfsctl_arg
* argp
= opaque_argp
;
180 union nfsctl_res
* resp
= opaque_resp
;
181 struct nfsctl_arg
* arg
= NULL
;
182 union nfsctl_res
* res
= NULL
;
190 if (!capable(CAP_SYS_ADMIN
)) {
194 if (!access_ok(VERIFY_READ
, argp
, sizeof(*argp
))
195 || (resp
&& !access_ok(VERIFY_WRITE
, resp
, sizeof(*resp
)))) {
199 err
= -ENOMEM
; /* ??? */
200 if (!(arg
= kmalloc(sizeof(*arg
), GFP_USER
)) ||
201 (resp
&& !(res
= kmalloc(sizeof(*res
), GFP_USER
)))) {
206 copy_from_user(arg
, argp
, sizeof(*argp
));
207 if (arg
->ca_version
!= NFSCTL_VERSION
) {
208 printk(KERN_WARNING
"nfsd: incompatible version in syscall.\n");
214 err
= nfsctl_svc(&arg
->ca_svc
);
216 case NFSCTL_ADDCLIENT
:
217 err
= nfsctl_addclient(&arg
->ca_client
);
219 case NFSCTL_DELCLIENT
:
220 err
= nfsctl_delclient(&arg
->ca_client
);
223 err
= nfsctl_export(&arg
->ca_export
);
225 case NFSCTL_UNEXPORT
:
226 err
= nfsctl_unexport(&arg
->ca_export
);
229 case NFSCTL_UGIDUPDATE
:
230 err
= nfsctl_ugidupdate(&arg
->ca_umap
);
234 err
= nfsctl_getfh(&arg
->ca_getfh
, &res
->cr_getfh
);
237 err
= nfsctl_getfd(&arg
->ca_getfd
, &res
->cr_getfh
);
244 copy_to_user(resp
, res
, sizeof(*resp
));
258 /* New-style module support since 2.1.18 */
259 #if LINUX_VERSION_CODE >= 131346
261 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
264 extern int (*do_nfsservctl
)(int, void *, void *);
267 * This is called as the fill_inode function when an inode
268 * is going into (fill = 1) or out of service (fill = 0).
270 * We use it here to make sure the module can't be unloaded
271 * while a /proc inode is in use.
273 void nfsd_modcount(struct inode
*inode
, int fill
)
282 * Initialize the module
287 printk("Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n");
288 do_nfsservctl
= handle_sys_nfsservctl
;
293 * Clean up the mess before unloading the module
299 printk("nfsd: nfsd busy, remove delayed\n");
302 do_nfsservctl
= NULL
;
303 nfsd_export_shutdown();
304 nfsd_cache_shutdown();
306 remove_proc_entry("fs/nfs/exports", NULL
);
307 remove_proc_entry("fs/nfs", NULL
);
308 nfsd_stat_shutdown();
309 nfsd_lockd_shutdown();