Print this page
Fix NFS design problems re. multiple zone keys
Make NFS server zone-specific data all have the same lifetime
Fix rfs4_clean_state_exi
Fix exi_cache_reclaim
Fix mistakes in zone keys work
More fixes re. exi_zoneid and exi_tree
(danmcd -> Keep some ASSERT()s around for readability.)


  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         }