99 #include <sys/clconf.h>
100
101 #include <sys/tsol/label.h>
102
103 #define MAXHOST 32
104 const char *kinet_ntop6(uchar_t *, char *, size_t);
105
106 /*
107 * Module linkage information.
108 */
109
110 static struct modlmisc modlmisc = {
111 &mod_miscops, "NFS server module"
112 };
113
114 static struct modlinkage modlinkage = {
115 MODREV_1, (void *)&modlmisc, NULL
116 };
117
118 zone_key_t nfssrv_zone_key;
119 kmem_cache_t *nfs_xuio_cache;
120 int nfs_loaned_buffers = 0;
121
122 int
123 _init(void)
124 {
125 int status;
126
127 nfs_srvinit();
128
129 status = mod_install((struct modlinkage *)&modlinkage);
130 if (status != 0) {
131 /*
132 * Could not load module, cleanup previous
133 * initialization work.
134 */
135 nfs_srvfini();
136
137 return (status);
138 }
184 #define PUBLICFH_CHECK(ne, disp, exi, fsid, xfid) \
185 ((disp->dis_flags & RPC_PUBLICFH_OK) && \
186 ((exi->exi_export.ex_flags & EX_PUBLIC) || \
187 (exi == ne->exi_public && exportmatch(ne->exi_root, \
188 fsid, xfid))))
189
190 static void nfs_srv_shutdown_all(int);
191 static void rfs4_server_start(nfs_globals_t *, int);
192 static void nullfree(void);
193 static void rfs_dispatch(struct svc_req *, SVCXPRT *);
194 static void acl_dispatch(struct svc_req *, SVCXPRT *);
195 static void common_dispatch(struct svc_req *, SVCXPRT *,
196 rpcvers_t, rpcvers_t, char *,
197 struct rpc_disptable *);
198 static int checkauth(struct exportinfo *, struct svc_req *, cred_t *, int,
199 bool_t, bool_t *);
200 static char *client_name(struct svc_req *req);
201 static char *client_addr(struct svc_req *req, char *buf);
202 extern int sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
203 extern bool_t sec_svc_inrootlist(int, caddr_t, int, caddr_t *);
204 static void *nfs_srv_zone_init(zoneid_t);
205 static void nfs_srv_zone_fini(zoneid_t, void *);
206
207 #define NFSLOG_COPY_NETBUF(exi, xprt, nb) { \
208 (nb)->maxlen = (xprt)->xp_rtaddr.maxlen; \
209 (nb)->len = (xprt)->xp_rtaddr.len; \
210 (nb)->buf = kmem_alloc((nb)->len, KM_SLEEP); \
211 bcopy((xprt)->xp_rtaddr.buf, (nb)->buf, (nb)->len); \
212 }
213
214 /*
215 * Public Filehandle common nfs routines
216 */
217 static int MCLpath(char **);
218 static void URLparse(char *);
219
220 /*
221 * NFS callout table.
222 * This table is used by svc_getreq() to dispatch a request with
223 * a given prog/vers pair to an appropriate service provider
224 * dispatch routine.
225 *
246 };
247
248 static SVC_CALLOUT __nfs_sc_rdma[] = {
249 { NFS_PROGRAM, NFS_VERSMIN, NFS_VERSMAX, rfs_dispatch },
250 { NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, acl_dispatch }
251 };
252
253 static SVC_CALLOUT_TABLE nfs_sct_rdma = {
254 sizeof (__nfs_sc_rdma) / sizeof (__nfs_sc_rdma[0]), FALSE, __nfs_sc_rdma
255 };
256
257 /*
258 * DSS: distributed stable storage
259 * lists of all DSS paths: current, and before last warmstart
260 */
261 nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths;
262
263 int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *);
264 bool_t rfs4_minorvers_mismatch(struct svc_req *, SVCXPRT *, void *);
265
266 /*
267 * Will be called at the point the server pool is being unregistered
268 * from the pool list. From that point onwards, the pool is waiting
269 * to be drained and as such the server state is stale and pertains
270 * to the old instantiation of the NFS server pool.
271 */
272 void
273 nfs_srv_offline(void)
274 {
275 nfs_globals_t *ng;
276
277 ng = zone_getspecific(nfssrv_zone_key, curzone);
278
279 mutex_enter(&ng->nfs_server_upordown_lock);
280 if (ng->nfs_server_upordown == NFS_SERVER_RUNNING) {
281 ng->nfs_server_upordown = NFS_SERVER_OFFLINE;
282 }
283 mutex_exit(&ng->nfs_server_upordown_lock);
284 }
285
286 /*
287 * Will be called at the point the server pool is being destroyed so
288 * all transports have been closed and no service threads are in
289 * existence.
290 *
291 * If we quiesce the server, we're shutting it down without destroying the
292 * server state. This allows it to warm start subsequently.
293 */
294 void
295 nfs_srv_stop_all(void)
296 {
297 int quiesce = 0;
298 nfs_srv_shutdown_all(quiesce);
299 }
300
301 /*
302 * This alternative shutdown routine can be requested via nfssys()
303 */
304 void
305 nfs_srv_quiesce_all(void)
306 {
307 int quiesce = 1;
308 nfs_srv_shutdown_all(quiesce);
309 }
310
311 static void
312 nfs_srv_shutdown_all(int quiesce)
313 {
314 nfs_globals_t *ng = zone_getspecific(nfssrv_zone_key, curzone);
315
316 mutex_enter(&ng->nfs_server_upordown_lock);
317 if (quiesce) {
318 if (ng->nfs_server_upordown == NFS_SERVER_RUNNING ||
319 ng->nfs_server_upordown == NFS_SERVER_OFFLINE) {
320 ng->nfs_server_upordown = NFS_SERVER_QUIESCED;
321 cv_signal(&ng->nfs_server_upordown_cv);
322
323 /* reset DSS state */
324 rfs4_dss_numnewpaths = 0;
325 rfs4_dss_newpaths = NULL;
326
327 cmn_err(CE_NOTE, "nfs_server: server is now quiesced; "
328 "NFSv4 state has been preserved");
329 }
330 } else {
331 if (ng->nfs_server_upordown == NFS_SERVER_OFFLINE) {
332 ng->nfs_server_upordown = NFS_SERVER_STOPPING;
333 mutex_exit(&ng->nfs_server_upordown_lock);
334 rfs4_state_zone_fini();
409 * uap->fd is the fd of an open transport provider
410 */
411 int
412 nfs_svc(struct nfs_svc_args *arg, model_t model)
413 {
414 nfs_globals_t *ng;
415 file_t *fp;
416 SVCMASTERXPRT *xprt;
417 int error;
418 int readsize;
419 char buf[KNC_STRSIZE];
420 size_t len;
421 STRUCT_HANDLE(nfs_svc_args, uap);
422 struct netbuf addrmask;
423 SVC_CALLOUT_TABLE *sctp = NULL;
424
425 #ifdef lint
426 model = model; /* STRUCT macros don't always refer to it */
427 #endif
428
429 ng = zone_getspecific(nfssrv_zone_key, curzone);
430 STRUCT_SET_HANDLE(uap, model, arg);
431
432 /* Check privileges in nfssys() */
433
434 if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL)
435 return (EBADF);
436
437 /*
438 * Set read buffer size to rsize
439 * and add room for RPC headers.
440 */
441 readsize = nfs3tsize() + (RPC_MAXDATASIZE - NFS_MAXDATA);
442 if (readsize < RPC_MAXDATASIZE)
443 readsize = RPC_MAXDATASIZE;
444
445 error = copyinstr((const char *)STRUCT_FGETP(uap, netid), buf,
446 KNC_STRSIZE, &len);
447 if (error) {
448 releasef(STRUCT_FGET(uap, fd));
449 return (error);
450 }
451
452 addrmask.len = STRUCT_FGET(uap, addrmask.len);
453 addrmask.maxlen = STRUCT_FGET(uap, addrmask.maxlen);
454 addrmask.buf = kmem_alloc(addrmask.maxlen, KM_SLEEP);
455 error = copyin(STRUCT_FGETP(uap, addrmask.buf), addrmask.buf,
456 addrmask.len);
535 * If RDMA device available,
536 * start RDMA listener.
537 */
538 int
539 rdma_start(struct rdma_svc_args *rsa)
540 {
541 nfs_globals_t *ng;
542 int error;
543 rdma_xprt_group_t started_rdma_xprts;
544 rdma_stat stat;
545 int svc_state = 0;
546
547 /* Double check the vers min/max ranges */
548 if ((rsa->nfs_versmin > rsa->nfs_versmax) ||
549 (rsa->nfs_versmin < NFS_VERSMIN) ||
550 (rsa->nfs_versmax > NFS_VERSMAX)) {
551 rsa->nfs_versmin = NFS_VERSMIN_DEFAULT;
552 rsa->nfs_versmax = NFS_VERSMAX_DEFAULT;
553 }
554
555 ng = zone_getspecific(nfssrv_zone_key, curzone);
556 ng->nfs_versmin = rsa->nfs_versmin;
557 ng->nfs_versmax = rsa->nfs_versmax;
558
559 /* Set the versions in the callout table */
560 __nfs_sc_rdma[0].sc_versmin = rsa->nfs_versmin;
561 __nfs_sc_rdma[0].sc_versmax = rsa->nfs_versmax;
562 /* For the NFS_ACL program, check the max version */
563 __nfs_sc_rdma[1].sc_versmin = rsa->nfs_versmin;
564 if (rsa->nfs_versmax > NFS_ACL_VERSMAX)
565 __nfs_sc_rdma[1].sc_versmax = NFS_ACL_VERSMAX;
566 else
567 __nfs_sc_rdma[1].sc_versmax = rsa->nfs_versmax;
568
569 /* Initialize nfsv4 server */
570 if (rsa->nfs_versmax == (rpcvers_t)NFS_V4)
571 rfs4_server_start(ng, rsa->delegation);
572
573 started_rdma_xprts.rtg_count = 0;
574 started_rdma_xprts.rtg_listhead = NULL;
575 started_rdma_xprts.rtg_poolid = rsa->poolid;
2530 /*
2531 * No IP address to print. If there was a host name
2532 * printed, then we print a space.
2533 */
2534 (void) sprintf(buf, frontspace);
2535 }
2536
2537 return (buf);
2538 }
2539
2540 /*
2541 * NFS Server initialization routine. This routine should only be called
2542 * once. It performs the following tasks:
2543 * - Call sub-initialization routines (localize access to variables)
2544 * - Initialize all locks
2545 * - initialize the version 3 write verifier
2546 */
2547 void
2548 nfs_srvinit(void)
2549 {
2550 /* NFS server zone-specific global variables */
2551 zone_key_create(&nfssrv_zone_key, nfs_srv_zone_init,
2552 NULL, nfs_srv_zone_fini);
2553
2554 nfs_exportinit();
2555 rfs_srvrinit();
2556 rfs3_srvrinit();
2557 rfs4_srvrinit();
2558 nfsauth_init();
2559 }
2560
2561 /*
2562 * NFS Server finalization routine. This routine is called to cleanup the
2563 * initialization work previously performed if the NFS server module could
2564 * not be loaded correctly.
2565 */
2566 void
2567 nfs_srvfini(void)
2568 {
2569 nfsauth_fini();
2570 rfs4_srvrfini();
2571 rfs3_srvrfini();
2572 rfs_srvrfini();
2573 nfs_exportfini();
2574
2575 (void) zone_key_delete(nfssrv_zone_key);
2576 }
2577
2578 /* ARGSUSED */
2579 static void *
2580 nfs_srv_zone_init(zoneid_t zoneid)
2581 {
2582 nfs_globals_t *ng;
2583
2584 ng = kmem_zalloc(sizeof (*ng), KM_SLEEP);
2585
2586 ng->nfs_versmin = NFS_VERSMIN_DEFAULT;
2587 ng->nfs_versmax = NFS_VERSMAX_DEFAULT;
2588
2589 /* Init the stuff to control start/stop */
2590 ng->nfs_server_upordown = NFS_SERVER_STOPPED;
2591 mutex_init(&ng->nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL);
2592 cv_init(&ng->nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL);
2593 mutex_init(&ng->rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL);
2594 cv_init(&ng->rdma_wait_cv, NULL, CV_DEFAULT, NULL);
2595
2596 return (ng);
2597 }
2598
2599 /* ARGSUSED */
2600 static void
2601 nfs_srv_zone_fini(zoneid_t zoneid, void *data)
2602 {
2603 nfs_globals_t *ng;
2604
2605 ng = (nfs_globals_t *)data;
2606 mutex_destroy(&ng->nfs_server_upordown_lock);
2607 cv_destroy(&ng->nfs_server_upordown_cv);
2608 mutex_destroy(&ng->rdma_wait_mutex);
2609 cv_destroy(&ng->rdma_wait_cv);
2610
2611 kmem_free(ng, sizeof (*ng));
2612 }
2613
2614 /*
2615 * Set up an iovec array of up to cnt pointers.
2616 */
2617 void
2618 mblk_to_iov(mblk_t *m, int cnt, struct iovec *iovp)
2619 {
2620 while (m != NULL && cnt-- > 0) {
2621 iovp->iov_base = (caddr_t)m->b_rptr;
2622 iovp->iov_len = (m->b_wptr - m->b_rptr);
2623 iovp++;
2624 m = m->b_cont;
2625 }
|
99 #include <sys/clconf.h>
100
101 #include <sys/tsol/label.h>
102
103 #define MAXHOST 32
104 const char *kinet_ntop6(uchar_t *, char *, size_t);
105
106 /*
107 * Module linkage information.
108 */
109
110 static struct modlmisc modlmisc = {
111 &mod_miscops, "NFS server module"
112 };
113
114 static struct modlinkage modlinkage = {
115 MODREV_1, (void *)&modlmisc, NULL
116 };
117
118 zone_key_t nfssrv_zone_key;
119 list_t nfssrv_globals_list;
120 krwlock_t nfssrv_globals_rwl;
121
122 kmem_cache_t *nfs_xuio_cache;
123 int nfs_loaned_buffers = 0;
124
125 int
126 _init(void)
127 {
128 int status;
129
130 nfs_srvinit();
131
132 status = mod_install((struct modlinkage *)&modlinkage);
133 if (status != 0) {
134 /*
135 * Could not load module, cleanup previous
136 * initialization work.
137 */
138 nfs_srvfini();
139
140 return (status);
141 }
187 #define PUBLICFH_CHECK(ne, disp, exi, fsid, xfid) \
188 ((disp->dis_flags & RPC_PUBLICFH_OK) && \
189 ((exi->exi_export.ex_flags & EX_PUBLIC) || \
190 (exi == ne->exi_public && exportmatch(ne->exi_root, \
191 fsid, xfid))))
192
193 static void nfs_srv_shutdown_all(int);
194 static void rfs4_server_start(nfs_globals_t *, int);
195 static void nullfree(void);
196 static void rfs_dispatch(struct svc_req *, SVCXPRT *);
197 static void acl_dispatch(struct svc_req *, SVCXPRT *);
198 static void common_dispatch(struct svc_req *, SVCXPRT *,
199 rpcvers_t, rpcvers_t, char *,
200 struct rpc_disptable *);
201 static int checkauth(struct exportinfo *, struct svc_req *, cred_t *, int,
202 bool_t, bool_t *);
203 static char *client_name(struct svc_req *req);
204 static char *client_addr(struct svc_req *req, char *buf);
205 extern int sec_svc_getcred(struct svc_req *, cred_t *cr, char **, int *);
206 extern bool_t sec_svc_inrootlist(int, caddr_t, int, caddr_t *);
207 static void *nfs_server_zone_init(zoneid_t);
208 static void nfs_server_zone_fini(zoneid_t, void *);
209 static void nfs_server_zone_shutdown(zoneid_t, void *);
210
211 #define NFSLOG_COPY_NETBUF(exi, xprt, nb) { \
212 (nb)->maxlen = (xprt)->xp_rtaddr.maxlen; \
213 (nb)->len = (xprt)->xp_rtaddr.len; \
214 (nb)->buf = kmem_alloc((nb)->len, KM_SLEEP); \
215 bcopy((xprt)->xp_rtaddr.buf, (nb)->buf, (nb)->len); \
216 }
217
218 /*
219 * Public Filehandle common nfs routines
220 */
221 static int MCLpath(char **);
222 static void URLparse(char *);
223
224 /*
225 * NFS callout table.
226 * This table is used by svc_getreq() to dispatch a request with
227 * a given prog/vers pair to an appropriate service provider
228 * dispatch routine.
229 *
250 };
251
252 static SVC_CALLOUT __nfs_sc_rdma[] = {
253 { NFS_PROGRAM, NFS_VERSMIN, NFS_VERSMAX, rfs_dispatch },
254 { NFS_ACL_PROGRAM, NFS_ACL_VERSMIN, NFS_ACL_VERSMAX, acl_dispatch }
255 };
256
257 static SVC_CALLOUT_TABLE nfs_sct_rdma = {
258 sizeof (__nfs_sc_rdma) / sizeof (__nfs_sc_rdma[0]), FALSE, __nfs_sc_rdma
259 };
260
261 /*
262 * DSS: distributed stable storage
263 * lists of all DSS paths: current, and before last warmstart
264 */
265 nvlist_t *rfs4_dss_paths, *rfs4_dss_oldpaths;
266
267 int rfs4_dispatch(struct rpcdisp *, struct svc_req *, SVCXPRT *, char *);
268 bool_t rfs4_minorvers_mismatch(struct svc_req *, SVCXPRT *, void *);
269
270 nfs_globals_t *
271 nfs_srv_getzg(void)
272 {
273 nfs_globals_t *ng;
274
275 ng = zone_getspecific(nfssrv_zone_key, curzone);
276 return (ng);
277 }
278
279 /*
280 * Will be called at the point the server pool is being unregistered
281 * from the pool list. From that point onwards, the pool is waiting
282 * to be drained and as such the server state is stale and pertains
283 * to the old instantiation of the NFS server pool.
284 */
285 void
286 nfs_srv_offline(void)
287 {
288 nfs_globals_t *ng;
289
290 ng = nfs_srv_getzg();
291
292 mutex_enter(&ng->nfs_server_upordown_lock);
293 if (ng->nfs_server_upordown == NFS_SERVER_RUNNING) {
294 ng->nfs_server_upordown = NFS_SERVER_OFFLINE;
295 }
296 mutex_exit(&ng->nfs_server_upordown_lock);
297 }
298
299 /*
300 * Will be called at the point the server pool is being destroyed so
301 * all transports have been closed and no service threads are in
302 * existence.
303 *
304 * If we quiesce the server, we're shutting it down without destroying the
305 * server state. This allows it to warm start subsequently.
306 */
307 void
308 nfs_srv_stop_all(void)
309 {
310 int quiesce = 0;
311 nfs_srv_shutdown_all(quiesce);
312 }
313
314 /*
315 * This alternative shutdown routine can be requested via nfssys()
316 */
317 void
318 nfs_srv_quiesce_all(void)
319 {
320 int quiesce = 1;
321 nfs_srv_shutdown_all(quiesce);
322 }
323
324 static void
325 nfs_srv_shutdown_all(int quiesce)
326 {
327 nfs_globals_t *ng = nfs_srv_getzg();
328
329 mutex_enter(&ng->nfs_server_upordown_lock);
330 if (quiesce) {
331 if (ng->nfs_server_upordown == NFS_SERVER_RUNNING ||
332 ng->nfs_server_upordown == NFS_SERVER_OFFLINE) {
333 ng->nfs_server_upordown = NFS_SERVER_QUIESCED;
334 cv_signal(&ng->nfs_server_upordown_cv);
335
336 /* reset DSS state */
337 rfs4_dss_numnewpaths = 0;
338 rfs4_dss_newpaths = NULL;
339
340 cmn_err(CE_NOTE, "nfs_server: server is now quiesced; "
341 "NFSv4 state has been preserved");
342 }
343 } else {
344 if (ng->nfs_server_upordown == NFS_SERVER_OFFLINE) {
345 ng->nfs_server_upordown = NFS_SERVER_STOPPING;
346 mutex_exit(&ng->nfs_server_upordown_lock);
347 rfs4_state_zone_fini();
422 * uap->fd is the fd of an open transport provider
423 */
424 int
425 nfs_svc(struct nfs_svc_args *arg, model_t model)
426 {
427 nfs_globals_t *ng;
428 file_t *fp;
429 SVCMASTERXPRT *xprt;
430 int error;
431 int readsize;
432 char buf[KNC_STRSIZE];
433 size_t len;
434 STRUCT_HANDLE(nfs_svc_args, uap);
435 struct netbuf addrmask;
436 SVC_CALLOUT_TABLE *sctp = NULL;
437
438 #ifdef lint
439 model = model; /* STRUCT macros don't always refer to it */
440 #endif
441
442 ng = nfs_srv_getzg();
443 STRUCT_SET_HANDLE(uap, model, arg);
444
445 /* Check privileges in nfssys() */
446
447 if ((fp = getf(STRUCT_FGET(uap, fd))) == NULL)
448 return (EBADF);
449
450 /* Setup global file handle in nfs_export */
451 if ((error = nfs_export_get_rootfh(ng)) != 0)
452 return (error);
453
454 /*
455 * Set read buffer size to rsize
456 * and add room for RPC headers.
457 */
458 readsize = nfs3tsize() + (RPC_MAXDATASIZE - NFS_MAXDATA);
459 if (readsize < RPC_MAXDATASIZE)
460 readsize = RPC_MAXDATASIZE;
461
462 error = copyinstr((const char *)STRUCT_FGETP(uap, netid), buf,
463 KNC_STRSIZE, &len);
464 if (error) {
465 releasef(STRUCT_FGET(uap, fd));
466 return (error);
467 }
468
469 addrmask.len = STRUCT_FGET(uap, addrmask.len);
470 addrmask.maxlen = STRUCT_FGET(uap, addrmask.maxlen);
471 addrmask.buf = kmem_alloc(addrmask.maxlen, KM_SLEEP);
472 error = copyin(STRUCT_FGETP(uap, addrmask.buf), addrmask.buf,
473 addrmask.len);
552 * If RDMA device available,
553 * start RDMA listener.
554 */
555 int
556 rdma_start(struct rdma_svc_args *rsa)
557 {
558 nfs_globals_t *ng;
559 int error;
560 rdma_xprt_group_t started_rdma_xprts;
561 rdma_stat stat;
562 int svc_state = 0;
563
564 /* Double check the vers min/max ranges */
565 if ((rsa->nfs_versmin > rsa->nfs_versmax) ||
566 (rsa->nfs_versmin < NFS_VERSMIN) ||
567 (rsa->nfs_versmax > NFS_VERSMAX)) {
568 rsa->nfs_versmin = NFS_VERSMIN_DEFAULT;
569 rsa->nfs_versmax = NFS_VERSMAX_DEFAULT;
570 }
571
572 ng = nfs_srv_getzg();
573 ng->nfs_versmin = rsa->nfs_versmin;
574 ng->nfs_versmax = rsa->nfs_versmax;
575
576 /* Set the versions in the callout table */
577 __nfs_sc_rdma[0].sc_versmin = rsa->nfs_versmin;
578 __nfs_sc_rdma[0].sc_versmax = rsa->nfs_versmax;
579 /* For the NFS_ACL program, check the max version */
580 __nfs_sc_rdma[1].sc_versmin = rsa->nfs_versmin;
581 if (rsa->nfs_versmax > NFS_ACL_VERSMAX)
582 __nfs_sc_rdma[1].sc_versmax = NFS_ACL_VERSMAX;
583 else
584 __nfs_sc_rdma[1].sc_versmax = rsa->nfs_versmax;
585
586 /* Initialize nfsv4 server */
587 if (rsa->nfs_versmax == (rpcvers_t)NFS_V4)
588 rfs4_server_start(ng, rsa->delegation);
589
590 started_rdma_xprts.rtg_count = 0;
591 started_rdma_xprts.rtg_listhead = NULL;
592 started_rdma_xprts.rtg_poolid = rsa->poolid;
2547 /*
2548 * No IP address to print. If there was a host name
2549 * printed, then we print a space.
2550 */
2551 (void) sprintf(buf, frontspace);
2552 }
2553
2554 return (buf);
2555 }
2556
2557 /*
2558 * NFS Server initialization routine. This routine should only be called
2559 * once. It performs the following tasks:
2560 * - Call sub-initialization routines (localize access to variables)
2561 * - Initialize all locks
2562 * - initialize the version 3 write verifier
2563 */
2564 void
2565 nfs_srvinit(void)
2566 {
2567
2568 /* Truly global stuff in this module (not per zone) */
2569 rw_init(&nfssrv_globals_rwl, NULL, RW_DEFAULT, NULL);
2570 list_create(&nfssrv_globals_list, sizeof (nfs_globals_t),
2571 offsetof (nfs_globals_t, nfs_g_link));
2572
2573 /* The order here is important */
2574 nfs_exportinit();
2575 rfs_srvrinit();
2576 rfs3_srvrinit();
2577 rfs4_srvrinit();
2578 nfsauth_init();
2579
2580 /*
2581 * NFS server zone-specific global variables
2582 * Note the zone_init is called for the GZ here.
2583 */
2584 zone_key_create(&nfssrv_zone_key, nfs_server_zone_init,
2585 nfs_server_zone_shutdown, nfs_server_zone_fini);
2586 }
2587
2588 /*
2589 * NFS Server finalization routine. This routine is called to cleanup the
2590 * initialization work previously performed if the NFS server module could
2591 * not be loaded correctly.
2592 */
2593 void
2594 nfs_srvfini(void)
2595 {
2596
2597 /*
2598 * NFS server zone-specific global variables
2599 * Note the zone_fini is called for the GZ here.
2600 */
2601 (void) zone_key_delete(nfssrv_zone_key);
2602
2603 /* The order here is important (reverse of init) */
2604 nfsauth_fini();
2605 rfs4_srvrfini();
2606 rfs3_srvrfini();
2607 rfs_srvrfini();
2608 nfs_exportfini();
2609
2610 /* Truly global stuff in this module (not per zone) */
2611 list_destroy(&nfssrv_globals_list);
2612 rw_destroy(&nfssrv_globals_rwl);
2613 }
2614
2615 /*
2616 * Zone init, shutdown, fini functions for the NFS server
2617 *
2618 * This design is careful to create the entire hierarhcy of
2619 * NFS server "globals" (including those created by various
2620 * per-module *_zone_init functions, etc.) so that all these
2621 * objects have exactly the same lifetime.
2622 *
2623 * These objects are also kept on a list for two reasons:
2624 * 1: It makes finding these in mdb _much_ easier.
2625 * 2: It allows operating across all zone globals for
2626 * functions like nfs_auth.c:exi_cache_reclaim
2627 */
2628 static void *
2629 nfs_server_zone_init(zoneid_t zoneid)
2630 {
2631 nfs_globals_t *ng;
2632
2633 ng = kmem_zalloc(sizeof (*ng), KM_SLEEP);
2634
2635 ng->nfs_versmin = NFS_VERSMIN_DEFAULT;
2636 ng->nfs_versmax = NFS_VERSMAX_DEFAULT;
2637
2638 /* Init the stuff to control start/stop */
2639 ng->nfs_server_upordown = NFS_SERVER_STOPPED;
2640 mutex_init(&ng->nfs_server_upordown_lock, NULL, MUTEX_DEFAULT, NULL);
2641 cv_init(&ng->nfs_server_upordown_cv, NULL, CV_DEFAULT, NULL);
2642 mutex_init(&ng->rdma_wait_mutex, NULL, MUTEX_DEFAULT, NULL);
2643 cv_init(&ng->rdma_wait_cv, NULL, CV_DEFAULT, NULL);
2644
2645 ng->nfs_zoneid = zoneid;
2646
2647 /*
2648 * Order here is important.
2649 * export init must precede srv init calls.
2650 */
2651 nfs_export_zone_init(ng);
2652 rfs_srv_zone_init(ng);
2653 rfs3_srv_zone_init(ng);
2654 rfs4_srv_zone_init(ng);
2655 nfsauth_zone_init(ng);
2656
2657 rw_enter(&nfssrv_globals_rwl, RW_WRITER);
2658 list_insert_tail(&nfssrv_globals_list, ng);
2659 rw_exit(&nfssrv_globals_rwl);
2660
2661 return (ng);
2662 }
2663
2664 /* ARGSUSED */
2665 static void
2666 nfs_server_zone_shutdown(zoneid_t zoneid, void *data)
2667 {
2668 nfs_globals_t *ng;
2669
2670 ng = (nfs_globals_t *)data;
2671
2672 /*
2673 * Order is like _fini, but only
2674 * some modules need this hook.
2675 */
2676 nfsauth_zone_shutdown(ng);
2677 nfs_export_zone_shutdown(ng);
2678 }
2679
2680 /* ARGSUSED */
2681 static void
2682 nfs_server_zone_fini(zoneid_t zoneid, void *data)
2683 {
2684 nfs_globals_t *ng;
2685
2686 ng = (nfs_globals_t *)data;
2687
2688 rw_enter(&nfssrv_globals_rwl, RW_WRITER);
2689 list_remove(&nfssrv_globals_list, ng);
2690 rw_exit(&nfssrv_globals_rwl);
2691
2692 /*
2693 * Order here is important.
2694 * reverse order from init
2695 */
2696 nfsauth_zone_fini(ng);
2697 rfs4_srv_zone_fini(ng);
2698 rfs3_srv_zone_fini(ng);
2699 rfs_srv_zone_fini(ng);
2700 nfs_export_zone_fini(ng);
2701
2702 mutex_destroy(&ng->nfs_server_upordown_lock);
2703 cv_destroy(&ng->nfs_server_upordown_cv);
2704 mutex_destroy(&ng->rdma_wait_mutex);
2705 cv_destroy(&ng->rdma_wait_cv);
2706
2707 kmem_free(ng, sizeof (*ng));
2708 }
2709
2710 /*
2711 * Set up an iovec array of up to cnt pointers.
2712 */
2713 void
2714 mblk_to_iov(mblk_t *m, int cnt, struct iovec *iovp)
2715 {
2716 while (m != NULL && cnt-- > 0) {
2717 iovp->iov_base = (caddr_t)m->b_rptr;
2718 iovp->iov_len = (m->b_wptr - m->b_rptr);
2719 iovp++;
2720 m = m->b_cont;
2721 }
|