Print this page
11083 support NFS server in zone
Portions contributed by: Dan Kruchinin <dan.kruchinin@nexenta.com>
Portions contributed by: Stepan Zastupov <stepan.zastupov@gmail.com>
Portions contributed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Portions contributed by: Mike Zeller <mike@mikezeller.net>
Portions contributed by: Dan McDonald <danmcd@joyent.com>
Portions contributed by: Gordon Ross <gordon.w.ross@gmail.com>
Portions contributed by: Vitaliy Gusev <gusev.vitaliy@gmail.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Jason King <jbk@joyent.com>
Reviewed by: C Fraire <cfraire@me.com>
Change-Id: I22f289d357503f9b48a0bc2482cc4328a6d43d16


 826                                 delay(SEC_TO_TICK(NLM_NSM_RPCBIND_TIMEOUT));
 827                                 continue;
 828                         }
 829                 }
 830 
 831                 break;
 832         }
 833 
 834         if (stat != RPC_SUCCESS) {
 835                 DTRACE_PROBE2(rpcbind__error, enum clnt_stat, stat,
 836                     int, retries);
 837                 error = ENOENT;
 838                 goto error;
 839         }
 840 
 841         /*
 842          * Create an RPC handle that'll be used for communication with local
 843          * statd using the status monitor protocol.
 844          */
 845         error = clnt_tli_kcreate(&nsm->ns_knc, &nsm->ns_addr, SM_PROG, SM_VERS,
 846             0, NLM_RPC_RETRIES, kcred, &nsm->ns_handle);
 847         if (error != 0)
 848                 goto error;
 849 
 850         /*
 851          * Create an RPC handle that'll be used for communication with the
 852          * local statd using the address registration protocol.
 853          */
 854         error = clnt_tli_kcreate(&nsm->ns_knc, &nsm->ns_addr, NSM_ADDR_PROGRAM,
 855             NSM_ADDR_V1, 0, NLM_RPC_RETRIES, kcred, &nsm->ns_addr_handle);

 856         if (error != 0)
 857                 goto error;
 858 
 859         sema_init(&nsm->ns_sem, 1, NULL, SEMA_DEFAULT, NULL);
 860         return (0);
 861 
 862 error:
 863         kmem_free(nsm->ns_addr.buf, nsm->ns_addr.maxlen);
 864         if (nsm->ns_handle)


 865                 CLNT_DESTROY(nsm->ns_handle);

 866 
 867         return (error);
 868 }
 869 
 870 static void
 871 nlm_nsm_fini(struct nlm_nsm *nsm)
 872 {
 873         kmem_free(nsm->ns_addr.buf, nsm->ns_addr.maxlen);


 874         CLNT_DESTROY(nsm->ns_addr_handle);
 875         nsm->ns_addr_handle = NULL;


 876         CLNT_DESTROY(nsm->ns_handle);
 877         nsm->ns_handle = NULL;
 878         sema_destroy(&nsm->ns_sem);
 879 }
 880 
 881 static enum clnt_stat
 882 nlm_nsm_simu_crash(struct nlm_nsm *nsm)
 883 {
 884         enum clnt_stat stat;
 885 
 886         sema_p(&nsm->ns_sem);
 887         nlm_nsm_clnt_init(nsm->ns_handle, nsm);
 888         stat = sm_simu_crash_1(NULL, NULL, nsm->ns_handle);
 889         sema_v(&nsm->ns_sem);
 890 
 891         return (stat);
 892 }
 893 
 894 static enum clnt_stat
 895 nlm_nsm_stat(struct nlm_nsm *nsm, int32_t *out_stat)


2545                 if (nvp != NULL) {
2546                         active = 1;
2547                         break;
2548                 }
2549 
2550                 hostp = AVL_NEXT(&g->nlm_hosts_tree, hostp);
2551         }
2552 
2553         mutex_exit(&g->lock);
2554         return (active);
2555 }
2556 
2557 /*
2558  * Called right before NFS export is going to
2559  * dissapear. The function finds all vnodes
2560  * belonging to the given export and cleans
2561  * all remote locks and share reservations
2562  * on them.
2563  */
2564 void
2565 nlm_unexport(struct exportinfo *exi)
2566 {
2567         struct nlm_globals *g;
2568         struct nlm_host *hostp;
2569 
2570         g = zone_getspecific(nlm_zone_key, curzone);
2571 
2572         mutex_enter(&g->lock);






2573         hostp = avl_first(&g->nlm_hosts_tree);
2574         while (hostp != NULL) {
2575                 struct nlm_vhold *nvp;
2576 
2577                 if (hostp->nh_flags & NLM_NH_INIDLE) {
2578                         TAILQ_REMOVE(&g->nlm_idle_hosts, hostp, nh_link);
2579                         hostp->nh_flags &= ~NLM_NH_INIDLE;
2580                 }
2581                 hostp->nh_refs++;
2582 
2583                 mutex_exit(&g->lock);
2584 
2585                 mutex_enter(&hostp->nh_lock);
2586                 TAILQ_FOREACH(nvp, &hostp->nh_vholds_list, nv_link) {
2587                         vnode_t *vp;
2588 
2589                         nvp->nv_refcnt++;
2590                         mutex_exit(&hostp->nh_lock);
2591 
2592                         vp = nvp->nv_vp;


2600                          * to drop all locks from this vnode, let's
2601                          * do it.
2602                          */
2603                         nlm_vhold_clean(nvp, hostp->nh_sysid);
2604 
2605                 next_iter:
2606                         mutex_enter(&hostp->nh_lock);
2607                         nvp->nv_refcnt--;
2608                 }
2609                 mutex_exit(&hostp->nh_lock);
2610 
2611                 mutex_enter(&g->lock);
2612                 nlm_host_release_locked(g, hostp);
2613 
2614                 hostp = AVL_NEXT(&g->nlm_hosts_tree, hostp);
2615         }
2616 
2617         mutex_exit(&g->lock);
2618 }
2619 






















2620 /*
2621  * Allocate new unique sysid.
2622  * In case of failure (no available sysids)
2623  * return LM_NOSYSID.
2624  */
2625 sysid_t
2626 nlm_sysid_alloc(void)
2627 {
2628         sysid_t ret_sysid = LM_NOSYSID;
2629 
2630         rw_enter(&lm_lck, RW_WRITER);
2631         if (nlm_sysid_nidx > LM_SYSID_MAX)
2632                 nlm_sysid_nidx = LM_SYSID;
2633 
2634         if (!BT_TEST(nlm_sysid_bmap, nlm_sysid_nidx)) {
2635                 BT_SET(nlm_sysid_bmap, nlm_sysid_nidx);
2636                 ret_sysid = nlm_sysid_nidx++;
2637         } else {
2638                 index_t id;
2639 


2768 
2769         rw_exit(&lm_lck);
2770 }
2771 
2772 void
2773 nlm_cprresume(void)
2774 {
2775         struct nlm_globals *g;
2776 
2777         rw_enter(&lm_lck, RW_READER);
2778         TAILQ_FOREACH(g, &nlm_zones_list, nlm_link)
2779                 nlm_resume_zone(g);
2780 
2781         rw_exit(&lm_lck);
2782 }
2783 
2784 static void
2785 nlm_nsm_clnt_init(CLIENT *clnt, struct nlm_nsm *nsm)
2786 {
2787         (void) clnt_tli_kinit(clnt, &nsm->ns_knc, &nsm->ns_addr, 0,
2788             NLM_RPC_RETRIES, kcred);
2789 }
2790 
2791 static void
2792 nlm_netbuf_to_netobj(struct netbuf *addr, int *family, netobj *obj)
2793 {
2794         /* LINTED pointer alignment */
2795         struct sockaddr *sa = (struct sockaddr *)addr->buf;
2796 
2797         *family = sa->sa_family;
2798 
2799         switch (sa->sa_family) {
2800         case AF_INET: {
2801                 /* LINTED pointer alignment */
2802                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
2803 
2804                 obj->n_len = sizeof (sin->sin_addr);
2805                 obj->n_bytes = (char *)&sin->sin_addr;
2806                 break;
2807         }
2808 


 826                                 delay(SEC_TO_TICK(NLM_NSM_RPCBIND_TIMEOUT));
 827                                 continue;
 828                         }
 829                 }
 830 
 831                 break;
 832         }
 833 
 834         if (stat != RPC_SUCCESS) {
 835                 DTRACE_PROBE2(rpcbind__error, enum clnt_stat, stat,
 836                     int, retries);
 837                 error = ENOENT;
 838                 goto error;
 839         }
 840 
 841         /*
 842          * Create an RPC handle that'll be used for communication with local
 843          * statd using the status monitor protocol.
 844          */
 845         error = clnt_tli_kcreate(&nsm->ns_knc, &nsm->ns_addr, SM_PROG, SM_VERS,
 846             0, NLM_RPC_RETRIES, zone_kcred(), &nsm->ns_handle);
 847         if (error != 0)
 848                 goto error;
 849 
 850         /*
 851          * Create an RPC handle that'll be used for communication with the
 852          * local statd using the address registration protocol.
 853          */
 854         error = clnt_tli_kcreate(&nsm->ns_knc, &nsm->ns_addr, NSM_ADDR_PROGRAM,
 855             NSM_ADDR_V1, 0, NLM_RPC_RETRIES, zone_kcred(),
 856             &nsm->ns_addr_handle);
 857         if (error != 0)
 858                 goto error;
 859 
 860         sema_init(&nsm->ns_sem, 1, NULL, SEMA_DEFAULT, NULL);
 861         return (0);
 862 
 863 error:
 864         kmem_free(nsm->ns_addr.buf, nsm->ns_addr.maxlen);
 865         if (nsm->ns_handle) {
 866                 ASSERT(nsm->ns_handle->cl_auth != NULL);
 867                 auth_destroy(nsm->ns_handle->cl_auth);
 868                 CLNT_DESTROY(nsm->ns_handle);
 869         }
 870 
 871         return (error);
 872 }
 873 
 874 static void
 875 nlm_nsm_fini(struct nlm_nsm *nsm)
 876 {
 877         kmem_free(nsm->ns_addr.buf, nsm->ns_addr.maxlen);
 878         if (nsm->ns_addr_handle->cl_auth != NULL)
 879                 auth_destroy(nsm->ns_addr_handle->cl_auth);
 880         CLNT_DESTROY(nsm->ns_addr_handle);
 881         nsm->ns_addr_handle = NULL;
 882         if (nsm->ns_handle->cl_auth != NULL)
 883                 auth_destroy(nsm->ns_handle->cl_auth);
 884         CLNT_DESTROY(nsm->ns_handle);
 885         nsm->ns_handle = NULL;
 886         sema_destroy(&nsm->ns_sem);
 887 }
 888 
 889 static enum clnt_stat
 890 nlm_nsm_simu_crash(struct nlm_nsm *nsm)
 891 {
 892         enum clnt_stat stat;
 893 
 894         sema_p(&nsm->ns_sem);
 895         nlm_nsm_clnt_init(nsm->ns_handle, nsm);
 896         stat = sm_simu_crash_1(NULL, NULL, nsm->ns_handle);
 897         sema_v(&nsm->ns_sem);
 898 
 899         return (stat);
 900 }
 901 
 902 static enum clnt_stat
 903 nlm_nsm_stat(struct nlm_nsm *nsm, int32_t *out_stat)


2553                 if (nvp != NULL) {
2554                         active = 1;
2555                         break;
2556                 }
2557 
2558                 hostp = AVL_NEXT(&g->nlm_hosts_tree, hostp);
2559         }
2560 
2561         mutex_exit(&g->lock);
2562         return (active);
2563 }
2564 
2565 /*
2566  * Called right before NFS export is going to
2567  * dissapear. The function finds all vnodes
2568  * belonging to the given export and cleans
2569  * all remote locks and share reservations
2570  * on them.
2571  */
2572 void
2573 nlm_zone_unexport(struct nlm_globals *g, struct exportinfo *exi)
2574 {

2575         struct nlm_host *hostp;
2576 


2577         mutex_enter(&g->lock);
2578         if (g->run_status != NLM_ST_UP) {
2579                 /* nothing to do */
2580                 mutex_exit(&g->lock);
2581                 return;
2582         }
2583 
2584         hostp = avl_first(&g->nlm_hosts_tree);
2585         while (hostp != NULL) {
2586                 struct nlm_vhold *nvp;
2587 
2588                 if (hostp->nh_flags & NLM_NH_INIDLE) {
2589                         TAILQ_REMOVE(&g->nlm_idle_hosts, hostp, nh_link);
2590                         hostp->nh_flags &= ~NLM_NH_INIDLE;
2591                 }
2592                 hostp->nh_refs++;
2593 
2594                 mutex_exit(&g->lock);
2595 
2596                 mutex_enter(&hostp->nh_lock);
2597                 TAILQ_FOREACH(nvp, &hostp->nh_vholds_list, nv_link) {
2598                         vnode_t *vp;
2599 
2600                         nvp->nv_refcnt++;
2601                         mutex_exit(&hostp->nh_lock);
2602 
2603                         vp = nvp->nv_vp;


2611                          * to drop all locks from this vnode, let's
2612                          * do it.
2613                          */
2614                         nlm_vhold_clean(nvp, hostp->nh_sysid);
2615 
2616                 next_iter:
2617                         mutex_enter(&hostp->nh_lock);
2618                         nvp->nv_refcnt--;
2619                 }
2620                 mutex_exit(&hostp->nh_lock);
2621 
2622                 mutex_enter(&g->lock);
2623                 nlm_host_release_locked(g, hostp);
2624 
2625                 hostp = AVL_NEXT(&g->nlm_hosts_tree, hostp);
2626         }
2627 
2628         mutex_exit(&g->lock);
2629 }
2630 
2631 void
2632 nlm_unexport(struct exportinfo *exi)
2633 {
2634         struct nlm_globals *g;
2635 
2636         rw_enter(&lm_lck, RW_READER);
2637         TAILQ_FOREACH(g, &nlm_zones_list, nlm_link) {
2638                 if (g->nlm_zoneid == exi->exi_zoneid) {
2639                         /*
2640                          * NOTE: If we want to drop lm_lock before
2641                          * calling nlm_zone_unexport(), we should break,
2642                          * and have a post-rw_exit() snippit like:
2643                          *      if (g != NULL)
2644                          *              nlm_zone_unexport(g, exi);
2645                          */
2646                         nlm_zone_unexport(g, exi);
2647                         break; /* Only going to match once! */
2648                 }
2649         }
2650         rw_exit(&lm_lck);
2651 }
2652 
2653 /*
2654  * Allocate new unique sysid.
2655  * In case of failure (no available sysids)
2656  * return LM_NOSYSID.
2657  */
2658 sysid_t
2659 nlm_sysid_alloc(void)
2660 {
2661         sysid_t ret_sysid = LM_NOSYSID;
2662 
2663         rw_enter(&lm_lck, RW_WRITER);
2664         if (nlm_sysid_nidx > LM_SYSID_MAX)
2665                 nlm_sysid_nidx = LM_SYSID;
2666 
2667         if (!BT_TEST(nlm_sysid_bmap, nlm_sysid_nidx)) {
2668                 BT_SET(nlm_sysid_bmap, nlm_sysid_nidx);
2669                 ret_sysid = nlm_sysid_nidx++;
2670         } else {
2671                 index_t id;
2672 


2801 
2802         rw_exit(&lm_lck);
2803 }
2804 
2805 void
2806 nlm_cprresume(void)
2807 {
2808         struct nlm_globals *g;
2809 
2810         rw_enter(&lm_lck, RW_READER);
2811         TAILQ_FOREACH(g, &nlm_zones_list, nlm_link)
2812                 nlm_resume_zone(g);
2813 
2814         rw_exit(&lm_lck);
2815 }
2816 
2817 static void
2818 nlm_nsm_clnt_init(CLIENT *clnt, struct nlm_nsm *nsm)
2819 {
2820         (void) clnt_tli_kinit(clnt, &nsm->ns_knc, &nsm->ns_addr, 0,
2821             NLM_RPC_RETRIES, zone_kcred());
2822 }
2823 
2824 static void
2825 nlm_netbuf_to_netobj(struct netbuf *addr, int *family, netobj *obj)
2826 {
2827         /* LINTED pointer alignment */
2828         struct sockaddr *sa = (struct sockaddr *)addr->buf;
2829 
2830         *family = sa->sa_family;
2831 
2832         switch (sa->sa_family) {
2833         case AF_INET: {
2834                 /* LINTED pointer alignment */
2835                 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
2836 
2837                 obj->n_len = sizeof (sin->sin_addr);
2838                 obj->n_bytes = (char *)&sin->sin_addr;
2839                 break;
2840         }
2841