d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * CDDL HEADER START
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * The contents of this file are subject to the terms of the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Common Development and Distribution License (the "License").
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * You may not use this file except in compliance with the License.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * or http://www.opensolaris.org/os/licensing.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * See the License for the specific language governing permissions
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * and limitations under the License.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * When distributing Covered Code, include this CDDL HEADER in each
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * If applicable, add the following below this CDDL HEADER, with the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * fields enclosed by brackets "[]" replaced with your own identifying
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * information: Portions Copyright [yyyy] [name of copyright owner]
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * CDDL HEADER END
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Use is subject to license terms.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * vnode ops for the /dev/net directory
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * The lookup is based on the internal vanity naming node table. We also
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * override readdir in order to delete net nodes no longer in-use.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/types.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/param.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/sysmacros.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/sunndi.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <fs/fs_subr.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/fs/dv_node.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/fs/sdev_impl.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/policy.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/zone.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz#include <sys/dls.h>
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstruct vnodeops *devnet_vnodeops;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Check if a net sdev_node is still valid - i.e. it represents a current
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * network link.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * This serves two purposes
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * - only valid net nodes are returned during lookup() and readdir().
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * - since net sdev_nodes are not actively destroyed when a network link
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * goes away, we use the validator to do deferred cleanup i.e. when such
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * nodes are encountered during subsequent lookup() and readdir().
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzint
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevnet_validate(struct sdev_node *dv)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz datalink_id_t linkid;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy zoneid_t zoneid;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(dv->sdev_state == SDEV_READY);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (dls_mgmt_get_linkid(dv->sdev_name, &linkid) != 0)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (SDEV_VTOR_INVALID);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (SDEV_IS_GLOBAL(dv))
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (SDEV_VTOR_VALID);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy zoneid = getzoneid();
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (zone_check_datalink(&zoneid, linkid) == 0 ?
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy SDEV_VTOR_VALID : SDEV_VTOR_INVALID);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * This callback is invoked from devname_lookup_func() to create
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * a net entry when the node is not found in the cache.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevnet_create_rvp(const char *nm, struct vattr *vap, dls_dl_handle_t *ddhp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz timestruc_t now;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dev_t dev;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int error;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((error = dls_devnet_open(nm, ddhp, &dev)) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz sdcmn_err12(("devnet_create_rvp: not a valid vanity name "
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "network node: %s\n", nm));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (error);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * This is a valid network device (at least at this point in time).
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Create the node by setting the attribute; the rest is taken care
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * of by devname_lookup_func().
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *vap = sdev_vattr_chr;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vap->va_mode |= 0666;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vap->va_rdev = dev;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz gethrestime(&now);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vap->va_atime = now;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vap->va_mtime = now;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz vap->va_ctime = now;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Lookup for /dev/net directory
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * If the entry does not exist, the devnet_create_rvp() callback
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * is invoked to create it. Nodes do not persist across reboot.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED3*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevnet_lookup(struct vnode *dvp, char *nm, struct vnode **vpp,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct pathname *pnp, int flags, struct vnode *rdir, struct cred *cred,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz caller_context_t *ct, int *direntflags, pathname_t *realpnp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct sdev_node *ddv = VTOSDEV(dvp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct sdev_node *dv = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dls_dl_handle_t ddh = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct vattr vattr;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int nmlen;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int error = ENOENT;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (SDEVTOV(ddv)->v_type != VDIR)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (ENOTDIR);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Empty name or ., return node itself.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz nmlen = strlen(nm);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((nmlen == 0) || ((nmlen == 1) && (nm[0] == '.'))) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *vpp = SDEVTOV(ddv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VN_HOLD(*vpp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * .., return the parent directory
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((nmlen == 2) && (strcmp(nm, "..") == 0)) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *vpp = SDEVTOV(ddv->sdev_dotdot);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VN_HOLD(*vpp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_enter(&ddv->sdev_contents, RW_WRITER);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * directory cache lookup:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((dv = sdev_cache_lookup(ddv, nm)) != NULL) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi ASSERT(dv->sdev_state == SDEV_READY);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (!(dv->sdev_flags & SDEV_ATTR_INVALID))
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi goto found;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * ZOMBIED parent does not allow new node creation, bail out early.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ddv->sdev_state == SDEV_ZOMBIE)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto failed;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz error = devnet_create_rvp(nm, &vattr, &ddh);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (error != 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto failed;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz error = sdev_mknode(ddv, nm, &dv, &vattr, NULL, NULL, cred, SDEV_READY);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (error != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dls_devnet_close(ddh);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto failed;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(dv != NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_enter(&dv->sdev_contents, RW_WRITER);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dv->sdev_flags & SDEV_ATTR_INVALID) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * SDEV_ATTR_INVALID means that this device has been
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * detached, and its dev_t might've been changed too.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Therefore, sdev_node's 'vattr' needs to be updated.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz SDEVTOV(dv)->v_rdev = vattr.va_rdev;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(dv->sdev_attr != NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dv->sdev_attr->va_rdev = vattr.va_rdev;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dv->sdev_flags &= ~SDEV_ATTR_INVALID;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(dv->sdev_private == NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dv->sdev_private = ddh;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_exit(&dv->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzfound:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(SDEV_HELD(dv));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_exit(&ddv->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (sdev_to_vp(dv, vpp));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzfailed:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_exit(&ddv->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dv != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz SDEV_RELE(dv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz *vpp = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (error);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roydevnet_filldir_datalink(datalink_id_t linkid, void *arg)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy struct sdev_node *ddv = arg;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy struct vattr vattr;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy struct sdev_node *dv;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy dls_dl_handle_t ddh = NULL;
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy char link[MAXLINKNAMELEN];
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (dls_mgmt_get_linkinfo(linkid, link, NULL, NULL, NULL) != 0)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy return (0);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if ((dv = sdev_cache_lookup(ddv, (char *)link)) != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto found;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (devnet_create_rvp(link, &vattr, &ddh) != 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(ddh != NULL);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dls_devnet_close(ddh);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (sdev_mknode(ddv, (char *)link, &dv, &vattr, NULL, NULL, kcred,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz SDEV_READY) != 0) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * As there is no reference holding the network device, it could be
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * detached. Set SDEV_ATTR_INVALID so that the 'vattr' will be updated
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * later.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_enter(&dv->sdev_contents, RW_WRITER);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dv->sdev_flags |= SDEV_ATTR_INVALID;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_exit(&dv->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzfound:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz SDEV_SIMPLE_RELE(dv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevnet_filldir(struct sdev_node *ddv)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz sdev_node_t *dv, *next;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz datalink_id_t linkid;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(RW_READ_HELD(&ddv->sdev_contents));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (rw_tryupgrade(&ddv->sdev_contents) == NULL) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_exit(&ddv->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_enter(&ddv->sdev_contents, RW_WRITER);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg for (dv = SDEV_FIRST_ENTRY(ddv); dv; dv = next) {
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg next = SDEV_NEXT_ENTRY(ddv, dv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* validate and prune only ready nodes */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dv->sdev_state != SDEV_READY)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz switch (devnet_validate(dv)) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case SDEV_VTOR_VALID:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case SDEV_VTOR_SKIP:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz case SDEV_VTOR_INVALID:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case SDEV_VTOR_STALE:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz sdcmn_err12(("devnet_filldir: destroy invalid "
d62bc4badc1c1f1549c961cfb8b420e650e1272byz "node: %s(%p)\n", dv->sdev_name, (void *)dv));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz break;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (SDEVTOV(dv)->v_count > 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz continue;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz SDEV_HOLD(dv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /* remove the cache node */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) sdev_cache_update(ddv, &dv, dv->sdev_name,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz SDEV_CACHE_DELETE);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_RELE(dv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (((ddv->sdev_flags & SDEV_BUILD) == 0) && !dls_devnet_rebuild())
d62bc4badc1c1f1549c961cfb8b420e650e1272byz goto done;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (SDEV_IS_GLOBAL(ddv)) {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz linkid = DATALINK_INVALID_LINKID;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz do {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz linkid = dls_mgmt_get_next(linkid, DATALINK_CLASS_ALL,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz DATALINK_ANY_MEDIATYPE, DLMGMT_ACTIVE);
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy if (linkid != DATALINK_INVALID_LINKID)
2b24ab6b3865caeede9eeb9db6b83e1d89dcd1eaSebastien Roy (void) devnet_filldir_datalink(linkid, ddv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } while (linkid != DATALINK_INVALID_LINKID);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz (void) zone_datalink_walk(getzoneid(),
d62bc4badc1c1f1549c961cfb8b420e650e1272byz devnet_filldir_datalink, ddv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ddv->sdev_flags &= ~SDEV_BUILD;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdone:
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_downgrade(&ddv->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * Display all instantiated network datalink device nodes.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * A /dev/net entry will be created only after the first lookup of
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * the network datalink device succeeds.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED4*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic int
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevnet_readdir(struct vnode *dvp, struct uio *uiop, struct cred *cred,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int *eofp, caller_context_t *ct, int flags)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct sdev_node *sdvp = VTOSDEV(dvp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(sdvp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (uiop->uio_offset == 0)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz devnet_filldir(sdvp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return (devname_readdir_func(dvp, uiop, cred, eofp, 0));
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * This callback is invoked from devname_inactive_func() to release
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * the net entry which was held in devnet_create_rvp().
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevnet_inactive_callback(struct vnode *dvp)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct sdev_node *sdvp = VTOSDEV(dvp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dls_dl_handle_t ddh;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (dvp->v_type == VDIR)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz return;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(dvp->v_type == VCHR);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_enter(&sdvp->sdev_contents, RW_WRITER);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ddh = sdvp->sdev_private;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz sdvp->sdev_private = NULL;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz sdvp->sdev_flags |= SDEV_ATTR_INVALID;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz rw_exit(&sdvp->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * "ddh" (sdev_private) could be NULL if devnet_lookup fails.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (ddh != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz dls_devnet_close(ddh);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*ARGSUSED*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzstatic void
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevnet_inactive(struct vnode *dvp, struct cred *cred, caller_context_t *ct)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz devname_inactive_func(dvp, cred, devnet_inactive_callback);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * We override lookup and readdir to build entries based on the
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * in kernel vanity naming node table.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byzconst fs_operation_def_t devnet_vnodeops_tbl[] = {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_READDIR, { .vop_readdir = devnet_readdir },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_LOOKUP, { .vop_lookup = devnet_lookup },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_INACTIVE, { .vop_inactive = devnet_inactive },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_CREATE, { .error = fs_nosys },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_REMOVE, { .error = fs_nosys },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_MKDIR, { .error = fs_nosys },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_RMDIR, { .error = fs_nosys },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_SYMLINK, { .error = fs_nosys },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz VOPNAME_SETSECATTR, { .error = fs_nosys },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz NULL, NULL
d62bc4badc1c1f1549c961cfb8b420e650e1272byz};