1905 VN_HOLD(dvp);
1906 }
1907 if (walk != NULL)
1908 *walk = 0;
1909
1910 for (;;) {
1911 bzero(&fid, sizeof (fid));
1912 fid.fid_len = MAXFIDSZ;
1913 error = vop_fid_pseudo(vp, &fid);
1914 if (error) {
1915 /*
1916 * If vop_fid_pseudo returns ENOSPC then the fid
1917 * supplied is too small. For now we simply
1918 * return EREMOTE.
1919 */
1920 if (error == ENOSPC)
1921 error = EREMOTE;
1922 break;
1923 }
1924
1925 if (v4srv)
1926 exi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
1927 else
1928 exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid);
1929
1930 if (exi != NULL) {
1931 /*
1932 * Found the export info
1933 */
1934 break;
1935 }
1936
1937 /*
1938 * We have just failed finding a matching export.
1939 * If we're at the root of this filesystem, then
1940 * it's time to stop (with failure).
1941 */
1942 if (vp->v_flag & VROOT) {
1943 error = EINVAL;
1944 break;
1945 }
1946
1947 if (walk != NULL)
1948 (*walk)++;
1949
2414 error = VFS_VGET(vfsp, &vp, fidp);
2415 /*
2416 * If we can not get vp from VFS_VGET, perhaps this is
2417 * an nfs v2/v3/v4 node in an nfsv4 pseudo filesystem.
2418 * Check it out.
2419 */
2420 if (error && PSEUDO(exi))
2421 error = nfs4_vget_pseudo(exi, &vp, fidp);
2422
2423 if (error || vp == NULL) {
2424 *statp = NFS4ERR_STALE;
2425 return (NULL);
2426 }
2427 /* XXX - disgusting hack */
2428 if (vp->v_type == VNON && vp->v_flag & V_XATTRDIR)
2429 vp->v_type = VDIR;
2430 *statp = NFS4_OK;
2431 return (vp);
2432 }
2433
2434 /*
2435 * Find the export structure associated with the given filesystem.
2436 * If found, then increment the ref count (exi_count).
2437 */
2438 struct exportinfo *
2439 checkexport(fsid_t *fsid, fid_t *fid)
2440 {
2441 struct exportinfo *exi;
2442
2443 rw_enter(&exported_lock, RW_READER);
2444 for (exi = exptable[exptablehash(fsid, fid)];
2445 exi != NULL;
2446 exi = exi->fid_hash.next) {
2447 if (exportmatch(exi, fsid, fid)) {
2448 /*
2449 * If this is the place holder for the
2450 * public file handle, then return the
2451 * real export entry for the public file
2452 * handle.
2453 */
2454 if (exi->exi_export.ex_flags & EX_PUBLIC) {
2455 exi = exi_public;
2456 }
2457
2458 exi_hold(exi);
2459 rw_exit(&exported_lock);
2460 return (exi);
2461 }
2462 }
2463 rw_exit(&exported_lock);
2464 return (NULL);
2465 }
2466
2467
2468 /*
2469 * "old school" version of checkexport() for NFS4. NFS4
2470 * rfs4_compound holds exported_lock for duration of compound
2471 * processing. This version doesn't manipulate exi_count
2472 * since NFS4 breaks fundamental assumptions in the exi_count
2473 * design.
2474 */
2475 struct exportinfo *
2476 checkexport4(fsid_t *fsid, fid_t *fid, vnode_t *vp)
2477 {
2478 struct exportinfo *exi;
2479
2480 ASSERT(RW_LOCK_HELD(&exported_lock));
2481
2482 for (exi = exptable[exptablehash(fsid, fid)];
2483 exi != NULL;
2484 exi = exi->fid_hash.next) {
2485 if (exportmatch(exi, fsid, fid)) {
2486 /*
2487 * If this is the place holder for the
2488 * public file handle, then return the
2489 * real export entry for the public file
2490 * handle.
2491 */
2492 if (exi->exi_export.ex_flags & EX_PUBLIC) {
2493 exi = exi_public;
2494 }
2495
2496 /*
2497 * If vp is given, check if vp is the
2498 * same vnode as the exported node.
2499 *
2500 * Since VOP_FID of a lofs node returns the
2501 * fid of its real node (ufs), the exported
2502 * node for lofs and (pseudo) ufs may have
2503 * the same fsid and fid.
2504 */
2505 if (vp == NULL || vp == exi->exi_vp)
2506 return (exi);
2507 }
2508 }
2509
2510 return (NULL);
2511 }
2512
2513 /*
2514 * Free an entire export list node
2515 */
2516 void
2517 exportfree(struct exportinfo *exi)
2518 {
2519 struct exportdata *ex;
2520 struct charset_cache *cache;
2521 int i;
2522
2523 ex = &exi->exi_export;
2524
2525 ASSERT(exi->exi_vp != NULL && !(exi->exi_export.ex_flags & EX_PUBLIC));
2526 VN_RELE(exi->exi_vp);
2527 if (exi->exi_dvp != NULL)
2528 VN_RELE(exi->exi_dvp);
2529
2530 if (ex->ex_flags & EX_INDEX)
|
1905 VN_HOLD(dvp);
1906 }
1907 if (walk != NULL)
1908 *walk = 0;
1909
1910 for (;;) {
1911 bzero(&fid, sizeof (fid));
1912 fid.fid_len = MAXFIDSZ;
1913 error = vop_fid_pseudo(vp, &fid);
1914 if (error) {
1915 /*
1916 * If vop_fid_pseudo returns ENOSPC then the fid
1917 * supplied is too small. For now we simply
1918 * return EREMOTE.
1919 */
1920 if (error == ENOSPC)
1921 error = EREMOTE;
1922 break;
1923 }
1924
1925 exi = checkexport(&vp->v_vfsp->vfs_fsid, &fid,
1926 v4srv ? vp : NULL);
1927 if (exi != NULL) {
1928 /*
1929 * Found the export info
1930 */
1931 break;
1932 }
1933
1934 /*
1935 * We have just failed finding a matching export.
1936 * If we're at the root of this filesystem, then
1937 * it's time to stop (with failure).
1938 */
1939 if (vp->v_flag & VROOT) {
1940 error = EINVAL;
1941 break;
1942 }
1943
1944 if (walk != NULL)
1945 (*walk)++;
1946
2411 error = VFS_VGET(vfsp, &vp, fidp);
2412 /*
2413 * If we can not get vp from VFS_VGET, perhaps this is
2414 * an nfs v2/v3/v4 node in an nfsv4 pseudo filesystem.
2415 * Check it out.
2416 */
2417 if (error && PSEUDO(exi))
2418 error = nfs4_vget_pseudo(exi, &vp, fidp);
2419
2420 if (error || vp == NULL) {
2421 *statp = NFS4ERR_STALE;
2422 return (NULL);
2423 }
2424 /* XXX - disgusting hack */
2425 if (vp->v_type == VNON && vp->v_flag & V_XATTRDIR)
2426 vp->v_type = VDIR;
2427 *statp = NFS4_OK;
2428 return (vp);
2429 }
2430
2431 struct exportinfo *
2432 checkexport_nohold(fsid_t *fsid, fid_t *fid, vnode_t *vp)
2433 {
2434 struct exportinfo *exi;
2435
2436 for (exi = exptable[exptablehash(fsid, fid)];
2437 exi != NULL;
2438 exi = exi->fid_hash.next) {
2439 if (exportmatch(exi, fsid, fid)) {
2440 /*
2441 * If this is the place holder for the
2442 * public file handle, then return the
2443 * real export entry for the public file
2444 * handle.
2445 */
2446 if (exi->exi_export.ex_flags & EX_PUBLIC) {
2447 exi = exi_public;
2448 }
2449
2450 /*
2451 * If vp is given, check if vp is the
2452 * same vnode as the exported node.
2453 *
2454 * Since VOP_FID of a lofs node returns the
2455 * fid of its real node (ufs), the exported
2456 * node for lofs and (pseudo) ufs may have
2457 * the same fsid and fid.
2458 */
2459 if (vp == NULL || vp == exi->exi_vp) {
2460 return (exi);
2461 }
2462 }
2463 }
2464 return (NULL);
2465 }
2466
2467 /*
2468 * Find the export structure associated with the given filesystem.
2469 * If found, then increment the ref count (exi_count).
2470 */
2471 struct exportinfo *
2472 checkexport(fsid_t *fsid, fid_t *fid, vnode_t *vp)
2473 {
2474 struct exportinfo *exi;
2475
2476 rw_enter(&exported_lock, RW_READER);
2477 exi = checkexport_nohold(fsid, fid, vp);
2478 if (exi)
2479 exi_hold(exi);
2480 rw_exit(&exported_lock);
2481
2482 return (exi);
2483 }
2484
2485 /*
2486 * Free an entire export list node
2487 */
2488 void
2489 exportfree(struct exportinfo *exi)
2490 {
2491 struct exportdata *ex;
2492 struct charset_cache *cache;
2493 int i;
2494
2495 ex = &exi->exi_export;
2496
2497 ASSERT(exi->exi_vp != NULL && !(exi->exi_export.ex_flags & EX_PUBLIC));
2498 VN_RELE(exi->exi_vp);
2499 if (exi->exi_dvp != NULL)
2500 VN_RELE(exi->exi_dvp);
2501
2502 if (ex->ex_flags & EX_INDEX)
|