/* * Get the change attribute from visible and returns TRUE. * If the change value is not available returns FALSE. */ bool_t nfs_visible_change(struct exportinfo *exi, vnode_t *vp, timespec_t *change) { struct exp_visible *visp; fid_t fid; treenode_t *node; /* * First check to see if vp is export root. */ if (VN_CMP(vp, exi->exi_vp)) goto exproot; /* * Only a PSEUDO node has a visible list or an exported VROOT * node may have a visible list. */ if (!PSEUDO(exi)) exi = get_root_export(exi); /* Get the fid of the vnode */ bzero(&fid, sizeof (fid)); fid.fid_len = MAXFIDSZ; if (vop_fid_pseudo(vp, &fid) != 0) return (FALSE); /* * We can't trust VN_CMP() above because of LOFS. * Even though VOP_CMP will do the right thing for LOFS * objects, VN_CMP will short circuit out early when the * vnode ops ptrs are different. Just in case we're dealing * with LOFS, compare exi_fid/fsid here. */ if (EQFID(&exi->exi_fid, &fid) && EQFSID(&exi->exi_fsid, &vp->v_vfsp->vfs_fsid)) goto exproot; /* See if it matches any fid in the visible list */ for (visp = exi->exi_visible; visp; visp = visp->vis_next) { if (EQFID(&fid, &visp->vis_fid)) { *change = visp->vis_change; return (TRUE); } } return (FALSE); exproot: /* The VROOT export have its visible available through treenode */ node = exi->exi_tree; if (node != ns_root) { ASSERT(node->tree_vis != NULL); *change = node->tree_vis->vis_change; } else { ASSERT(node->tree_vis == NULL); *change = ns_root_change; } return (TRUE); }
/* * Return true if the supplied vnode has a sub-directory exported. */ int has_visible(struct exportinfo *exi, vnode_t *vp) { struct exp_visible *visp; fid_t fid; bool_t vp_is_exported; vp_is_exported = VN_CMP(vp, exi->exi_vp); /* * An exported root vnode has a sub-dir shared if it has a visible list. * i.e. if it does not have a visible list, then there is no node in * this filesystem leads to any other shared node. */ if (vp_is_exported && (vp->v_flag & VROOT)) return (exi->exi_visible ? 1 : 0); /* * Only the exportinfo of a fs root node may have a visible list. * Either it is a pseudo root node, or a real exported root node. */ exi = get_root_export(exi); if (!exi->exi_visible) return (0); /* Get the fid of the vnode */ bzero(&fid, sizeof (fid)); fid.fid_len = MAXFIDSZ; if (vop_fid_pseudo(vp, &fid) != 0) { return (0); } /* * See if vp is in the visible list of the root node exportinfo. */ for (visp = exi->exi_visible; visp; visp = visp->vis_next) { if (EQFID(&fid, &visp->vis_fid)) { /* * If vp is an exported non-root node with only 1 path * count (for itself), it indicates no sub-dir shared * using this vp as a path. */ if (vp_is_exported && visp->vis_count < 2) break; return (1); } } return (0); }
/* * Returns true if the supplied inode is visible * in this export. This function is used by * readdir which uses inode numbers from the * directory. * * NOTE: this code does not match inode number for ".", * but it isn't required because NFS4 server rddir * skips . and .. entries. */ int nfs_visible_inode(struct exportinfo *exi, ino64_t ino, struct exp_visible **visp) { /* * Only a PSEUDO node has a visible list or an exported VROOT * node may have a visible list. */ if (! PSEUDO(exi)) exi = get_root_export(exi); for (*visp = exi->exi_visible; *visp != NULL; *visp = (*visp)->vis_next) if ((u_longlong_t)ino == (*visp)->vis_ino) { return (1); } return (0); }
/* * Returns true if the supplied inode is visible * in this export. This function is used by * readdir which uses inode numbers from the * directory. * * NOTE: this code does not match inode number for ".", * but it isn't required because NFS4 server rddir * skips . and .. entries. */ int nfs_visible_inode(struct exportinfo *exi, ino64_t ino, int *expseudo) { struct exp_visible *visp; /* * Only a PSEUDO node has a visible list or an exported VROOT * node may have a visible list. */ if (! PSEUDO(exi)) exi = get_root_export(exi); for (visp = exi->exi_visible; visp; visp = visp->vis_next) if ((u_longlong_t)ino == visp->vis_ino) { *expseudo = visp->vis_exported; return (1); } *expseudo = 0; return (0); }
/* * Returns true if the supplied vnode is visible * in this export. If vnode is visible, return * vis_exported in expseudo. */ int nfs_visible(struct exportinfo *exi, vnode_t *vp, int *expseudo) { struct exp_visible *visp; fid_t fid; /* * First check to see if vp is export root. * * A pseudo export root can never be exported * (it would be a real export then); however, * it is always visible. If a pseudo root object * was exported by server admin, then the entire * pseudo exportinfo (and all visible entries) would * be destroyed. A pseudo exportinfo only exists * to provide access to real (descendant) export(s). * * Previously, rootdir was special cased here; however, * the export root special case handles the rootdir * case also. */ if (VN_CMP(vp, exi->exi_vp)) { *expseudo = 0; return (1); } /* * Only a PSEUDO node has a visible list or an exported VROOT * node may have a visible list. */ if (! PSEUDO(exi)) exi = get_root_export(exi); /* Get the fid of the vnode */ bzero(&fid, sizeof (fid)); fid.fid_len = MAXFIDSZ; if (vop_fid_pseudo(vp, &fid) != 0) { *expseudo = 0; return (0); } /* * We can't trust VN_CMP() above because of LOFS. * Even though VOP_CMP will do the right thing for LOFS * objects, VN_CMP will short circuit out early when the * vnode ops ptrs are different. Just in case we're dealing * with LOFS, compare exi_fid/fsid here. * * expseudo is not set because this is not an export */ if (EQFID(&exi->exi_fid, &fid) && EQFSID(&exi->exi_fsid, &vp->v_vfsp->vfs_fsid)) { *expseudo = 0; return (1); } /* See if it matches any fid in the visible list */ for (visp = exi->exi_visible; visp; visp = visp->vis_next) { if (EQFID(&fid, &visp->vis_fid)) { *expseudo = visp->vis_exported; return (1); } } *expseudo = 0; return (0); }