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
|