facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * CDDL HEADER START
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * The contents of this file are subject to the terms of the
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Common Development and Distribution License (the "License").
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * You may not use this file except in compliance with the License.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * See the License for the specific language governing permissions
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * and limitations under the License.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * When distributing Covered Code, include this CDDL HEADER in each
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * If applicable, add the following below this CDDL HEADER, with the
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * fields enclosed by brackets "[]" replaced with your own identifying
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * information: Portions Copyright [yyyy] [name of copyright owner]
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * CDDL HEADER END
0fbb751d81ab0a7c7ddfd8d4e447e075a9f7024fJohn Levon * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
45b1747515a17db45e8971501ee84a26bdff37b2Alex Wilson * Copyright (c) 2013, 2016 Joyent, Inc. All rights reserved.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * utility routines for the /dev fs
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* prototype memory vattrs */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_fsid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nodeid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nlink */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_size */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_atime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_mtime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_ctime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_rdev */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_blksize */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nblocks */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0 /* va_vcode */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_fsid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nodeid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nlink */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_size */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_atime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_mtime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_ctime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_rdev */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_blksize */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nblocks */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0 /* va_vcode */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_fsid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nodeid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nlink */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_size */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_atime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_mtime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_ctime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_rdev */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_blksize */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nblocks */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0 /* va_vcode */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_fsid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nodeid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nlink */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_size */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_atime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_mtime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_ctime */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_rdev */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_blksize */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0, /* va_nblocks */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai 0 /* va_vcode */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* static */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic struct vnodeops *sdev_get_vop(struct sdev_node *);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylorstatic void sdev_set_no_negcache(struct sdev_node *);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic fs_operation_def_t *sdev_merge_vtab(const fs_operation_def_t []);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(dv->sdev_prof.dev_glob_incdir);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(dv->sdev_prof.dev_glob_excdir);
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee/* sdev_node cache constructor */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED1*/
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee return (-1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee/* sdev_node cache destructor */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED1*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* initialize sdev_node cache */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#endif /* DEBUG */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sizeof (struct sdev_node), 0, i_sdev_node_ctor, i_sdev_node_dtor,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* destroy sdev_node cache */
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg * Compare two nodes lexographically to balance avl tree
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jgsdev_compare_nodes(const struct sdev_node *dv1, const struct sdev_node *dv2)
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_set_nodestate(struct sdev_node *dv, sdev_node_state_t state)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliamsdev_attr_update(struct sdev_node *dv, vattr_t *vap)
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp->va_atime = (mask & AT_ATIME) ? vap->va_atime : now;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp->va_mtime = (mask & AT_MTIME) ? vap->va_mtime : now;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp->va_ctime = (mask & AT_CTIME) ? vap->va_ctime : now;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliamsdev_attr_alloc(struct sdev_node *dv, vattr_t *vap)
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam dv->sdev_attr = kmem_zalloc(sizeof (struct vattr), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* alloc and initialize a sdev_node */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nodeinit(struct sdev_node *ddv, char *nm, struct sdev_node **newdv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) snprintf(dv->sdev_path, len, "%s/%s", ddv->sdev_path, nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* overwritten for VLNK nodes */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * initialized to the parent's vnodeops.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * maybe overwriten for a VDIR
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags = ddv->sdev_flags; /* inherit from the parent first */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * Transition a sdev_node into SDEV_READY state. If this fails, it is up to the
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * caller to transition the node to the SDEV_ZOMBIE state.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nodeready(struct sdev_node *dv, struct vattr *vap, struct vnode *avp,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_setops(vp, sdev_get_vop(dv)); /* from internal vtab */
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg (int (*)(const void *, const void *))sdev_compare_nodes,
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg sizeof (struct sdev_node),
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_symlink = i_ddi_strdup((char *)args, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * shadow node is created here OR
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * if failed (indicated by dv->sdev_attrvp == NULL),
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * created later in sdev_setattr
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if ((dv->sdev_attrvp == NULL) && SDEV_IS_PERSIST(dv))
b7beec954f20585da1efb36c9c4b96bba6429210jg if (error == 0) {
b7beec954f20585da1efb36c9c4b96bba6429210jg /* transition to READY state */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Build the VROOT sdev_node.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_mkroot(struct vfs *vfsp, dev_t devdev, struct vnode *mvp,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_setops(vp, sdev_vnodeops); /* apply the default vnodeops at /dev */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* vfs_mountdev1 set mount point later */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_namelen = strlen(dv->sdev_name); /* '\0' not included */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg (int (*)(const void *, const void *))sdev_compare_nodes,
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg sizeof (struct sdev_node),
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* directory dependent vop table */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai const fs_operation_def_t *vt_service; /* vnodeops table */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnodeops **vt_global_vops; /* global container for vop */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int (*vt_vtor)(struct sdev_node *); /* validate sdev_node */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * A nice improvement would be to provide a plug-in mechanism
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * for this table instead of a const table.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai { "pts", devpts_vnodeops_tbl, NULL, &devpts_vnodeops, devpts_validate,
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China { "vt", devvt_vnodeops_tbl, NULL, &devvt_vnodeops, devvt_validate,
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China SDEV_DYNAMIC | SDEV_VTOR },
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor { "zvol", devzvol_vnodeops_tbl, NULL, &devzvol_vnodeops,
dd9c3b29f8e9f6b99b80e1fd8fc03241abd67311Jerry Jelinek devzvol_validate, SDEV_ZONED | SDEV_DYNAMIC | SDEV_VTOR | SDEV_SUBDIR },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz { "net", devnet_vnodeops_tbl, NULL, &devnet_vnodeops, devnet_validate,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk { "ipnet", devipnet_vnodeops_tbl, NULL, &devipnet_vnodeops,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk devipnet_validate, SDEV_DYNAMIC | SDEV_VTOR | SDEV_NO_NCACHE },
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * SDEV_DYNAMIC: prevent calling out to devfsadm, since only the
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * lofi driver controls child nodes.
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * SDEV_PERSIST: ensure devfsadm knows to clean up any persisted
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * stale nodes (e.g. from devfsadm -R).
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * In addition, devfsadm knows not to attempt a rmdir: a zone
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * may hold a reference, which would zombify the node,
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * preventing a mkdir.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * We need to match off of the sdev_path, not the sdev_name. We are only allowed
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * to exist directly under /dev.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (strncmp(dv->sdev_path, "/dev/", 5) != 0)
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return (&vtab[i]);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return (&vtab[i]);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sets a directory's vnodeops if the directory is in the vtab;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic struct vnodeops *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* gets the relative path to /dev/ */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor /* gets the vtab entry it matches */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi (SDEV_IS_PERSIST(dv) || !SDEV_IS_DYNAMIC(dv)))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*NOTREACHED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* child inherits the persistence of the parent */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Build the base root inode
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * for now, follow the lead of tmpfs here
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * need to someday understand the requirements here
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* mission complete */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * A convenient wrapper to get the devfs node vnode for a device
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * minor functionality: readlink() of a /dev symlink
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Place the link into dv->sdev_symlink
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_node_check(struct sdev_node *dv, struct vattr *nvap, void *nargs)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * existing sdev_node has a different type.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " %s type %d does not match new node type %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * For a symlink, the target should be the same.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " %s has different symlink %s as new node "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_mknode - a wrapper for sdev_nodeinit(), sdev_nodeready()
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * arguments:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * - ddv (parent)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * - nm (child name)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * - newdv (sdev_node for nm is returned here)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * - vap (vattr for the node to be created, va_type should be set.
b7beec954f20585da1efb36c9c4b96bba6429210jg * - avp (attribute vnode)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the defaults should be used if unknown)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * . tnm (for VLNK)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * . global sdev_node (for !SDEV_GLOBAL)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * - state: SDEV_INIT, SDEV_READY
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * only ddv, nm, newddv, vap, cred are required for sdev_mknode(SDEV_INIT)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * NOTE: directory contents writers lock needs to be held before
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * calling this routine.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_mknode(struct sdev_node *ddv, char *nm, struct sdev_node **newdv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr *vap, struct vnode *avp, void *args, struct cred *cred,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* allocate and initialize a sdev_node */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error != 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " name %s can not be initialized\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* insert into the directory cache */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_ADD);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " be transitioned into READY state, "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Do some sanity checking to make sure
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the existing sdev_node is what has been
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * asked for.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_DELETE);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * We created this node, it wasn't passed into us. Therefore it
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * is up to us to delete it.
b7beec954f20585da1efb36c9c4b96bba6429210jg * convenient wrapper to change vp's ATIME, CTIME and MTIME
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_update_timestamps(struct vnode *vp, cred_t *cred, uint_t mask)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the backing store vnode is released here
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED1*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* no references */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * reset the attrvp so that no more
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * references can be made on this already
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * vn_rele() vnode
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(dv->sdev_symlink, strlen(dv->sdev_symlink) + 1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* return node to initial state as per constructor */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * DIRECTORY CACHE lookup
ecb4d93a50f2e89903a83c86c7a8c7f8740e512bjg return (dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Inserts a new sdev_node in a parent directory
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_direnter(struct sdev_node *ddv, struct sdev_node *dv)
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg VERIFY(avl_find(&ddv->sdev_entries, dv, &where) == NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * The following check is needed because while sdev_nodes are linked
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * in SDEV_INIT state, they have their link counts incremented only
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * in SDEV_READY state.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Delete an existing dv from directory cache
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * In the case of a node is still held by non-zero reference count, the node is
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * put into ZOMBIE state. The node is always unlinked from its parent, but it is
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * not destroyed via sdev_inactive until its reference count reaches "0".
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_dirdelete(struct sdev_node *ddv, struct sdev_node *dv)
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * unlink ourselves from the parent directory now to take care of the ..
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * link. However, if we're a directory, we don't remove our reference to
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * ourself eg. '.' until we are torn down in the inactive callback.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * sdev_inactive expects nodes to have a link to themselves when we're
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * tearing them down. If we're transitioning from the initial state to
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * zombie and not via ready, then we're not going to have this link that
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * comes from the node being ready. As a result, we need to increment
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * our link count by one to account for this.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (os == SDEV_INIT && dv->sdev_nlink == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * check if the source is in the path of the target
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * source and target are different
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED2*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_checkpath(struct sdev_node *sdv, struct sdev_node *tdv, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* fs root */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (;;) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * avoid error cases like
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * mv a a/b
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * mv a a/b/c
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* done checking because root is reached */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_rnmnode(struct sdev_node *oddv, struct sdev_node *odv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *nddv, struct sdev_node **ndvp, char *nnm,
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
0bfaec6936a60046cf3a098fa731cb5e07377595llai * the source may have been deleted by another thread before
0bfaec6936a60046cf3a098fa731cb5e07377595llai * we gets here.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * If renaming a directory, and the parents are different (".." must be
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * changed) then the source dir must not be in the dir hierarchy above
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the target since it would orphan everything below the source dir.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /* fix the source for a symlink */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * The underlying symlink doesn't exist. This
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * node probably shouldn't even exist. While
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * it's a bit jarring to consumers, we're going
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * to remove the node from /dev.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi link = i_ddi_strdup(odv->sdev_symlink, KM_SLEEP);
0bfaec6936a60046cf3a098fa731cb5e07377595llai /* destination existing */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* handling renaming to itself */
0bfaec6936a60046cf3a098fa731cb5e07377595llai /* in case dir1 exists in dir2 and "mv dir1 dir2" */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * We did not place the hold on *ndvp, so even though
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * we're deleting the node, we should not get rid of our
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * Get rid of the node from the directory cache note.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * Don't forget that it's not up to us to remove the vn
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * ref on the sdev node, as we did not place it.
0bfaec6936a60046cf3a098fa731cb5e07377595llai * make a fresh node from the source attrs
0bfaec6936a60046cf3a098fa731cb5e07377595llai /* move dir contents */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Merge sdev_node specific information into an attribute structure.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * note: sdev_node is not locked here
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_vattr_merge(struct sdev_node *dv, struct vattr *vap)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if ((vp->v_type == VCHR) || (vp->v_type == VBLK)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * If vnode is a device, return special vnode instead
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * (though it knows all about -us- via sp->s_realvp)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai default: /* most types are returned as is */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * junction between devname and root file system, e.g. ufs
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidevname_backstore_lookup(struct sdev_node *ddv, char *nm, struct vnode **rvp)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rval = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, kcred, NULL, NULL,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_filldir_from_store(struct sdev_node *ddv, int dlen, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* refill the cache if not already */
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam *vap = *sdev_getdefault_attr(VDIR); /* note structure copy here */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * This early, we may be in a read-only /dev environment: leave
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * the creation of any nodes we'd attempt to persist to
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * devfsadm. Because /dev itself is normally persistent, any
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * node which is not marked dynamic will end up being marked
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * persistent. However, some nodes are both dynamic and
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * persistent, mostly lofi and rlofi, so we need to be careful
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * in our check.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Creating a backing store entry based on sdev_attr.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * This is called either as part of node creation in a persistent directory
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * or from setattr/setsecattr to persist access attributes across reboot.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_shadow_node(struct sdev_node *dv, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&dv->sdev_contents) && dv->sdev_attrvp == NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* try to find it in the backing store */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, cred, NULL, NULL,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* let's try to persist the node */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_MKDIR(rdvp, nm, vap, rvp, cred, NULL, 0, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_shadow_node: mkdir vp %p error %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = VOP_CREATE(rdvp, nm, vap, NONEXCL, VREAD|VWRITE,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_shadow_node: create vp %p, error %d\n",
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_SYMLINK(rdvp, nm, vap, dv->sdev_symlink, cred,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_shadow_node: create symlink error %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*NOTREACHED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* go back to lookup to factor out spec node and set attrvp */
b7beec954f20585da1efb36c9c4b96bba6429210jg sdcmn_err(("cannot persist %s - error %d\n", dv->sdev_path, error));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cache_add(struct sdev_node *ddv, struct sdev_node **dv, char *nm)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cache_delete(struct sdev_node *ddv, struct sdev_node **dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * update the in-core directory cache
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cache_update(struct sdev_node *ddv, struct sdev_node **dv, char *nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (ops) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * retrieve the named entry from the directory cache
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Implicit reconfig for nodes constructed by a link generator
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Start devfsadm if needed, or if devfsadm is in progress,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * prepare to block on devfsadm either completing or
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * constructing the desired node. As devfsadmd is global
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * in scope, constructing all necessary nodes, we only
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * need to initiate it once.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_call_devfsadmd(struct sdev_node *ddv, struct sdev_node *dv, char *nm)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (!DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Support for specialized device naming construction mechanisms
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_call_dircallback(struct sdev_node *ddv, struct sdev_node **dvp, char *nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int (*callback)(struct sdev_node *, char *, void **, struct cred *,
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China physpath = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China rv = callback(ddv, nm, (void *)&physpath, kcred, NULL,
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China kmem_free(physpath, MAXPATHLEN);
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam *vap = *sdev_getdefault_attr(VLNK); /* structure copy */
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China vap->va_size = strlen(physpath);
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China rv = sdev_mknode(ddv, nm, &dv, vap, NULL,
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China (void *)physpath, cred, SDEV_READY);
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China kmem_free(physpath, MAXPATHLEN);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * callback is responsible to set the basic attributes,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * dev_t if VCHR or VBLK/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rv = callback(ddv, nm, (void *)&vattr, kcred, NULL, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "callback failed \n"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (-1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai impossible(("lookup: %s/%s by %s not supported (%d)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * note: because devfsadmd -> /usr/sbin/devfsadm
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * it is safe to use "devfsadm" to capture the lookups
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * from devfsadm and its daemon version.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Lookup Order:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_node cache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * backing store (SDEV_PERSIST);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * DBNR: a. dir_ops implemented in the loadable modules;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * b. vnode ops in vtab.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidevname_lookup_func(struct sdev_node *ddv, char *nm, struct vnode **vpp,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct cred *cred, int (*callback)(struct sdev_node *, char *, void **,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Empty name or ., return node itself.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((nmlen == 0) || ((nmlen == 1) && (nm[0] == '.'))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * .., return the parent directory
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * (a) directory cache lookup:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* ZOMBIED parent won't allow node creation */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* compensate the threads started after devfsadm */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error != 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * ZOMBIED parent does not allow new node creation.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * bail out early
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * (b0): backing store lookup
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * SDEV_PERSIST is default except:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * 1) pts nodes
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * 2) non-chmod'ed local nodes
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor * 3) zvol nodes
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (retried) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* first thread that is doing the lookup on this node */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor error = sdev_call_dircallback(ddv, &dv, nm, callback,
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor * (b1) invoking devfsadm once per life time for devfsadm nodes
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (sdev_reconfig_boot || !i_ddi_io_initialized() ||
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SDEV_IS_DYNAMIC(ddv) || SDEV_IS_NO_NCACHE(dv) ||
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor * filter out known non-existent devices recorded
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor * during initial reconfiguration boot for which
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor * reconfig should not be done and lookup may
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor * be short-circuited now.
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor /* bypassing devfsadm internal nodes */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor sdcmn_err8(("lookup of %s/%s by %s: reconfig\n",
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor "?lookup of %s/%s by %s: reconfig\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Check validity of returned node
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * The name exists, but the cache entry is
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * stale and needs to be re-created.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_DELETE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* FALLTHRU */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "dev fs: validator failed: %s(%p)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err3(("devname_lookup_func: returning vp %p v_count %d state %d "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "for nm %s, error %d\n", (void *)*vpp, (*vpp)->v_count,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Destroy the node that is created for synchronization purposes.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Node state may have changed during the lock
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * changes. Re-check.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Given a directory node, mark all nodes beneath as
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * STALE, i.e. nodes that don't exist as far as new
ecb4d93a50f2e89903a83c86c7a8c7f8740e512bjg * consumers are concerned. Remove them from the
ecb4d93a50f2e89903a83c86c7a8c7f8740e512bjg * list of directory entries so that no lookup or
ecb4d93a50f2e89903a83c86c7a8c7f8740e512bjg * directory traversal will find them. The node
ecb4d93a50f2e89903a83c86c7a8c7f8740e512bjg * not deallocated so existing holds are not affected.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi while ((dv = SDEV_FIRST_ENTRY(ddv)) != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Given a directory node, clean out all the nodes beneath.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * If expr is specified, clean node with names matching expr.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * If SDEV_ENFORCE is specified in flags, busy nodes are made stale,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * so they are excluded from future lookups.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cleandir(struct sdev_node *ddv, char *expr, uint_t flags)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * We try our best to destroy all unused sdev_node's
45b1747515a17db45e8971501ee84a26bdff37b2Alex Wilson for (dv = SDEV_FIRST_ENTRY(ddv); dv != NULL; dv = next) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * at this point, either dv is not held or SDEV_ENFORCE
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * is specified. In either case, dv needs to be deleted
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* take care the backing store clean up */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* do not propagate the backing store errors */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "not cleaned\n"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * a convenient wrapper for readdir() funcs
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiadd_dir_entry(dirent64_t *de, char *nm, size_t size, ino_t ino, offset_t off)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) strncpy(de->d_name, nm, DIRENT64_NAMELEN(reclen));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_mount service routines
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_copyin_mountargs(struct mounta *uap, struct sdev_mountargs *args)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error = copyin(uap->dataptr, args, sizeof (*args))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * readdir helper func
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidevname_readdir_func(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor if ((sdev_boot_state == SDEV_BOOT_STATE_COMPLETE) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * invoking "devfsadm" to do system device reconfig
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "?readdir of %s by %s: reconfig\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * compensate the "ls" started later than "devfsadm"
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * release the contents lock so that
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg * the cache may be updated by devfsadmd
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* handle "." and ".." */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (soff == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* first time */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* gets the cache */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err3(("sdev_readdir: diroff %lld soff %lld for '%s' \n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* bypassing pre-matured nodes */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Check validity of node
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * Drop invalid and nodes to be skipped.
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * A node the validator indicates as stale needs
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * to be returned as presumably the node name itself
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * is valid and the node data itself will be refreshed
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * on lookup. An application performing a readdir then
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * stat on each entry should thus always see consistent
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * data. In any case, it is not possible to synchronize
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * with dynamic kernel state, and any view we return can
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam * never be anything more than a snapshot at a point in time.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "dev fs: validator failed: %s(%p)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*NOTREACHED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "diroff %lld, soff %lld, dv %p\n", outcount, diroff, soff,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void *)dv));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) VOP_SETATTR(ddv->sdev_attrvp, &attr, 0, kcred, NULL);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam ASSERT(vp->v_type == VDIR || vp->v_type == VLNK);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam * Deal with the .. special case where we may be
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam * traversing up across a mount point, to the
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam * root of this filesystem or global root.
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_LOOKUP(vp, nm, &cvp, NULL, 0, NULL, kcred, NULL,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* traverse mount points encountered on our journey */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vn_ismntpt(cvp) && (error = traverse(&cvp)) != 0) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam * symbolic link, can be either relative and absolute
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if ((cvp->v_type == VLNK) && pn_pathleft(&pn)) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (error = pn_getsymlink(cvp, &linkpath, kcred)) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam error = pn_insert(&pn, &linkpath, strlen(nm));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Direct the operation to the persisting filesystem
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * underlying /dev. Bail if we encounter a
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * non-persistent dev entity here.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Only return persisted nodes in the filesystem underlying /dev.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (dp = dbuf; ((intptr_t)dp < (intptr_t)dbuf + dbuflen);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai newlist = (char **)
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth sizeof (char *), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai npaths * sizeof (char *));
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth /* if checking empty, one entry is as good as many */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_modctl_readdir_free(char **pathlist, int npaths, int npaths_alloc)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (i = 0; i < npaths; i++) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(pathlist, (npaths_alloc + 1) * sizeof (char *));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * construct a new template with overrides from vtab
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* make a copy of standard vnode ops table */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bcopy((void *)sdev_vnodeops_tbl, new, sdev_vnodeops_tbl_size);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* replace the overrides from tab */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (tab_entry = tab; tab_entry->name != NULL; tab_entry++) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* free memory allocated by sdev_merge_vtab */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * a generic setattr() function
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * note: flags only supports AT_UID and AT_GID.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Future enhancements can be done for other types, e.g. AT_MODE
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidevname_setattr_func(struct vnode *vp, struct vattr *vap, int flags,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct cred *cred, int (*callback)(struct sdev_node *, struct vattr *,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* some sanity checks */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* no need to set attribute, but do not fail either */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* If backing store exists, just set it. */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Otherwise, for nodes with the persistence attribute, create it.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ((vap->va_mask & ~AT_TIMES) != 0 && !SDEV_IS_DYNAMIC(dv))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_attr was allocated in sdev_mknode
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * a callback must be provided if the protocol is set
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * a generic inactive() function
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevname_inactive_func(struct vnode *vp, struct cred *cred,
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * sdev is a rather bad public citizen. It violates the general
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * agreement that in memory nodes should always have a valid reference
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * count on their vnode. But that's not the case here. This means that
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * we do actually have to distinguish between getting inactive callbacks
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * for zombies and otherwise. This should probably be fixed.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /* Remove the . entry to ourselves */