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