685 * Find for given treenode the exportinfo which has its
686 * exp_visible linked on its exi_visible list.
687 *
688 * Note: We could add new pointer either to treenode or
689 * to exp_visible, which will point there directly.
690 * This would buy some speed for some memory.
691 */
692 exportinfo_t *
693 vis2exi(treenode_t *tnode)
694 {
695 exportinfo_t *exi_ret = NULL;
696
697 for (;;) {
698 tnode = tnode->tree_parent;
699 if (TREE_ROOT(tnode)) {
700 exi_ret = tnode->tree_exi;
701 break;
702 }
703 }
704
705 ASSERT(exi_ret); /* Every visible should have its home exportinfo */
706 return (exi_ret);
707 }
708
709 /*
710 * For NFS V4.
711 * Add or remove the newly exported or unexported security flavors of the
712 * given exportinfo from its ancestors upto the system root.
713 */
714 void
715 srv_secinfo_treeclimb(nfs_export_t *ne, exportinfo_t *exip, secinfo_t *sec,
716 int seccnt, bool_t isadd)
717 {
718 treenode_t *tnode;
719
720 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
721
722 /*
723 * exi_tree can be null for the zone root
724 * which means we're already at the "top"
725 * and there's nothing more to "climb".
726 */
727 tnode = exip->exi_tree;
728 if (tnode == NULL) {
729 /* Should only happen for... */
730 ASSERT(exip == ne->exi_root);
731 return;
732 }
733
734 if (seccnt == 0)
735 return;
736
737 /*
738 * If flavors are being added and the new export root isn't
739 * also VROOT, its implicitly allowed flavors are inherited from
740 * its pseudonode.
741 * Note - for VROOT exports the implicitly allowed flavors were
742 * transferred from the PSEUDO export in exportfs()
743 */
744 if (isadd && !(exip->exi_vp->v_flag & VROOT) &&
745 tnode->tree_vis->vis_seccnt > 0) {
746 srv_secinfo_add(&exip->exi_export.ex_secinfo,
747 &exip->exi_export.ex_seccnt, tnode->tree_vis->vis_secinfo,
748 tnode->tree_vis->vis_seccnt, FALSE);
749 }
750
751 /*
752 * Move to parent node and propagate sec flavor
753 * to exportinfo and to visible structures.
754 */
755 tnode = tnode->tree_parent;
756
757 while (tnode != NULL) {
758
759 /* If there is exportinfo, update it */
760 if (tnode->tree_exi != NULL) {
761 secinfo_t **pxsec =
762 &tnode->tree_exi->exi_export.ex_secinfo;
763 int *pxcnt = &tnode->tree_exi->exi_export.ex_seccnt;
764 int is_pseudo = PSEUDO(tnode->tree_exi);
790 if ((exi)->hash_name.prev) \
791 (exi)->hash_name.prev->hash_name.next = (exi)->hash_name.next; \
792 if ((exi)->hash_name.next) \
793 (exi)->hash_name.next->hash_name.prev = (exi)->hash_name.prev; \
794 (exi)->hash_name.bckt = NULL;
795
796 #define exp_hash_link(exi, hash_name, bucket) \
797 (exi)->hash_name.bckt = (bucket); \
798 (exi)->hash_name.prev = NULL; \
799 (exi)->hash_name.next = *(bucket); \
800 if ((exi)->hash_name.next) \
801 (exi)->hash_name.next->hash_name.prev = (exi); \
802 *(bucket) = (exi);
803
804 void
805 export_link(nfs_export_t *ne, exportinfo_t *exi)
806 {
807 exportinfo_t **bckt;
808
809 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
810 ASSERT(exi->exi_zoneid == ne->ne_globals->nfs_zoneid);
811
812 bckt = &ne->exptable[exptablehash(&exi->exi_fsid, &exi->exi_fid)];
813 exp_hash_link(exi, fid_hash, bckt);
814
815 bckt = &ne->exptable_path_hash[pkp_tab_hash(exi->exi_export.ex_path,
816 strlen(exi->exi_export.ex_path))];
817 exp_hash_link(exi, path_hash, bckt);
818 }
819
820 /*
821 * Helper functions for exi_id handling
822 */
823 static int
824 exi_id_compar(const void *v1, const void *v2)
825 {
826 const struct exportinfo *e1 = v1;
827 const struct exportinfo *e2 = v2;
828
829 if (e1->exi_id < e2->exi_id)
830 return (-1);
831 if (e1->exi_id > e2->exi_id)
832 return (1);
833
834 return (0);
835 }
836
837 int
874 if (err != 0) {
875 ne->exi_rootfid.fid_len = 0;
876 return (err);
877 }
878
879 /* Setup the fhandle template exi_fh */
880 ne->exi_root->exi_fh.fh_fsid = rootdir->v_vfsp->vfs_fsid;
881 ne->exi_root->exi_fh.fh_xlen = ne->exi_rootfid.fid_len;
882 bcopy(ne->exi_rootfid.fid_data, ne->exi_root->exi_fh.fh_xdata,
883 ne->exi_rootfid.fid_len);
884 ne->exi_root->exi_fh.fh_len = sizeof (ne->exi_root->exi_fh.fh_data);
885
886 return (0);
887 }
888
889 void
890 nfs_export_zone_init(nfs_globals_t *ng)
891 {
892 int i;
893 nfs_export_t *ne;
894
895 ne = kmem_zalloc(sizeof (*ne), KM_SLEEP);
896
897 rw_init(&ne->exported_lock, NULL, RW_DEFAULT, NULL);
898
899 ne->ne_globals = ng; /* "up" pointer */
900
901 /*
902 * Allocate the place holder for the public file handle, which
903 * is all zeroes. It is initially set to the root filesystem.
904 */
905 ne->exi_root = kmem_zalloc(sizeof (*ne->exi_root), KM_SLEEP);
906 ne->exi_public = ne->exi_root;
907
908 ne->exi_root->exi_export.ex_flags = EX_PUBLIC;
909 ne->exi_root->exi_export.ex_pathlen = 1; /* length of "/" */
910 ne->exi_root->exi_export.ex_path =
911 kmem_alloc(ne->exi_root->exi_export.ex_pathlen + 1, KM_SLEEP);
912 ne->exi_root->exi_export.ex_path[0] = '/';
913 ne->exi_root->exi_export.ex_path[1] = '\0';
914
915 ne->exi_root->exi_count = 1;
916 mutex_init(&ne->exi_root->exi_lock, NULL, MUTEX_DEFAULT, NULL);
917
918 ne->exi_root->exi_vp = ZONE_ROOTVP();
919 ne->exi_root->exi_zoneid = ng->nfs_zoneid;
920
921 /*
922 * Fill in ne->exi_rootfid later, in nfs_export_get_rootfid
923 * because we can't correctly return errors here.
924 */
925
926 /* Initialize auth cache and auth cache lock */
927 for (i = 0; i < AUTH_TABLESIZE; i++) {
928 ne->exi_root->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t),
929 KM_SLEEP);
930 avl_create(ne->exi_root->exi_cache[i],
931 nfsauth_cache_clnt_compar, sizeof (struct auth_cache_clnt),
932 offsetof(struct auth_cache_clnt, authc_link));
933 }
934 rw_init(&ne->exi_root->exi_cache_lock, NULL, RW_DEFAULT, NULL);
935
936 /* setup exi_fh later, in nfs_export_get_rootfid */
937
938 rw_enter(&ne->exported_lock, RW_WRITER);
1378 strcmp(ex2->exi_export.ex_path, lookpn.pn_path) != 0) {
1379 DTRACE_PROBE(nfss__i__exported_lock2_stop);
1380 rw_exit(&ne->exported_lock);
1381 VN_RELE(vp);
1382 if (dvp != NULL)
1383 VN_RELE(dvp);
1384 pn_free(&lookpn);
1385 return (EEXIST);
1386 }
1387 }
1388 DTRACE_PROBE(nfss__i__exported_lock2_stop);
1389 rw_exit(&ne->exported_lock);
1390 pn_free(&lookpn);
1391
1392 exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
1393 exi->exi_fsid = fsid;
1394 exi->exi_fid = fid;
1395 exi->exi_vp = vp;
1396 exi->exi_count = 1;
1397 exi->exi_zoneid = crgetzoneid(cr);
1398 exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
1399 VSW_VOLATILEDEV) ? 1 : 0;
1400 mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);
1401 exi->exi_dvp = dvp;
1402
1403 /*
1404 * Initialize auth cache and auth cache lock
1405 */
1406 for (i = 0; i < AUTH_TABLESIZE; i++) {
1407 exi->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
1408 avl_create(exi->exi_cache[i], nfsauth_cache_clnt_compar,
1409 sizeof (struct auth_cache_clnt),
1410 offsetof(struct auth_cache_clnt, authc_link));
1411 }
1412 rw_init(&exi->exi_cache_lock, NULL, RW_DEFAULT, NULL);
1413
1414 /*
1415 * Build up the template fhandle
1416 */
1417 exi->exi_fh.fh_fsid = fsid;
1847 for (i = 0; i < AUTH_TABLESIZE; i++) {
1848 avl_destroy(exi->exi_cache[i]);
1849 kmem_free(exi->exi_cache[i], sizeof (avl_tree_t));
1850 }
1851
1852 kmem_free(exi, sizeof (*exi));
1853
1854 return (error);
1855 }
1856
1857 /*
1858 * Remove the exportinfo from the export list
1859 */
1860 void
1861 export_unlink(nfs_export_t *ne, struct exportinfo *exi)
1862 {
1863 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
1864
1865 exp_hash_unlink(exi, fid_hash);
1866 exp_hash_unlink(exi, path_hash);
1867 }
1868
1869 /*
1870 * Unexport an exported filesystem
1871 */
1872 static int
1873 unexport(nfs_export_t *ne, struct exportinfo *exi)
1874 {
1875 struct secinfo cursec[MAX_FLAVORS];
1876 int curcnt;
1877
1878 rw_enter(&ne->exported_lock, RW_WRITER);
1879
1880 /* Check if exi is still linked in the export table */
1881 if (!EXP_LINKED(exi) || PSEUDO(exi)) {
1882 rw_exit(&ne->exported_lock);
1883 return (EINVAL);
1884 }
1885
1886 mutex_enter(&nfs_exi_id_lock);
1920 rw_exit(&ne->exported_lock);
1921
1922 /*
1923 * Need to call into the NFSv4 server and release all data
1924 * held on this particular export. This is important since
1925 * the v4 server may be holding file locks or vnodes under
1926 * this export.
1927 */
1928 rfs4_clean_state_exi(ne, exi);
1929
1930 /*
1931 * Notify the lock manager that the filesystem is being
1932 * unexported.
1933 */
1934 lm_unexport(exi);
1935
1936 /*
1937 * If this was a public export, restore
1938 * the public filehandle to the root.
1939 */
1940 if (exi == ne->exi_public) {
1941 ne->exi_public = ne->exi_root;
1942
1943 nfslog_share_record(ne->exi_public, CRED());
1944 }
1945
1946 if (exi->exi_export.ex_flags & EX_LOG)
1947 nfslog_unshare_record(exi, CRED());
1948
1949 exi_rele(exi);
1950 return (0);
1951 }
1952
1953 /*
1954 * Get file handle system call.
1955 * Takes file name and returns a file handle for it.
1956 * Credentials must be verified before calling.
1957 */
1958 int
1959 nfs_getfh(struct nfs_getfh_args *args, model_t model, cred_t *cr)
2154 break;
2155 }
2156
2157 if (v4srv)
2158 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
2159 else
2160 exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid);
2161
2162 if (exi != NULL) {
2163 /*
2164 * Found the export info
2165 */
2166 break;
2167 }
2168
2169 /*
2170 * We have just failed finding a matching export.
2171 * If we're at the root of this filesystem, then
2172 * it's time to stop (with failure).
2173 */
2174 if (vp->v_flag & VROOT) {
2175 error = EINVAL;
2176 break;
2177 }
2178
2179 if (walk != NULL)
2180 (*walk)++;
2181
2182 /*
2183 * Now, do a ".." up vp. If dvp is supplied, use it,
2184 * otherwise, look it up.
2185 */
2186 if (dvp == NULL) {
2187 error = VOP_LOOKUP(vp, "..", &dvp, NULL, 0, NULL, cr,
2188 NULL, NULL, NULL);
2189 if (error)
2190 break;
2191 }
2192 VN_RELE(vp);
2193 vp = dvp;
2194 dvp = NULL;
|
685 * Find for given treenode the exportinfo which has its
686 * exp_visible linked on its exi_visible list.
687 *
688 * Note: We could add new pointer either to treenode or
689 * to exp_visible, which will point there directly.
690 * This would buy some speed for some memory.
691 */
692 exportinfo_t *
693 vis2exi(treenode_t *tnode)
694 {
695 exportinfo_t *exi_ret = NULL;
696
697 for (;;) {
698 tnode = tnode->tree_parent;
699 if (TREE_ROOT(tnode)) {
700 exi_ret = tnode->tree_exi;
701 break;
702 }
703 }
704
705 /* Every visible should have its home exportinfo */
706 ASSERT(exi_ret != NULL);
707 return (exi_ret);
708 }
709
710 /*
711 * For NFS V4.
712 * Add or remove the newly exported or unexported security flavors of the
713 * given exportinfo from its ancestors upto the system root.
714 */
715 static void
716 srv_secinfo_treeclimb(nfs_export_t *ne, exportinfo_t *exip, secinfo_t *sec,
717 int seccnt, bool_t isadd)
718 {
719 treenode_t *tnode;
720
721 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
722
723 /*
724 * exi_tree can be null for the zone root
725 * which means we're already at the "top"
726 * and there's nothing more to "climb".
727 */
728 tnode = exip->exi_tree;
729 if (tnode == NULL) {
730 /* Should only happen for... */
731 ASSERT(exip == ne->exi_root);
732 return;
733 }
734
735 if (seccnt == 0)
736 return;
737
738 /*
739 * If flavors are being added and the new export root isn't
740 * also VROOT, its implicitly allowed flavors are inherited from
741 * its pseudonode.
742 * Note - for VROOT exports the implicitly allowed flavors were
743 * transferred from the PSEUDO export in exportfs()
744 */
745 if (isadd && !(exip->exi_vp->v_flag & VROOT) &&
746 !VN_CMP(exip->exi_vp, EXI_TO_ZONEROOTVP(exip)) &&
747 tnode->tree_vis->vis_seccnt > 0) {
748 srv_secinfo_add(&exip->exi_export.ex_secinfo,
749 &exip->exi_export.ex_seccnt, tnode->tree_vis->vis_secinfo,
750 tnode->tree_vis->vis_seccnt, FALSE);
751 }
752
753 /*
754 * Move to parent node and propagate sec flavor
755 * to exportinfo and to visible structures.
756 */
757 tnode = tnode->tree_parent;
758
759 while (tnode != NULL) {
760
761 /* If there is exportinfo, update it */
762 if (tnode->tree_exi != NULL) {
763 secinfo_t **pxsec =
764 &tnode->tree_exi->exi_export.ex_secinfo;
765 int *pxcnt = &tnode->tree_exi->exi_export.ex_seccnt;
766 int is_pseudo = PSEUDO(tnode->tree_exi);
792 if ((exi)->hash_name.prev) \
793 (exi)->hash_name.prev->hash_name.next = (exi)->hash_name.next; \
794 if ((exi)->hash_name.next) \
795 (exi)->hash_name.next->hash_name.prev = (exi)->hash_name.prev; \
796 (exi)->hash_name.bckt = NULL;
797
798 #define exp_hash_link(exi, hash_name, bucket) \
799 (exi)->hash_name.bckt = (bucket); \
800 (exi)->hash_name.prev = NULL; \
801 (exi)->hash_name.next = *(bucket); \
802 if ((exi)->hash_name.next) \
803 (exi)->hash_name.next->hash_name.prev = (exi); \
804 *(bucket) = (exi);
805
806 void
807 export_link(nfs_export_t *ne, exportinfo_t *exi)
808 {
809 exportinfo_t **bckt;
810
811 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
812
813 bckt = &ne->exptable[exptablehash(&exi->exi_fsid, &exi->exi_fid)];
814 exp_hash_link(exi, fid_hash, bckt);
815
816 bckt = &ne->exptable_path_hash[pkp_tab_hash(exi->exi_export.ex_path,
817 strlen(exi->exi_export.ex_path))];
818 exp_hash_link(exi, path_hash, bckt);
819 exi->exi_ne = ne;
820 }
821
822 /*
823 * Helper functions for exi_id handling
824 */
825 static int
826 exi_id_compar(const void *v1, const void *v2)
827 {
828 const struct exportinfo *e1 = v1;
829 const struct exportinfo *e2 = v2;
830
831 if (e1->exi_id < e2->exi_id)
832 return (-1);
833 if (e1->exi_id > e2->exi_id)
834 return (1);
835
836 return (0);
837 }
838
839 int
876 if (err != 0) {
877 ne->exi_rootfid.fid_len = 0;
878 return (err);
879 }
880
881 /* Setup the fhandle template exi_fh */
882 ne->exi_root->exi_fh.fh_fsid = rootdir->v_vfsp->vfs_fsid;
883 ne->exi_root->exi_fh.fh_xlen = ne->exi_rootfid.fid_len;
884 bcopy(ne->exi_rootfid.fid_data, ne->exi_root->exi_fh.fh_xdata,
885 ne->exi_rootfid.fid_len);
886 ne->exi_root->exi_fh.fh_len = sizeof (ne->exi_root->exi_fh.fh_data);
887
888 return (0);
889 }
890
891 void
892 nfs_export_zone_init(nfs_globals_t *ng)
893 {
894 int i;
895 nfs_export_t *ne;
896 zone_t *zone;
897
898 ne = kmem_zalloc(sizeof (*ne), KM_SLEEP);
899
900 rw_init(&ne->exported_lock, NULL, RW_DEFAULT, NULL);
901
902 ne->ne_globals = ng; /* "up" pointer */
903
904 /*
905 * Allocate the place holder for the public file handle, which
906 * is all zeroes. It is initially set to the root filesystem.
907 */
908 ne->exi_root = kmem_zalloc(sizeof (*ne->exi_root), KM_SLEEP);
909 ne->exi_public = ne->exi_root;
910
911 ne->exi_root->exi_export.ex_flags = EX_PUBLIC;
912 ne->exi_root->exi_export.ex_pathlen = 1; /* length of "/" */
913 ne->exi_root->exi_export.ex_path =
914 kmem_alloc(ne->exi_root->exi_export.ex_pathlen + 1, KM_SLEEP);
915 ne->exi_root->exi_export.ex_path[0] = '/';
916 ne->exi_root->exi_export.ex_path[1] = '\0';
917
918 ne->exi_root->exi_count = 1;
919 mutex_init(&ne->exi_root->exi_lock, NULL, MUTEX_DEFAULT, NULL);
920
921 /*
922 * Because we cannot:
923 * ASSERT(curzone->zone_id == ng->nfs_zoneid);
924 * We grab the zone pointer explicitly (like netstacks do) and
925 * set the rootvp here.
926 *
927 * Subsequent exportinfo_t's that get export_link()ed to "ne" also
928 * will backpoint to "ne" such that exi->exi_ne->exi_root->exi_vp
929 * will get the zone's rootvp for a given exportinfo_t.
930 */
931 zone = zone_find_by_id_nolock(ng->nfs_zoneid);
932 ne->exi_root->exi_vp = zone->zone_rootvp;
933 ne->exi_root->exi_zoneid = ng->nfs_zoneid;
934
935 /*
936 * Fill in ne->exi_rootfid later, in nfs_export_get_rootfid
937 * because we can't correctly return errors here.
938 */
939
940 /* Initialize auth cache and auth cache lock */
941 for (i = 0; i < AUTH_TABLESIZE; i++) {
942 ne->exi_root->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t),
943 KM_SLEEP);
944 avl_create(ne->exi_root->exi_cache[i],
945 nfsauth_cache_clnt_compar, sizeof (struct auth_cache_clnt),
946 offsetof(struct auth_cache_clnt, authc_link));
947 }
948 rw_init(&ne->exi_root->exi_cache_lock, NULL, RW_DEFAULT, NULL);
949
950 /* setup exi_fh later, in nfs_export_get_rootfid */
951
952 rw_enter(&ne->exported_lock, RW_WRITER);
1392 strcmp(ex2->exi_export.ex_path, lookpn.pn_path) != 0) {
1393 DTRACE_PROBE(nfss__i__exported_lock2_stop);
1394 rw_exit(&ne->exported_lock);
1395 VN_RELE(vp);
1396 if (dvp != NULL)
1397 VN_RELE(dvp);
1398 pn_free(&lookpn);
1399 return (EEXIST);
1400 }
1401 }
1402 DTRACE_PROBE(nfss__i__exported_lock2_stop);
1403 rw_exit(&ne->exported_lock);
1404 pn_free(&lookpn);
1405
1406 exi = kmem_zalloc(sizeof (*exi), KM_SLEEP);
1407 exi->exi_fsid = fsid;
1408 exi->exi_fid = fid;
1409 exi->exi_vp = vp;
1410 exi->exi_count = 1;
1411 exi->exi_zoneid = crgetzoneid(cr);
1412 ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
1413 exi->exi_volatile_dev = (vfssw[vp->v_vfsp->vfs_fstype].vsw_flag &
1414 VSW_VOLATILEDEV) ? 1 : 0;
1415 mutex_init(&exi->exi_lock, NULL, MUTEX_DEFAULT, NULL);
1416 exi->exi_dvp = dvp;
1417
1418 /*
1419 * Initialize auth cache and auth cache lock
1420 */
1421 for (i = 0; i < AUTH_TABLESIZE; i++) {
1422 exi->exi_cache[i] = kmem_alloc(sizeof (avl_tree_t), KM_SLEEP);
1423 avl_create(exi->exi_cache[i], nfsauth_cache_clnt_compar,
1424 sizeof (struct auth_cache_clnt),
1425 offsetof(struct auth_cache_clnt, authc_link));
1426 }
1427 rw_init(&exi->exi_cache_lock, NULL, RW_DEFAULT, NULL);
1428
1429 /*
1430 * Build up the template fhandle
1431 */
1432 exi->exi_fh.fh_fsid = fsid;
1862 for (i = 0; i < AUTH_TABLESIZE; i++) {
1863 avl_destroy(exi->exi_cache[i]);
1864 kmem_free(exi->exi_cache[i], sizeof (avl_tree_t));
1865 }
1866
1867 kmem_free(exi, sizeof (*exi));
1868
1869 return (error);
1870 }
1871
1872 /*
1873 * Remove the exportinfo from the export list
1874 */
1875 void
1876 export_unlink(nfs_export_t *ne, struct exportinfo *exi)
1877 {
1878 ASSERT(RW_WRITE_HELD(&ne->exported_lock));
1879
1880 exp_hash_unlink(exi, fid_hash);
1881 exp_hash_unlink(exi, path_hash);
1882 ASSERT3P(exi->exi_ne, ==, ne);
1883 exi->exi_ne = NULL;
1884 }
1885
1886 /*
1887 * Unexport an exported filesystem
1888 */
1889 static int
1890 unexport(nfs_export_t *ne, struct exportinfo *exi)
1891 {
1892 struct secinfo cursec[MAX_FLAVORS];
1893 int curcnt;
1894
1895 rw_enter(&ne->exported_lock, RW_WRITER);
1896
1897 /* Check if exi is still linked in the export table */
1898 if (!EXP_LINKED(exi) || PSEUDO(exi)) {
1899 rw_exit(&ne->exported_lock);
1900 return (EINVAL);
1901 }
1902
1903 mutex_enter(&nfs_exi_id_lock);
1937 rw_exit(&ne->exported_lock);
1938
1939 /*
1940 * Need to call into the NFSv4 server and release all data
1941 * held on this particular export. This is important since
1942 * the v4 server may be holding file locks or vnodes under
1943 * this export.
1944 */
1945 rfs4_clean_state_exi(ne, exi);
1946
1947 /*
1948 * Notify the lock manager that the filesystem is being
1949 * unexported.
1950 */
1951 lm_unexport(exi);
1952
1953 /*
1954 * If this was a public export, restore
1955 * the public filehandle to the root.
1956 */
1957
1958 /*
1959 * XXX KEBE ASKS --> Should CRED() instead be
1960 * exi->exi_zone->zone_kcred?
1961 */
1962 if (exi == ne->exi_public) {
1963 ne->exi_public = ne->exi_root;
1964
1965 nfslog_share_record(ne->exi_public, CRED());
1966 }
1967
1968 if (exi->exi_export.ex_flags & EX_LOG)
1969 nfslog_unshare_record(exi, CRED());
1970
1971 exi_rele(exi);
1972 return (0);
1973 }
1974
1975 /*
1976 * Get file handle system call.
1977 * Takes file name and returns a file handle for it.
1978 * Credentials must be verified before calling.
1979 */
1980 int
1981 nfs_getfh(struct nfs_getfh_args *args, model_t model, cred_t *cr)
2176 break;
2177 }
2178
2179 if (v4srv)
2180 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
2181 else
2182 exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid);
2183
2184 if (exi != NULL) {
2185 /*
2186 * Found the export info
2187 */
2188 break;
2189 }
2190
2191 /*
2192 * We have just failed finding a matching export.
2193 * If we're at the root of this filesystem, then
2194 * it's time to stop (with failure).
2195 */
2196 ASSERT3P(vp->v_vfsp->vfs_zone, ==, curzone);
2197 if ((vp->v_flag & VROOT) || VN_IS_CURZONEROOT(vp)) {
2198 error = EINVAL;
2199 break;
2200 }
2201
2202 if (walk != NULL)
2203 (*walk)++;
2204
2205 /*
2206 * Now, do a ".." up vp. If dvp is supplied, use it,
2207 * otherwise, look it up.
2208 */
2209 if (dvp == NULL) {
2210 error = VOP_LOOKUP(vp, "..", &dvp, NULL, 0, NULL, cr,
2211 NULL, NULL, NULL);
2212 if (error)
2213 break;
2214 }
2215 VN_RELE(vp);
2216 vp = dvp;
2217 dvp = NULL;
|