facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * CDDL HEADER START
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
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 *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * or http://www.opensolaris.org/os/licensing.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * See the License for the specific language governing permissions
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * and limitations under the License.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
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 *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * CDDL HEADER END
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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 */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * utility routines for the /dev fs
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/types.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/param.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/t_lock.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/systm.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/sysmacros.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/user.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/time.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/vfs.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/vnode.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/file.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/fcntl.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/flock.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/kmem.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/uio.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/errno.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/stat.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/cred.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/dirent.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/pathname.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/cmn_err.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/debug.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/mode.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/policy.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <fs/fs_subr.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/mount.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/fs/snode.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/fs/dv_node.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/fs/sdev_impl.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/sunndi.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/sunmdi.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/conf.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/proc.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/user.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#include <sys/modctl.h>
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#ifdef DEBUG
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint sdev_debug = 0x00000001;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint sdev_debug_cache_flags = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#endif
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * globals
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* prototype memory vattrs */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivattr_t sdev_vattr_dir = {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VDIR, /* va_type */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_DIRMODE_DEFAULT, /* va_mode */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_UID_DEFAULT, /* va_uid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_GID_DEFAULT, /* va_gid */
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};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivattr_t sdev_vattr_lnk = {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai AT_TYPE|AT_MODE, /* va_mask */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VLNK, /* va_type */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_LNKMODE_DEFAULT, /* va_mode */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_UID_DEFAULT, /* va_uid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_GID_DEFAULT, /* va_gid */
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};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivattr_t sdev_vattr_blk = {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VBLK, /* va_type */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai S_IFBLK | SDEV_DEVMODE_DEFAULT, /* va_mode */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_UID_DEFAULT, /* va_uid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_GID_DEFAULT, /* va_gid */
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};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivattr_t sdev_vattr_chr = {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai AT_TYPE|AT_MODE|AT_UID|AT_GID, /* va_mask */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VCHR, /* va_type */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai S_IFCHR | SDEV_DEVMODE_DEFAULT, /* va_mode */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_UID_DEFAULT, /* va_uid */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_GID_DEFAULT, /* va_gid */
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};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaikmem_cache_t *sdev_node_cache; /* sdev_node cache */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint devtype; /* fstype */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
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 sdev_free_vtab(fs_operation_def_t *);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_prof_free(struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(!SDEV_IS_GLOBAL(dv));
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(dv->sdev_prof.dev_name);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(dv->sdev_prof.dev_map);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(dv->sdev_prof.dev_symlink);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(dv->sdev_prof.dev_glob_incdir);
aab83bb83be7342f6cfccaed8d5fe0b2f404855dJosef 'Jeff' Sipek nvlist_free(dv->sdev_prof.dev_glob_excdir);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee/* sdev_node cache constructor */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED1*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaii_sdev_node_ctor(void *buf, void *cfarg, int flag)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = (struct sdev_node *)buf;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bzero(buf, sizeof (struct sdev_node));
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee vp = dv->sdev_vnode = vn_alloc(flag);
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee if (vp == NULL) {
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee return (-1);
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee }
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee vp->v_data = dv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_init(&dv->sdev_contents, NULL, RW_DEFAULT, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
b5fca8f855054d167d04d3b4de5210c83ed2083ctomee/* sdev_node cache destructor */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED1*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaii_sdev_node_dtor(void *buf, void *arg)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = (struct sdev_node *)buf;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_destroy(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_free(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* initialize sdev_node cache */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_node_cache_init()
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int flags = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#ifdef DEBUG
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai flags = sdev_debug_cache_flags;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (flags)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err(("cache debug flags 0x%x\n", flags));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#endif /* DEBUG */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(sdev_node_cache == NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_node_cache = kmem_cache_create("sdev_node_cache",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sizeof (struct sdev_node), 0, i_sdev_node_ctor, i_sdev_node_dtor,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai NULL, NULL, NULL, flags);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* destroy sdev_node cache */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_node_cache_fini()
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(sdev_node_cache != NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_cache_destroy(sdev_node_cache);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_node_cache = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg/*
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg * Compare two nodes lexographically to balance avl tree
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg */
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jgstatic int
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jgsdev_compare_nodes(const struct sdev_node *dv1, const struct sdev_node *dv2)
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg{
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg int rv;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg if ((rv = strcmp(dv1->sdev_name, dv2->sdev_name)) == 0)
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg return (0);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg return ((rv < 0) ? -1 : 1);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg}
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_set_nodestate(struct sdev_node *dv, sdev_node_state_t state)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&dv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_state = state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliamsdev_attr_update(struct sdev_node *dv, vattr_t *vap)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam timestruc_t now;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam struct vattr *attrp;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam uint_t mask;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam ASSERT(dv->sdev_attr);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(vap);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp = dv->sdev_attr;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam mask = vap->va_mask;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam if (mask & AT_TYPE)
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp->va_type = vap->va_type;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam if (mask & AT_MODE)
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp->va_mode = vap->va_mode;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam if (mask & AT_UID)
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp->va_uid = vap->va_uid;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam if (mask & AT_GID)
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp->va_gid = vap->va_gid;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam if (mask & AT_RDEV)
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam attrp->va_rdev = vap->va_rdev;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai gethrestime(&now);
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 Gilliam}
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliamstatic void
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliamsdev_attr_alloc(struct sdev_node *dv, vattr_t *vap)
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam{
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam ASSERT(dv->sdev_attr == NULL);
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam ASSERT(vap->va_mask & AT_TYPE);
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam ASSERT(vap->va_mask & AT_MODE);
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam dv->sdev_attr = kmem_zalloc(sizeof (struct vattr), KM_SLEEP);
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam sdev_attr_update(dv, vap);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* alloc and initialize a sdev_node */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nodeinit(struct sdev_node *ddv, char *nm, struct sdev_node **newdv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vattr_t *vap)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai size_t nmlen, len;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai devname_handle_t *dhl;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nmlen = strlen(nm) + 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (nmlen > MAXNAMELEN) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_nodeinit: node name %s"
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " too long\n", nm));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *newdv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENAMETOOLONG);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name = kmem_alloc(nmlen, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bcopy(nm, dv->sdev_name, nmlen);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_namelen = nmlen - 1; /* '\0' not included */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai len = strlen(ddv->sdev_path) + strlen(nm) + 2;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_path = kmem_alloc(len, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) snprintf(dv->sdev_path, len, "%s/%s", ddv->sdev_path, nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* overwritten for VLNK nodes */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_symlink = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_reinit(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_vfsp = SDEVTOV(ddv)->v_vfsp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vap)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_type = vap->va_type;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * initialized to the parent's vnodeops.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * maybe overwriten for a VDIR
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_setops(vp, vn_getops(SDEVTOV(ddv)));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_exists(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_dotdot = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attrvp = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vap) {
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam sdev_attr_alloc(dv, vap);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attr = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_ino = sdev_mkino(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_nlink = 0; /* updated on insert */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags = ddv->sdev_flags; /* inherit from the parent first */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags |= SDEV_BUILD;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cv_init(&dv->sdev_lookup_cv, NULL, CV_DEFAULT, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_GLOBAL(ddv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags |= SDEV_GLOBAL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dhl = &(dv->sdev_handle);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dhl->dh_data = dv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dhl->dh_args = NULL;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor sdev_set_no_negcache(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_gdir_gen = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags &= ~SDEV_GLOBAL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_origin = NULL; /* set later */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_ldir_gen = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_devtree_gen = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&dv->sdev_contents, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_set_nodestate(dv, SDEV_INIT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *newdv = dv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nodeready(struct sdev_node *dv, struct vattr *vap, struct vnode *avp,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai void *args, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vtype_t type;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv && (dv->sdev_state != SDEV_READY) && vap);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai type = vap->va_type;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_type = type;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_rdev = vap->va_rdev;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&dv->sdev_contents, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (type == VDIR) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_nlink = 2;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags &= ~SDEV_PERSIST;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags &= ~SDEV_DYNAMIC;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_setops(vp, sdev_get_vop(dv)); /* from internal vtab */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_dotdot);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(SDEVTOV(dv->sdev_dotdot)->v_type == VDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_rdev = SDEVTOV(dv->sdev_dotdot)->v_rdev;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg avl_create(&dv->sdev_entries,
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg (int (*)(const void *, const void *))sdev_compare_nodes,
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg sizeof (struct sdev_node),
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg offsetof(struct sdev_node, sdev_avllink));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (type == VLNK) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(args);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_nlink = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_symlink = i_ddi_strdup((char *)args, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_nlink = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!(SDEV_IS_GLOBAL(dv))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_origin = (struct sdev_node *)args;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags &= ~SDEV_PERSIST;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * shadow node is created here OR
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * if failed (indicated by dv->sdev_attrvp == NULL),
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * created later in sdev_setattr
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (avp) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attrvp = avp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam if (dv->sdev_attr == NULL) {
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam sdev_attr_alloc(dv, vap);
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam } else {
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam sdev_attr_update(dv, vap);
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if ((dv->sdev_attrvp == NULL) && SDEV_IS_PERSIST(dv))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_shadow_node(dv, cred);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
b7beec954f20585da1efb36c9c4b96bba6429210jg if (error == 0) {
b7beec954f20585da1efb36c9c4b96bba6429210jg /* transition to READY state */
b7beec954f20585da1efb36c9c4b96bba6429210jg sdev_set_nodestate(dv, SDEV_READY);
b7beec954f20585da1efb36c9c4b96bba6429210jg sdev_nc_node_exists(dv);
b7beec954f20585da1efb36c9c4b96bba6429210jg }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Build the VROOT sdev_node.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistruct sdev_node *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_mkroot(struct vfs *vfsp, dev_t devdev, struct vnode *mvp,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *avp, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char devdir[] = "/dev";
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(sdev_node_cache != NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(avp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv = kmem_cache_alloc(sdev_node_cache, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_reinit(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_flag |= VROOT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_vfsp = vfsp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_type = VDIR;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp->v_rdev = devdev;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_setops(vp, sdev_vnodeops); /* apply the default vnodeops at /dev */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_exists(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vfsp->vfs_mntpt)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name = i_ddi_strdup(
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (char *)refstr_value(vfsp->vfs_mntpt), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai else
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* vfs_mountdev1 set mount point later */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name = i_ddi_strdup("/dev", KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_namelen = strlen(dv->sdev_name); /* '\0' not included */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_path = i_ddi_strdup(devdir, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_ino = SDEV_ROOTINO;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_nlink = 2; /* name + . (no sdev_insert) */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_dotdot = dv; /* .. == self */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attrvp = avp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attr = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_init(&dv->sdev_lookup_lock, NULL, MUTEX_DEFAULT, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cv_init(&dv->sdev_lookup_cv, NULL, CV_DEFAULT, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (strcmp(dv->sdev_name, "/dev") == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags = SDEV_BUILD|SDEV_GLOBAL|SDEV_PERSIST;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bzero(&dv->sdev_handle, sizeof (dv->sdev_handle));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_gdir_gen = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags = SDEV_BUILD;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags &= ~SDEV_PERSIST;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bzero(&dv->sdev_prof, sizeof (dv->sdev_prof));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_ldir_gen = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_devtree_gen = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg avl_create(&dv->sdev_entries,
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg (int (*)(const void *, const void *))sdev_compare_nodes,
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg sizeof (struct sdev_node),
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg offsetof(struct sdev_node, sdev_avllink));
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&dv->sdev_contents, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_set_nodestate(dv, SDEV_READY);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_nc_node_exists(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* directory dependent vop table */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistruct sdev_vop_table {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *vt_name; /* subdirectory name */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai const fs_operation_def_t *vt_service; /* vnodeops table */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnodeops *vt_vops; /* constructed vop */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnodeops **vt_global_vops; /* global container for vop */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int (*vt_vtor)(struct sdev_node *); /* validate sdev_node */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int vt_flags;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * A nice improvement would be to provide a plug-in mechanism
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * for this table instead of a const table.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic struct sdev_vop_table vtab[] =
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai { "pts", devpts_vnodeops_tbl, NULL, &devpts_vnodeops, devpts_validate,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_DYNAMIC | SDEV_VTOR },
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
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 },
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor { "zvol", devzvol_vnodeops_tbl, NULL, &devzvol_vnodeops,
dd9c3b29f8e9f6b99b80e1fd8fc03241abd67311Jerry Jelinek devzvol_validate, SDEV_ZONED | SDEV_DYNAMIC | SDEV_VTOR | SDEV_SUBDIR },
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai { "zcons", NULL, NULL, NULL, NULL, SDEV_NO_NCACHE },
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
d62bc4badc1c1f1549c961cfb8b420e650e1272byz { "net", devnet_vnodeops_tbl, NULL, &devnet_vnodeops, devnet_validate,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz SDEV_DYNAMIC | SDEV_VTOR },
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk { "ipnet", devipnet_vnodeops_tbl, NULL, &devipnet_vnodeops,
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk devipnet_validate, SDEV_DYNAMIC | SDEV_VTOR | SDEV_NO_NCACHE },
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon /*
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * SDEV_DYNAMIC: prevent calling out to devfsadm, since only the
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * lofi driver controls child nodes.
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon *
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * SDEV_PERSIST: ensure devfsadm knows to clean up any persisted
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon * stale nodes (e.g. from devfsadm -R).
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon *
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.
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon */
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon { "lofi", NULL, NULL, NULL, NULL,
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon SDEV_ZONED | SDEV_DYNAMIC | SDEV_PERSIST },
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon { "rlofi", NULL, NULL, NULL, NULL,
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon SDEV_ZONED | SDEV_DYNAMIC | SDEV_PERSIST },
0fbb751d81ab0a7c7ddfd8d4e447e075a9f7024fJohn Levon
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai { NULL, NULL, NULL, NULL, NULL, 0}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi/*
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 */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylorstruct sdev_vop_table *
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylorsdev_match(struct sdev_node *dv)
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor{
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor int vlen;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor int i;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi const char *path;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (strlen(dv->sdev_path) <= 5)
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi return (NULL);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (strncmp(dv->sdev_path, "/dev/", 5) != 0)
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi return (NULL);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi path = dv->sdev_path + 5;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor for (i = 0; vtab[i].vt_name; i++) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (strcmp(vtab[i].vt_name, path) == 0)
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return (&vtab[i]);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (vtab[i].vt_flags & SDEV_SUBDIR) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor vlen = strlen(vtab[i].vt_name);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if ((strncmp(vtab[i].vt_name, path,
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi vlen - 1) == 0) && path[vlen] == '/')
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return (&vtab[i]);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor }
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor }
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return (NULL);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sets a directory's vnodeops if the directory is in the vtab;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic struct vnodeops *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_get_vop(struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor struct sdev_vop_table *vtp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *path;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai path = dv->sdev_path;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(path);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* gets the relative path to /dev/ */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai path += 5;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor /* gets the vtab entry it matches */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if ((vtp = sdev_match(dv)) != NULL) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor dv->sdev_flags |= vtp->vt_flags;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (SDEV_IS_PERSIST(dv->sdev_dotdot) &&
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi (SDEV_IS_PERSIST(dv) || !SDEV_IS_DYNAMIC(dv)))
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi dv->sdev_flags |= SDEV_PERSIST;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (vtp->vt_vops) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (vtp->vt_global_vops)
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor *(vtp->vt_global_vops) = vtp->vt_vops;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return (vtp->vt_vops);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (vtp->vt_service) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai fs_operation_def_t *templ;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor templ = sdev_merge_vtab(vtp->vt_service);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (vn_make_ops(vtp->vt_name,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (const fs_operation_def_t *)templ,
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor &vtp->vt_vops) != 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_PANIC, "%s: malformed vnode ops\n",
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor vtp->vt_name);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*NOTREACHED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (vtp->vt_global_vops) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor *(vtp->vt_global_vops) = vtp->vt_vops;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_free_vtab(templ);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return (vtp->vt_vops);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (sdev_vnodeops);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* child inherits the persistence of the parent */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_PERSIST(dv->sdev_dotdot))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags |= SDEV_PERSIST;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (sdev_vnodeops);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylorsdev_set_no_negcache(struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int i;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *path;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_path);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai path = dv->sdev_path + strlen("/dev/");
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (i = 0; vtab[i].vt_name; i++) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (strcmp(vtab[i].vt_name, path) == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vtab[i].vt_flags & SDEV_NO_NCACHE)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_flags |= SDEV_NO_NCACHE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_get_vtor(struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor struct sdev_vop_table *vtp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor vtp = sdev_match(dv);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (vtp)
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return ((void *)vtp->vt_vtor);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor else
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor return (NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Build the base root inode
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiino_t
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_mkino(struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ino_t ino;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * for now, follow the lead of tmpfs here
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * need to someday understand the requirements here
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ino = (ino_t)(uint32_t)((uintptr_t)dv >> 3);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ino += SDEV_ROOTINO + 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ino);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylorint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_getlink(struct vnode *linkvp, char **link)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int err;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *buf;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct uio uio = {0};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct iovec iov = {0};
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (linkvp == NULL)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(linkvp->v_type == VLNK);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai buf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai iov.iov_base = buf;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai iov.iov_len = MAXPATHLEN;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_iov = &iov;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_iovcnt = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_resid = MAXPATHLEN;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_segflg = UIO_SYSSPACE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_llimit = MAXOFFSET_T;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw err = VOP_READLINK(linkvp, &uio, kcred, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (err) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_WARN, "readlink %s failed in dev\n", buf);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(buf, MAXPATHLEN);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* mission complete */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *link = i_ddi_strdup(buf, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(buf, MAXPATHLEN);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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 */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_follow_link(struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int err;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *linkvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *link = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai linkvp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (linkvp == NULL)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(linkvp->v_type == VLNK);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai err = sdev_getlink(linkvp, &link);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (err) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_symlink = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(link != NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_symlink = link;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_node_check(struct sdev_node *dv, struct vattr *nvap, void *nargs)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vtype_t otype = SDEVTOV(dv)->v_type;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * existing sdev_node has a different type.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (otype != nvap->va_type) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_node_check: existing node "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " %s type %d does not match new node type %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name, otype, nvap->va_type));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (EEXIST);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * For a symlink, the target should be the same.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (otype == VLNK) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(nargs != NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_symlink != NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (strcmp(dv->sdev_symlink, (char *)nargs) != 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_node_check: existing node "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " %s has different symlink %s as new node "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " %s\n", dv->sdev_name, dv->sdev_symlink,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (char *)nargs));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (EEXIST);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_mknode - a wrapper for sdev_nodeinit(), sdev_nodeready()
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
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 * - cred
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * - args
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * . tnm (for VLNK)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * . global sdev_node (for !SDEV_GLOBAL)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * - state: SDEV_INIT, SDEV_READY
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * only ddv, nm, newddv, vap, cred are required for sdev_mknode(SDEV_INIT)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * NOTE: directory contents writers lock needs to be held before
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * calling this routine.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
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 sdev_node_state_t state)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_node_state_t node_state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(state != SDEV_ZOMBIE);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (*newdv) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv = *newdv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* allocate and initialize a sdev_node */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ddv->sdev_state == SDEV_ZOMBIE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_mknode: parent %s ZOMBIEd\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_path));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_nodeinit(ddv, nm, &dv, vap);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error != 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_mknode: error %d,"
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " name %s can not be initialized\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error, nm));
b7beec954f20585da1efb36c9c4b96bba6429210jg return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* insert into the directory cache */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_ADD);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai node_state = dv->sdev_state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(node_state != SDEV_ZOMBIE);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (state == SDEV_READY) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (node_state) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_INIT:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_nodeready(dv, vap, avp, args, cred);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_mknode: node %s can NOT"
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai " be transitioned into READY state, "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "error %d\n", nm, error));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_READY:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Do some sanity checking to make sure
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the existing sdev_node is what has been
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * asked for.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_node_check(dv, vap, args);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai default:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *newdv = dv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT((*newdv)->sdev_state != SDEV_ZOMBIE);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_DELETE);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /*
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * We created this node, it wasn't passed into us. Therefore it
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi * is up to us to delete it.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (*newdv == NULL)
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_SIMPLE_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *newdv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
b7beec954f20585da1efb36c9c4b96bba6429210jg * convenient wrapper to change vp's ATIME, CTIME and MTIME
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_update_timestamps(struct vnode *vp, cred_t *cred, uint_t mask)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr attr;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai timestruc_t now;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int err;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai gethrestime(&now);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & AT_CTIME)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai attr.va_ctime = now;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & AT_MTIME)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai attr.va_mtime = now;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & AT_ATIME)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai attr.va_atime = now;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai attr.va_mask = (mask & AT_TIMES);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai err = VOP_SETATTR(vp, &attr, 0, cred, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (err && (err != EROFS)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err(("update timestamps error %d\n", err));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * the backing store vnode is released here
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED1*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_nodedestroy(struct sdev_node *dv, uint_t flags)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* no references */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_nlink == 0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_attrvp != NULLVP) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(dv->sdev_attrvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * reset the attrvp so that no more
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * references can be made on this already
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * vn_rele() vnode
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attrvp = NULLVP;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_attr != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(dv->sdev_attr, sizeof (struct vattr));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attr = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_name != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(dv->sdev_name, dv->sdev_namelen + 1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_symlink != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(dv->sdev_symlink, strlen(dv->sdev_symlink) + 1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_symlink = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_path) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(dv->sdev_path, strlen(dv->sdev_path) + 1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_path = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!SDEV_IS_GLOBAL(dv))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_prof_free(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg if (SDEVTOV(dv)->v_type == VDIR) {
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg ASSERT(SDEV_FIRST_ENTRY(dv) == NULL);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg avl_destroy(&dv->sdev_entries);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg }
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_destroy(&dv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cv_destroy(&dv->sdev_lookup_cv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* return node to initial state as per constructor */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) memset((void *)&dv->sdev_instance_data, 0,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sizeof (dv->sdev_instance_data));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vn_invalid(SDEVTOV(dv));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_cache_free(sdev_node_cache, dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * DIRECTORY CACHE lookup
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistruct sdev_node *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_findbyname(struct sdev_node *ddv, char *nm)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg struct sdev_node dvtmp;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg avl_index_t where;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_LOCK_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg dvtmp.sdev_name = nm;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg dv = avl_find(&ddv->sdev_entries, &dvtmp, &where);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg if (dv) {
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg ASSERT(dv->sdev_dotdot == ddv);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg ASSERT(strcmp(dv->sdev_name, nm) == 0);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi ASSERT(dv->sdev_state != SDEV_ZOMBIE);
ecb4d93a50f2e89903a83c86c7a8c7f8740e512bjg SDEV_HOLD(dv);
ecb4d93a50f2e89903a83c86c7a8c7f8740e512bjg return (dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Inserts a new sdev_node in a parent directory
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_direnter(struct sdev_node *ddv, struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg avl_index_t where;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(SDEVTOV(ddv)->v_type == VDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(ddv->sdev_nlink >= 2);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_nlink == 0);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi ASSERT(dv->sdev_state != SDEV_ZOMBIE);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_dotdot = ddv;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg VERIFY(avl_find(&ddv->sdev_entries, dv, &where) == NULL);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg avl_insert(&ddv->sdev_entries, dv, where);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_nlink++;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidecr_link(struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi VERIFY(RW_WRITE_HELD(&dv->sdev_contents));
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (dv->sdev_state != SDEV_INIT) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi VERIFY(dv->sdev_nlink >= 1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_nlink--;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi } else {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi VERIFY(dv->sdev_nlink == 0);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Delete an existing dv from directory cache
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
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".
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_dirdelete(struct sdev_node *ddv, struct sdev_node *dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_node_state_t os;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&vp->v_lock);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi rw_enter(&dv->sdev_contents, RW_WRITER);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi os = dv->sdev_state;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi ASSERT(os != SDEV_ZOMBIE);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi dv->sdev_state = SDEV_ZOMBIE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /*
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 */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi decr_link(ddv);
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg avl_remove(&ddv->sdev_entries, dv);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /*
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 */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (os == SDEV_INIT && dv->sdev_nlink == 0)
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi dv->sdev_nlink++;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi rw_exit(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&vp->v_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * check if the source is in the path of the target
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * source and target are different
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*ARGSUSED2*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_checkpath(struct sdev_node *sdv, struct sdev_node *tdv, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dotdot, *dir;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dotdot = tdv->sdev_dotdot;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dotdot);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* fs root */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dotdot == tdv) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (;;) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * avoid error cases like
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * mv a a/b
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * mv a a/b/c
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * etc.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dotdot == sdv) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = EINVAL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dir = dotdot;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dotdot = dir->sdev_dotdot;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* done checking because root is reached */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dir == dotdot) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_rnmnode(struct sdev_node *oddv, struct sdev_node *odv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *nddv, struct sdev_node **ndvp, char *nnm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *ovp = SDEVTOV(odv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *nvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr vattr;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int doingdir = (ovp->v_type == VDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *link = NULL;
0bfaec6936a60046cf3a098fa731cb5e07377595llai int samedir = (oddv == nddv) ? 1 : 0;
0bfaec6936a60046cf3a098fa731cb5e07377595llai int bkstore = 0;
0bfaec6936a60046cf3a098fa731cb5e07377595llai struct sdev_node *idv = NULL;
0bfaec6936a60046cf3a098fa731cb5e07377595llai struct sdev_node *ndv = NULL;
0bfaec6936a60046cf3a098fa731cb5e07377595llai timestruc_t now;
0bfaec6936a60046cf3a098fa731cb5e07377595llai
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_GETATTR(ovp, &vattr, 0, cred, NULL);
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (error)
0bfaec6936a60046cf3a098fa731cb5e07377595llai return (error);
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (!samedir)
0bfaec6936a60046cf3a098fa731cb5e07377595llai rw_enter(&oddv->sdev_contents, RW_WRITER);
0bfaec6936a60046cf3a098fa731cb5e07377595llai rw_enter(&nddv->sdev_contents, RW_WRITER);
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai /*
0bfaec6936a60046cf3a098fa731cb5e07377595llai * the source may have been deleted by another thread before
0bfaec6936a60046cf3a098fa731cb5e07377595llai * we gets here.
0bfaec6936a60046cf3a098fa731cb5e07377595llai */
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (odv->sdev_state != SDEV_READY) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = ENOENT;
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (doingdir && (odv == nddv)) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = EINVAL;
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (doingdir && (oddv != nddv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_checkpath(odv, nddv, cred);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error)
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /* fix the source for a symlink */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (vattr.va_type == VLNK) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (odv->sdev_symlink == NULL) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi error = sdev_follow_link(odv);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (error) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /*
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 */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (SDEV_IS_PERSIST((*ndvp)))
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi bkstore = 1;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_dirdelete(oddv, odv);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (bkstore) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi ASSERT(nddv->sdev_attrvp);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi error = VOP_REMOVE(nddv->sdev_attrvp,
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi nnm, cred, NULL, 0);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (error)
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi goto err_out;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi error = ENOENT;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi goto err_out;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi ASSERT(odv->sdev_symlink);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi link = i_ddi_strdup(odv->sdev_symlink, KM_SLEEP);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
0bfaec6936a60046cf3a098fa731cb5e07377595llai /* destination existing */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (*ndvp) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nvp = SDEVTOV(*ndvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(nvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* handling renaming to itself */
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (odv == *ndvp) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = 0;
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (nvp->v_type == VDIR) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (!doingdir) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = EISDIR;
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (vn_vfswlock(nvp)) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = EBUSY;
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (vn_mountedvfs(nvp) != NULL) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai vn_vfsunlock(nvp);
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = EBUSY;
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai /* in case dir1 exists in dir2 and "mv dir1 dir2" */
0bfaec6936a60046cf3a098fa731cb5e07377595llai if ((*ndvp)->sdev_nlink > 2) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai vn_vfsunlock(nvp);
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = EEXIST;
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai vn_vfsunlock(nvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /*
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 * reference.
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_dirdelete(nddv, *ndvp);
0bfaec6936a60046cf3a098fa731cb5e07377595llai *ndvp = NULL;
b7beec954f20585da1efb36c9c4b96bba6429210jg ASSERT(nddv->sdev_attrvp);
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = VOP_RMDIR(nddv->sdev_attrvp, nnm,
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth nddv->sdev_attrvp, cred, NULL, 0);
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (error)
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai } else {
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (doingdir) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = ENOTDIR;
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (SDEV_IS_PERSIST((*ndvp))) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai bkstore = 1;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_dirdelete(nddv, *ndvp);
0bfaec6936a60046cf3a098fa731cb5e07377595llai *ndvp = NULL;
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (bkstore) {
b7beec954f20585da1efb36c9c4b96bba6429210jg ASSERT(nddv->sdev_attrvp);
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = VOP_REMOVE(nddv->sdev_attrvp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nnm, cred, NULL, 0);
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (error)
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth goto err_out;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
0bfaec6936a60046cf3a098fa731cb5e07377595llai /*
0bfaec6936a60046cf3a098fa731cb5e07377595llai * make a fresh node from the source attrs
0bfaec6936a60046cf3a098fa731cb5e07377595llai */
0bfaec6936a60046cf3a098fa731cb5e07377595llai ASSERT(RW_WRITE_HELD(&nddv->sdev_contents));
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = sdev_mknode(nddv, nnm, ndvp, &vattr,
0bfaec6936a60046cf3a098fa731cb5e07377595llai NULL, (void *)link, cred, SDEV_READY);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (link != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(link, strlen(link) + 1);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi link = NULL;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (error)
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai ASSERT(*ndvp);
0bfaec6936a60046cf3a098fa731cb5e07377595llai ASSERT((*ndvp)->sdev_state == SDEV_READY);
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai /* move dir contents */
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (doingdir) {
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg for (idv = SDEV_FIRST_ENTRY(odv); idv;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg idv = SDEV_NEXT_ENTRY(odv, idv)) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_HOLD(idv);
0bfaec6936a60046cf3a098fa731cb5e07377595llai error = sdev_rnmnode(odv, idv,
0bfaec6936a60046cf3a098fa731cb5e07377595llai (struct sdev_node *)(*ndvp), &ndv,
0bfaec6936a60046cf3a098fa731cb5e07377595llai idv->sdev_name, cred);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_RELE(idv);
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (error)
0bfaec6936a60046cf3a098fa731cb5e07377595llai goto err_out;
0bfaec6936a60046cf3a098fa731cb5e07377595llai ndv = NULL;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if ((*ndvp)->sdev_attrvp) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai sdev_update_timestamps((*ndvp)->sdev_attrvp, kcred,
0bfaec6936a60046cf3a098fa731cb5e07377595llai AT_CTIME|AT_ATIME);
0bfaec6936a60046cf3a098fa731cb5e07377595llai } else {
0bfaec6936a60046cf3a098fa731cb5e07377595llai ASSERT((*ndvp)->sdev_attr);
0bfaec6936a60046cf3a098fa731cb5e07377595llai gethrestime(&now);
0bfaec6936a60046cf3a098fa731cb5e07377595llai (*ndvp)->sdev_attr->va_ctime = now;
0bfaec6936a60046cf3a098fa731cb5e07377595llai (*ndvp)->sdev_attr->va_atime = now;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (nddv->sdev_attrvp) {
0bfaec6936a60046cf3a098fa731cb5e07377595llai sdev_update_timestamps(nddv->sdev_attrvp, kcred,
0bfaec6936a60046cf3a098fa731cb5e07377595llai AT_MTIME|AT_ATIME);
0bfaec6936a60046cf3a098fa731cb5e07377595llai } else {
0bfaec6936a60046cf3a098fa731cb5e07377595llai ASSERT(nddv->sdev_attr);
0bfaec6936a60046cf3a098fa731cb5e07377595llai gethrestime(&now);
0bfaec6936a60046cf3a098fa731cb5e07377595llai nddv->sdev_attr->va_mtime = now;
0bfaec6936a60046cf3a098fa731cb5e07377595llai nddv->sdev_attr->va_atime = now;
0bfaec6936a60046cf3a098fa731cb5e07377595llai }
0bfaec6936a60046cf3a098fa731cb5e07377595llai rw_exit(&nddv->sdev_contents);
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (!samedir)
0bfaec6936a60046cf3a098fa731cb5e07377595llai rw_exit(&oddv->sdev_contents);
0bfaec6936a60046cf3a098fa731cb5e07377595llai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(*ndvp);
0bfaec6936a60046cf3a098fa731cb5e07377595llai return (error);
0bfaec6936a60046cf3a098fa731cb5e07377595llai
0bfaec6936a60046cf3a098fa731cb5e07377595llaierr_out:
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (link != NULL) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi kmem_free(link, strlen(link) + 1);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi link = NULL;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
0bfaec6936a60046cf3a098fa731cb5e07377595llai rw_exit(&nddv->sdev_contents);
0bfaec6936a60046cf3a098fa731cb5e07377595llai if (!samedir)
0bfaec6936a60046cf3a098fa731cb5e07377595llai rw_exit(&oddv->sdev_contents);
0bfaec6936a60046cf3a098fa731cb5e07377595llai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Merge sdev_node specific information into an attribute structure.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * note: sdev_node is not locked here
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_vattr_merge(struct sdev_node *dv, struct vattr *vap)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_nlink = dv->sdev_nlink;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_nodeid = dv->sdev_ino;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_fsid = SDEVTOV(dv->sdev_dotdot)->v_rdev;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_type = vp->v_type;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vp->v_type == VDIR) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_rdev = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_fsid = vp->v_rdev;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (vp->v_type == VLNK) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_rdev = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_mode &= ~S_IFMT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_mode |= S_IFLNK;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if ((vp->v_type == VCHR) || (vp->v_type == VBLK)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_rdev = vp->v_rdev;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_mode &= ~S_IFMT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vap->va_type == VCHR)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_mode |= S_IFCHR;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai else
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_mode |= S_IFBLK;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_rdev = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylorstruct vattr *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_getdefault_attr(enum vtype type)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (type == VDIR)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (&sdev_vattr_dir);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai else if (type == VCHR)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (&sdev_vattr_chr);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai else if (type == VBLK)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (&sdev_vattr_blk);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai else if (type == VLNK)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (&sdev_vattr_lnk);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai else
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_to_vp(struct sdev_node *dv, struct vnode **vpp)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int rv = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (vp->v_type) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case VCHR:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case VBLK:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * If vnode is a device, return special vnode instead
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * (though it knows all about -us- via sp->s_realvp)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = specvp(vp, vp->v_rdev, vp->v_type, kcred);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (*vpp == NULLVP)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rv = ENOSYS;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai default: /* most types are returned as is */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (rv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * junction between devname and root file system, e.g. ufs
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidevname_backstore_lookup(struct sdev_node *ddv, char *nm, struct vnode **rvp)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *rdvp = ddv->sdev_attrvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int rval = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(rdvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rval = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, kcred, NULL, NULL,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (rval);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_filldir_from_store(struct sdev_node *ddv, int dlen, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *nm;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *dirvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vnode_t *vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int eof;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct iovec iov;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct uio uio;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct dirent64 *dp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dirent64_t *dbuf;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai size_t dbuflen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr vattr;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *link = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ddv->sdev_attrvp == NULL)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!(ddv->sdev_flags & SDEV_BUILD))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dirvp = ddv->sdev_attrvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_HOLD(dirvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dbuf = kmem_zalloc(dlen, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_iov = &iov;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_iovcnt = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_segflg = UIO_SYSSPACE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_fmode = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_extflg = UIO_COPY_CACHED;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_loffset = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_llimit = MAXOFFSET_T;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai eof = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai while (!error && !eof) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_resid = dlen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai iov.iov_base = (char *)dbuf;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai iov.iov_len = dlen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) VOP_RWLOCK(dirvp, V_WRITELOCK_FALSE, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_READDIR(dirvp, &uio, kcred, &eof, NULL, 0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VOP_RWUNLOCK(dirvp, V_WRITELOCK_FALSE, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dbuflen = dlen - uio.uio_resid;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error || dbuflen == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (!(ddv->sdev_flags & SDEV_BUILD))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (dp = dbuf; ((intptr_t)dp <
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (intptr_t)dbuf + dbuflen);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nm = dp->d_name;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (strcmp(nm, ".") == 0 ||
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai strcmp(nm, "..") == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = NULLVP;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv = sdev_cache_lookup(ddv, nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi VERIFY(dv->sdev_state != SDEV_ZOMBIE);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_SIMPLE_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* refill the cache if not already */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = devname_backstore_lookup(ddv, nm, &vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_GETATTR(vp, &vattr, 0, cred, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vattr.va_type == VLNK) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_getlink(vp, &link);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(link != NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!rw_tryupgrade(&ddv->sdev_contents)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_mknode(ddv, nm, &dv, &vattr, vp, link,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cred, SDEV_READY);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_downgrade(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (link != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(link, strlen(link) + 1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai link = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_state != SDEV_ZOMBIE);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_SIMPLE_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidone:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(dirvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(dbuf, dlen);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
6b9384783302cfb5bb67d617114d5a4e1dc3d609jgvoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_filldir_dynamic(struct sdev_node *ddv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int i;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam struct vattr vattr;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam struct vattr *vap = &vattr;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *nm = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg ASSERT((ddv->sdev_flags & SDEV_BUILD));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam *vap = *sdev_getdefault_attr(VDIR); /* note structure copy here */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor gethrestime(&vap->va_atime);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor vap->va_mtime = vap->va_atime;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor vap->va_ctime = vap->va_atime;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (i = 0; vtab[i].vt_name != NULL; i++) {
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon /*
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.
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if ((vtab[i].vt_flags & SDEV_PERSIST) ||
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi !(vtab[i].vt_flags & SDEV_DYNAMIC))
67323fc4f7476c5e8b55a5fe505c6f2dbf00e89aJohn Levon continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nm = vtab[i].vt_name;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_mknode(ddv, nm, &dv, vap, NULL,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai NULL, kcred, SDEV_READY);
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg if (error) {
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg cmn_err(CE_WARN, "%s/%s: error %d\n",
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg ddv->sdev_name, nm, error);
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg } else {
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg ASSERT(dv);
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg ASSERT(dv->sdev_state != SDEV_ZOMBIE);
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg SDEV_SIMPLE_RELE(dv);
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_shadow_node(struct sdev_node *dv, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *dvp = SDEVTOV(dv->sdev_dotdot);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *rdvp = VTOSDEV(dvp)->sdev_attrvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr *vap = dv->sdev_attr;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *nm = dv->sdev_name;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *tmpvp, **rvp = &tmpvp, *rrvp = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv && dv->sdev_name && rdvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&dv->sdev_contents) && dv->sdev_attrvp == NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllailookup:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* try to find it in the backing store */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_LOOKUP(rdvp, nm, rvp, NULL, 0, NULL, cred, NULL, NULL,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (VOP_REALVP(*rvp, &rrvp, NULL) == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_HOLD(rrvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(*rvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *rvp = rrvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(dv->sdev_attr, sizeof (vattr_t));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attr = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_attrvp = *rvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* let's try to persist the node */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai gethrestime(&vap->va_atime);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_mtime = vap->va_atime;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_ctime = vap->va_atime;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vap->va_mask |= AT_TYPE|AT_MODE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (vap->va_type) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case VDIR:
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 (void *)(*rvp), error));
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (!error)
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi VN_RELE(*rvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case VCHR:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case VBLK:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case VREG:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case VDOOR:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = VOP_CREATE(rdvp, nm, vap, NONEXCL, VREAD|VWRITE,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw rvp, cred, 0, NULL, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_shadow_node: create vp %p, error %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void *)(*rvp), error));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!error)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(*rvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case VLNK:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_symlink);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_SYMLINK(rdvp, nm, vap, dv->sdev_symlink, cred,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL, 0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_shadow_node: create symlink error %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai default:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_PANIC, "dev: %s: sdev_shadow_node "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "create\n", nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*NOTREACHED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* go back to lookup to factor out spec node and set attrvp */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto lookup;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
b7beec954f20585da1efb36c9c4b96bba6429210jg sdcmn_err(("cannot persist %s - error %d\n", dv->sdev_path, error));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cache_add(struct sdev_node *ddv, struct sdev_node **dv, char *nm)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dup = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((dup = sdev_findbyname(ddv, nm)) == NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_direnter(ddv, *dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi VERIFY(dup->sdev_state != SDEV_ZOMBIE);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_SIMPLE_RELE(*dv);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_nodedestroy(*dv, 0);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi *dv = dup;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cache_delete(struct sdev_node *ddv, struct sdev_node **dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_dirdelete(ddv, *dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * update the in-core directory cache
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cache_update(struct sdev_node *ddv, struct sdev_node **dv, char *nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_cache_ops_t ops)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT((SDEV_HELD(*dv)));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (ops) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_CACHE_ADD:
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_cache_add(ddv, dv, nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_CACHE_DELETE:
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_cache_delete(ddv, dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai default:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * retrieve the named entry from the directory cache
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistruct sdev_node *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cache_lookup(struct sdev_node *ddv, char *nm)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_LOCK_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv = sdev_findbyname(ddv, nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_call_devfsadmd(struct sdev_node *ddv, struct sdev_node *dv, char *nm)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err6(("lookup: waiting for %s/%s, 0x%x\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_name, nm, devfsadm_state));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&dv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_BLOCK_OTHERS(dv, (SDEV_LOOKUP | SDEV_LGWAITING));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&dv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (!DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err6(("lookup %s/%s starting devfsadm, 0x%x\n",
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth ddv->sdev_name, nm, devfsadm_state));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_devfsadmd_thread(ddv, dv, kcred);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&dv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_BLOCK_OTHERS(dv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (SDEV_LOOKUP | SDEV_LGWAITING));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&dv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = -1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Support for specialized device naming construction mechanisms
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_call_dircallback(struct sdev_node *ddv, struct sdev_node **dvp, char *nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int (*callback)(struct sdev_node *, char *, void **, struct cred *,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai void *, char *), int flags, struct cred *cred)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int rv = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *physpath = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr vattr;
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam struct vattr *vap = &vattr;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor struct sdev_node *dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (flags & SDEV_VLINK) {
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 NULL);
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China if (rv) {
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China kmem_free(physpath, MAXPATHLEN);
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China return (-1);
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China }
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam *vap = *sdev_getdefault_attr(VLNK); /* structure copy */
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China vap->va_size = strlen(physpath);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor gethrestime(&vap->va_atime);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor vap->va_mtime = vap->va_atime;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor vap->va_ctime = vap->va_atime;
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China
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);
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China if (rv)
aecfc01d1bad84e66649703f7fc2926ef70b34barui zang - Sun Microsystems - Beijing China return (rv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (flags & SDEV_VATTR) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * /dev/pts
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * callback is responsible to set the basic attributes,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * e.g. va_type/va_uid/va_gid/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * dev_t if VCHR or VBLK/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(callback);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rv = callback(ddv, nm, (void *)&vattr, kcred, NULL, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (rv) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err3(("devname_lookup_func: SDEV_NONE "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "callback failed \n"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (-1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rv = sdev_mknode(ddv, nm, &dv, &vattr, NULL, NULL,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cred, SDEV_READY);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (rv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (rv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai impossible(("lookup: %s/%s by %s not supported (%d)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEVTOV(ddv)->v_path, nm, curproc->p_user.u_comm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai __LINE__));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rv = -1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *dvp = dv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (rv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiis_devfsadm_thread(char *exec_name)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
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 */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (strcmp(exec_name, "devfsadm") == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidevname_lookup_func(struct sdev_node *ddv, char *nm, struct vnode **vpp,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct cred *cred, int (*callback)(struct sdev_node *, char *, void **,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct cred *, void *, char *), int flags)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int rv = 0, nmlen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *rvp = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int retried = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr vattr;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *lookup_thread = curproc->p_user.u_comm;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int failed_flags = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int (*vtor)(struct sdev_node *) = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int parent_state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *link = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEVTOV(ddv)->v_type != VDIR)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOTDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Empty name or ., return node itself.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nmlen = strlen(nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((nmlen == 0) || ((nmlen == 1) && (nm[0] == '.'))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = SDEVTOV(ddv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_HOLD(*vpp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * .., return the parent directory
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((nmlen == 2) && (strcmp(nm, "..") == 0)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = SDEVTOV(ddv->sdev_dotdot);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_HOLD(*vpp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_READER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ddv->sdev_flags & SDEV_VTOR) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(vtor);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaitryagain:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * (a) directory cache lookup:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_READ_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai parent_state = ddv->sdev_state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv = sdev_cache_lookup(ddv, nm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai state = dv->sdev_state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (state) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_INIT:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (is_devfsadm_thread(lookup_thread))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* ZOMBIED parent won't allow node creation */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (parent_state == SDEV_ZOMBIE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto nolock_notfound;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&dv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* compensate the threads started after devfsadm */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai !(SDEV_IS_LOOKUP(dv)))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_BLOCK_OTHERS(dv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (SDEV_LOOKUP | SDEV_LGWAITING));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_LOOKUP(dv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai failed_flags |= SLF_REBUILT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_wait4lookup(dv, SDEV_LOOKUP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&dv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_READER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error != 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto nolock_notfound;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai state = dv->sdev_state;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (state == SDEV_INIT) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto nolock_notfound;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (state == SDEV_READY) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto found;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (state == SDEV_ZOMBIE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto lookup_failed;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&dv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_READY:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto found;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_ZOMBIE:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto lookup_failed;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai default:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_lookup_failed(ddv, nm, failed_flags);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = NULLVP;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_READ_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * ZOMBIED parent does not allow new node creation.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * bail out early
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (parent_state == SDEV_ZOMBIE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor *vpp = NULLVP;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
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
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_PERSIST(ddv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = devname_backstore_lookup(ddv, nm, &rvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
bb5fffbea58a3c7c5826a58c13c21e6c87558e52Jerry Gilliam vattr.va_mask = AT_TYPE|AT_MODE|AT_UID|AT_GID;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_GETATTR(rvp, &vattr, 0, cred, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_lookup_failed(ddv, nm, failed_flags);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = NULLVP;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vattr.va_type == VLNK) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_getlink(rvp, &link);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_lookup_failed(ddv, nm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai failed_flags);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = NULLVP;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(link != NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!rw_tryupgrade(&ddv->sdev_contents)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_mknode(ddv, nm, &dv, &vattr,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rvp, link, cred, SDEV_READY);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_downgrade(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (link != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(link, strlen(link) + 1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai link = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto lookup_failed;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto found;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (retried) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err3(("retry of lookup of %s/%s: failed\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_name, nm));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_lookup_failed(ddv, nm, failed_flags);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = NULLVP;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirklookup_create_node:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* first thread that is doing the lookup on this node */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (callback) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor ASSERT(dv == NULL);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (!rw_tryupgrade(&ddv->sdev_contents)) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor rw_exit(&ddv->sdev_contents);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor rw_enter(&ddv->sdev_contents, RW_WRITER);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor }
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor error = sdev_call_dircallback(ddv, &dv, nm, callback,
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor flags, cred);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor rw_downgrade(&ddv->sdev_contents);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (error == 0) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor goto found;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor } else {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor rw_exit(&ddv->sdev_contents);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor goto lookup_failed;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor }
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!dv) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!rw_tryupgrade(&ddv->sdev_contents)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_mknode(ddv, nm, &dv, NULL, NULL, NULL,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cred, SDEV_INIT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!dv) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_lookup_failed(ddv, nm, failed_flags);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = NULLVP;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_downgrade(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor /*
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor * (b1) invoking devfsadm once per life time for devfsadm nodes
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(SDEV_HELD(dv));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (SDEV_IS_NO_NCACHE(dv))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai failed_flags |= SLF_NO_NCACHE;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (sdev_reconfig_boot || !i_ddi_io_initialized() ||
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SDEV_IS_DYNAMIC(ddv) || SDEV_IS_NO_NCACHE(dv) ||
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor ((moddebug & MODDEBUG_FINI_EBUSY) != 0)) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor ASSERT(SDEV_HELD(dv));
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor goto nolock_notfound;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (sdev_lookup_filter(ddv, nm)) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor goto nolock_notfound;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor /* bypassing devfsadm internal nodes */
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (is_devfsadm_thread(lookup_thread)) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor goto nolock_notfound;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (sdev_reconfig_disable) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor goto nolock_notfound;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor error = sdev_call_devfsadmd(ddv, dv, nm);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (error == 0) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor sdcmn_err8(("lookup of %s/%s by %s: reconfig\n",
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor ddv->sdev_name, nm, curproc->p_user.u_comm));
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor if (sdev_reconfig_verbose) {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor cmn_err(CE_CONT,
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor "?lookup of %s/%s by %s: reconfig\n",
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor ddv->sdev_name, nm, curproc->p_user.u_comm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor retried = 1;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor failed_flags |= SLF_REBUILT;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor ASSERT(dv->sdev_state != SDEV_ZOMBIE);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SDEV_SIMPLE_RELE(dv);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor goto tryagain;
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor } else {
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor goto nolock_notfound;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaifound:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_state == SDEV_READY);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vtor) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Check validity of returned node
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (vtor(dv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_VTOR_VALID:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk case SDEV_VTOR_STALE:
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /*
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * The name exists, but the cache entry is
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk * stale and needs to be re-created.
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk */
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk ASSERT(RW_READ_HELD(&ddv->sdev_contents));
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk if (rw_tryupgrade(&ddv->sdev_contents) == 0) {
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk rw_exit(&ddv->sdev_contents);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk rw_enter(&ddv->sdev_contents, RW_WRITER);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_cache_update(ddv, &dv, nm, SDEV_CACHE_DELETE);
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk rw_downgrade(&ddv->sdev_contents);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_RELE(dv);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi dv = NULL;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi goto lookup_create_node;
b127ac411761a3d8d642d9342d9cac2785e1faaaPhilip Kirk /* FALLTHRU */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_VTOR_INVALID:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err7(("lookup: destroy invalid "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "node: %s(%p)\n", dv->sdev_name, (void *)dv));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto nolock_notfound;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_VTOR_SKIP:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err7(("lookup: node not applicable - "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "skipping: %s(%p)\n", dv->sdev_name, (void *)dv));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SD_TRACE_FAILED_LOOKUP(ddv, nm, retried);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto lookup_failed;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai default:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_PANIC,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "dev fs: validator failed: %s(%p)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name, (void *)dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rv = sdev_to_vp(dv, vpp);
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 dv->sdev_state, nm, rv));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (rv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllainolock_notfound:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Destroy the node that is created for synchronization purposes.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err3(("devname_lookup_func: %s with state %d\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nm, dv->sdev_state));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_READ_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_state == SDEV_INIT) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!rw_tryupgrade(&ddv->sdev_contents)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Node state may have changed during the lock
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * changes. Re-check.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_state == SDEV_INIT) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_dirdelete(ddv, dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_lookup_failed(ddv, nm, failed_flags);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllailookup_failed:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_lookup_failed(ddv, nm, failed_flags);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *vpp = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_stale(struct sdev_node *ddv)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(SDEVTOV(ddv)->v_type == VDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_WRITER);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi while ((dv = SDEV_FIRST_ENTRY(ddv)) != NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = SDEVTOV(dv);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_HOLD(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vp->v_type == VDIR)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_stale(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_dirdelete(ddv, dv);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_flags |= SDEV_BUILD;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
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.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_cleandir(struct sdev_node *ddv, char *expr, uint_t flags)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int busy = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vnode *vp;
45b1747515a17db45e8971501ee84a26bdff37b2Alex Wilson struct sdev_node *dv, *next;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int bkstore = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int len = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *bks_name = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(SDEVTOV(ddv)->v_type == VDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * We try our best to destroy all unused sdev_node's
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_WRITER);
45b1747515a17db45e8971501ee84a26bdff37b2Alex Wilson for (dv = SDEV_FIRST_ENTRY(ddv); dv != NULL; dv = next) {
45b1747515a17db45e8971501ee84a26bdff37b2Alex Wilson next = SDEV_NEXT_ENTRY(ddv, dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = SDEVTOV(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (expr && gmatch(dv->sdev_name, expr) == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vp->v_type == VDIR &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_cleandir(dv, NULL, flags) != 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_cleandir: dir %s busy\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai busy++;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vp->v_count > 0 && (flags & SDEV_ENFORCE) == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_cleandir: dir %s busy\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai busy++;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * at this point, either dv is not held or SDEV_ENFORCE
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * is specified. In either case, dv needs to be deleted
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_HOLD(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bkstore = SDEV_IS_PERSIST(dv) ? 1 : 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (bkstore && (vp->v_type == VDIR))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bkstore += 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (bkstore) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai len = strlen(dv->sdev_name) + 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bks_name = kmem_alloc(len, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bcopy(dv->sdev_name, bks_name, len);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi sdev_dirdelete(ddv, dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* take care the backing store clean up */
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi if (bkstore) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(bks_name);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(ddv->sdev_attrvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (bkstore == 1) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = VOP_REMOVE(ddv->sdev_attrvp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bks_name, kcred, NULL, 0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (bkstore == 2) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = VOP_RMDIR(ddv->sdev_attrvp,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bks_name, ddv->sdev_attrvp, kcred, NULL, 0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* do not propagate the backing store errors */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err9(("sdev_cleandir: backing store"
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "not cleaned\n"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bkstore = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(bks_name, len);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bks_name = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai len = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi ddv->sdev_flags |= SDEV_BUILD;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi SDEV_RELE(dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_flags |= SDEV_BUILD;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (busy) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = EBUSY;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * a convenient wrapper for readdir() funcs
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisize_t
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiadd_dir_entry(dirent64_t *de, char *nm, size_t size, ino_t ino, offset_t off)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai size_t reclen = DIRENT64_RECLEN(strlen(nm));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (reclen > size)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai de->d_ino = (ino64_t)ino;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai de->d_off = (off64_t)off + 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai de->d_reclen = (ushort_t)reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) strncpy(de->d_name, nm, DIRENT64_NAMELEN(reclen));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (reclen);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_mount service routines
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_copyin_mountargs(struct mounta *uap, struct sdev_mountargs *args)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (uap->datalen != sizeof (*args))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (EINVAL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error = copyin(uap->dataptr, args, sizeof (*args))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_WARN, "sdev_copyin_mountargs: can not"
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "get user data. error %d\n", error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (EFAULT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#ifdef nextdp
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#undef nextdp
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai#endif
bc1009abdd0a493796645bd983c1601396c09a5fjg#define nextdp(dp) ((struct dirent64 *) \
bc1009abdd0a493796645bd983c1601396c09a5fjg (intptr_t)((char *)(dp) + (dp)->d_reclen))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * readdir helper func
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidevname_readdir_func(vnode_t *vp, uio_t *uiop, cred_t *cred, int *eofp,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int flags)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *ddv = VTOSDEV(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dirent64_t *dp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ulong_t outcount = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai size_t namelen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ulong_t alloc_count;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai void *outbuf;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct iovec *iovp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai size_t reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai offset_t diroff;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai offset_t soff;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int this_reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int (*vtor)(struct sdev_node *) = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr attr;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai timestruc_t now;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(ddv->sdev_attr || ddv->sdev_attrvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(RW_READ_HELD(&ddv->sdev_contents));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (uiop->uio_loffset >= MAXOFF_T) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (eofp)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *eofp = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (uiop->uio_iovcnt != 1)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (EINVAL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vp->v_type != VDIR)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOTDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ddv->sdev_flags & SDEV_VTOR) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(vtor);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (eofp != NULL)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *eofp = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
bc1009abdd0a493796645bd983c1601396c09a5fjg soff = uiop->uio_loffset;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai iovp = uiop->uio_iov;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai alloc_count = iovp->iov_len;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp = outbuf = kmem_alloc(alloc_count, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai outcount = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ddv->sdev_state == SDEV_ZOMBIE)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto get_cache;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
b774fca88bff9e11d96e3b40f4d259d278048a3aszhou if (SDEV_IS_GLOBAL(ddv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor if ((sdev_boot_state == SDEV_BOOT_STATE_COMPLETE) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai !sdev_reconfig_boot && (flags & SDEV_BROWSE) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai !SDEV_IS_DYNAMIC(ddv) && !SDEV_IS_NO_NCACHE(ddv) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ((moddebug & MODDEBUG_FINI_EBUSY) == 0) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai !DEVNAME_DEVFSADM_HAS_RUN(devfsadm_state) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai !DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state) &&
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai !sdev_reconfig_disable) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * invoking "devfsadm" to do system device reconfig
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ddv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_BLOCK_OTHERS(ddv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (SDEV_READDIR|SDEV_LGWAITING));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ddv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err8(("readdir of %s by %s: reconfig\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_path, curproc->p_user.u_comm));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (sdev_reconfig_verbose) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_CONT,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "?readdir of %s by %s: reconfig\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_path, curproc->p_user.u_comm);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_devfsadmd_thread(ddv, NULL, kcred);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai } else if (DEVNAME_DEVFSADM_IS_RUNNING(devfsadm_state)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * compensate the "ls" started later than "devfsadm"
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ddv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai SDEV_BLOCK_OTHERS(ddv, (SDEV_READDIR|SDEV_LGWAITING));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ddv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * release the contents lock so that
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg * the cache may be updated by devfsadmd
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&ddv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_enter(&ddv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_READDIR(ddv))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) sdev_wait4lookup(ddv, SDEV_READDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai mutex_exit(&ddv->sdev_lookup_lock);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&ddv->sdev_contents, RW_READER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err4(("readdir of directory %s by %s\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ddv->sdev_name, curproc->p_user.u_comm));
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg if (ddv->sdev_flags & SDEV_BUILD) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_PERSIST(ddv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_filldir_from_store(ddv,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai alloc_count, cred);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
6b9384783302cfb5bb67d617114d5a4e1dc3d609jg ddv->sdev_flags &= ~SDEV_BUILD;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiget_cache:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* handle "." and ".." */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai diroff = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (soff == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* first time */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai this_reclen = DIRENT64_RECLEN(1);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (alloc_count < this_reclen) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = EINVAL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto done;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_ino = (ino64_t)ddv->sdev_ino;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_off = (off64_t)1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_reclen = (ushort_t)this_reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) strncpy(dp->d_name, ".",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai DIRENT64_NAMELEN(this_reclen));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai outcount += dp->d_reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp = nextdp(dp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai diroff++;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (soff <= 1) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai this_reclen = DIRENT64_RECLEN(2);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (alloc_count < outcount + this_reclen) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = EINVAL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto done;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_reclen = (ushort_t)this_reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_ino = (ino64_t)ddv->sdev_dotdot->sdev_ino;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_off = (off64_t)2;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) strncpy(dp->d_name, "..",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai DIRENT64_NAMELEN(this_reclen));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai outcount += dp->d_reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp = nextdp(dp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* gets the cache */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai diroff++;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg for (dv = SDEV_FIRST_ENTRY(ddv); dv;
aac43a5f8f51bcc570ff0ae9fad0380daf839ad9jg dv = SDEV_NEXT_ENTRY(ddv, dv), diroff++) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err3(("sdev_readdir: diroff %lld soff %lld for '%s' \n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai diroff, soff, dv->sdev_name));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* bypassing pre-matured nodes */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (diroff < soff || (dv->sdev_state != SDEV_READY)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err3(("sdev_readdir: pre-mature node "
681d9761e8516a7dc5ab6589e2dfe717777e1123Eric Taylor "%s %d\n", dv->sdev_name, dv->sdev_state));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
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 */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vtor) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai switch (vtor(dv)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_VTOR_VALID:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_VTOR_INVALID:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai case SDEV_VTOR_SKIP:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam case SDEV_VTOR_STALE:
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam sdcmn_err3(("sdev_readir: %s stale\n",
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam dv->sdev_name));
2b080a343365d348d0bc9c6b0904cbe4e0526818Jerry Gilliam break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai default:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_PANIC,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "dev fs: validator failed: %s(%p)\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dv->sdev_name, (void *)dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*NOTREACHED*/
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai namelen = strlen(dv->sdev_name);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai reclen = DIRENT64_RECLEN(namelen);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (outcount + reclen > alloc_count) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai goto full;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_reclen = (ushort_t)reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_ino = (ino64_t)dv->sdev_ino;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp->d_off = (off64_t)diroff + 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) strncpy(dp->d_name, dv->sdev_name,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai DIRENT64_NAMELEN(reclen));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai outcount += reclen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dp = nextdp(dp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaifull:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err4(("sdev_readdir: moving %lu bytes: "
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai "diroff %lld, soff %lld, dv %p\n", outcount, diroff, soff,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void *)dv));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (outcount)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = uiomove(outbuf, outcount, UIO_READ, uiop);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!error) {
bc1009abdd0a493796645bd983c1601396c09a5fjg uiop->uio_loffset = diroff;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (eofp)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *eofp = dv ? 0 : 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (ddv->sdev_attrvp) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai gethrestime(&now);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai attr.va_ctime = now;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai attr.va_atime = now;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai attr.va_mask = AT_CTIME|AT_ATIME;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) VOP_SETATTR(ddv->sdev_attrvp, &attr, 0, kcred, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidone:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(outbuf, alloc_count);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic int
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_modctl_lookup(const char *path, vnode_t **r_vp)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vnode_t *vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vnode_t *cvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *svp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *nm;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct pathname pn;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int persisted = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam ASSERT(INGLOBALZONE(curproc));
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error = pn_get((char *)path, UIO_SYSSPACE, &pn))
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nm = kmem_alloc(MAXNAMELEN, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = rootdir;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_HOLD(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai while (pn_pathleft(&pn)) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam ASSERT(vp->v_type == VDIR || vp->v_type == VLNK);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) pn_getcomponent(&pn, nm);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam /*
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 */
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (nm[0] == '.' && nm[1] == '.' && nm[2] == 0) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliamcheckforroot:
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (VN_CMP(vp, rootdir)) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam nm[1] = 0;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam } else if (vp->v_flag & VROOT) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam vfs_t *vfsp;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam cvp = vp;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam vfsp = cvp->v_vfsp;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam vfs_rlock_wait(vfsp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam vp = cvp->v_vfsp->vfs_vnodecovered;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (vp == NULL ||
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam vfs_unlock(vfsp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(cvp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam error = EIO;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam break;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam }
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_HOLD(vp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam vfs_unlock(vfsp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(cvp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam cvp = NULL;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam goto checkforroot;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam }
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam }
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_LOOKUP(vp, nm, &cvp, NULL, 0, NULL, kcred, NULL,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw NULL, NULL);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (error) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* traverse mount points encountered on our journey */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vn_ismntpt(cvp) && (error = traverse(&cvp)) != 0) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(cvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam /*
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam * symbolic link, can be either relative and absolute
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam */
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if ((cvp->v_type == VLNK) && pn_pathleft(&pn)) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam struct pathname linkpath;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam pn_alloc(&linkpath);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (error = pn_getsymlink(cvp, &linkpath, kcred)) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam pn_free(&linkpath);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam break;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam }
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (pn_pathleft(&linkpath) == 0)
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam (void) pn_set(&linkpath, ".");
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam error = pn_insert(&pn, &linkpath, strlen(nm));
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam pn_free(&linkpath);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (pn.pn_pathlen == 0) {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(vp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam return (ENOENT);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam }
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam if (pn.pn_path[0] == '/') {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam pn_skipslash(&pn);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(vp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(cvp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam vp = rootdir;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_HOLD(vp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam } else {
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(cvp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam }
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam continue;
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam }
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam VN_RELE(vp);
74bb9a80871576998889a2cdbffe159e60b4167fJerry Gilliam
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Direct the operation to the persisting filesystem
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * underlying /dev. Bail if we encounter a
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * non-persistent dev entity here.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (cvp->v_vfsp->vfs_fstype == devtype) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((VTOSDEV(cvp)->sdev_flags & SDEV_PERSIST) == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = ENOENT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(cvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (VTOSDEV(cvp) == NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = ENOENT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(cvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai svp = VTOSDEV(cvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((vp = svp->sdev_attrvp) == NULL) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = ENOENT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(cvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai persisted = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_HOLD(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(cvp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cvp = vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vp = cvp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai pn_skipslash(&pn);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(nm, MAXNAMELEN);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai pn_free(&pn);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Only return persisted nodes in the filesystem underlying /dev.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (!persisted) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (ENOENT);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *r_vp = vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_modctl_readdir(const char *dir, char ***dirlistp,
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth int *npathsp, int *npathsp_alloc, int checking_empty)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char **pathlist = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char **newlist = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int npaths = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int npaths_alloc = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dirent64_t *dbuf = NULL;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int n;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *s;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vnode_t *vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int eof;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct iovec iov;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct uio uio;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct dirent64 *dp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai size_t dlen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai size_t dbuflen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int ndirents = 64;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai char *nm;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_modctl_lookup(dir, &vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err11(("modctl readdir: %s by %s: %s\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dir, curproc->p_user.u_comm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (error == 0) ? "ok" : "failed"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dlen = ndirents * (sizeof (*dbuf));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dbuf = kmem_alloc(dlen, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_iov = &iov;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_iovcnt = 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_segflg = UIO_SYSSPACE;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_fmode = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_extflg = UIO_COPY_CACHED;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_loffset = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_llimit = MAXOFFSET_T;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai eof = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = 0;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai while (!error && !eof) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uio.uio_resid = dlen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai iov.iov_base = (char *)dbuf;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai iov.iov_len = dlen;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (void) VOP_RWLOCK(vp, V_WRITELOCK_FALSE, NULL);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = VOP_READDIR(vp, &uio, kcred, &eof, NULL, 0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VOP_RWUNLOCK(vp, V_WRITELOCK_FALSE, NULL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai dbuflen = dlen - uio.uio_resid;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error || dbuflen == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (dp = dbuf; ((intptr_t)dp < (intptr_t)dbuf + dbuflen);
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth dp = (dirent64_t *)((intptr_t)dp + dp->d_reclen)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai nm = dp->d_name;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (strcmp(nm, ".") == 0 || strcmp(nm, "..") == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai continue;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (npaths == npaths_alloc) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai npaths_alloc += 64;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai newlist = (char **)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_zalloc((npaths_alloc + 1) *
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth sizeof (char *), KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (pathlist) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bcopy(pathlist, newlist,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai npaths * sizeof (char *));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(pathlist,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (npaths + 1) * sizeof (char *));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai pathlist = newlist;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai n = strlen(nm) + 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai s = kmem_alloc(n, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bcopy(nm, s, n);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai pathlist[npaths++] = s;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err11((" %s/%s\n", dir, s));
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth /* if checking empty, one entry is as good as many */
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth if (checking_empty) {
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth eof = 1;
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth break;
e37c6c376a1a22a828db3bb5ab40c86cb08f9c86cth }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiexit:
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dbuf)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(dbuf, dlen);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *dirlistp = pathlist;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *npathsp = npaths;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *npathsp_alloc = npaths_alloc;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaivoid
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_modctl_readdir_free(char **pathlist, int npaths, int npaths_alloc)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int i, n;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (i = 0; i < npaths; i++) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai n = strlen(pathlist[i]) + 1;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(pathlist[i], n);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(pathlist, (npaths_alloc + 1) * sizeof (char *));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_modctl_devexists(const char *path)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai vnode_t *vp;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_modctl_lookup(path, &vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdcmn_err11(("modctl dev exists: %s by %s: %s\n",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai path, curproc->p_user.u_comm,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai (error == 0) ? "ok" : "failed"));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error == 0)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai VN_RELE(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiextern int sdev_vnodeops_tbl_size;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * construct a new template with overrides from vtab
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic fs_operation_def_t *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_merge_vtab(const fs_operation_def_t tab[])
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai fs_operation_def_t *new;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai const fs_operation_def_t *tab_entry;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* make a copy of standard vnode ops table */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai new = kmem_alloc(sdev_vnodeops_tbl_size, KM_SLEEP);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai bcopy((void *)sdev_vnodeops_tbl, new, sdev_vnodeops_tbl_size);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* replace the overrides from tab */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai for (tab_entry = tab; tab_entry->name != NULL; tab_entry++) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai fs_operation_def_t *std_entry = new;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai while (std_entry->name) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (strcmp(tab_entry->name, std_entry->name) == 0) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai std_entry->func = tab_entry->func;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai break;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai std_entry++;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (std_entry->name == NULL)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai cmn_err(CE_NOTE, "sdev_merge_vtab: entry %s unused.",
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai tab_entry->name);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (new);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/* free memory allocated by sdev_merge_vtab */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaistatic void
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaisdev_free_vtab(fs_operation_def_t *new)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai kmem_free(new, sdev_vnodeops_tbl_size);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai/*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * a generic setattr() function
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai *
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * note: flags only supports AT_UID and AT_GID.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Future enhancements can be done for other types, e.g. AT_MODE
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaiint
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllaidevname_setattr_func(struct vnode *vp, struct vattr *vap, int flags,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct cred *cred, int (*callback)(struct sdev_node *, struct vattr *,
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int), int protocol)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai{
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *dv = VTOSDEV(vp);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct sdev_node *parent = dv->sdev_dotdot;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai struct vattr *get;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai uint_t mask = vap->va_mask;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai int error;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* some sanity checks */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vap->va_mask & AT_NOSET)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (EINVAL);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vap->va_mask & AT_SIZE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (vp->v_type == VDIR) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (EISDIR);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* no need to set attribute, but do not fail either */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(parent);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&parent->sdev_contents, RW_READER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_state == SDEV_ZOMBIE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&parent->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /* If backing store exists, just set it. */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (dv->sdev_attrvp) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&parent->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * Otherwise, for nodes with the persistence attribute, create it.
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(dv->sdev_attr);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (SDEV_IS_PERSIST(dv) ||
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ((vap->va_mask & ~AT_TIMES) != 0 && !SDEV_IS_DYNAMIC(dv))) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_vattr_merge(dv, vap);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&dv->sdev_contents, RW_WRITER);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = sdev_shadow_node(dv, cred);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&parent->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (VOP_SETATTR(dv->sdev_attrvp, vap, flags, cred, NULL));
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * sdev_attr was allocated in sdev_mknode
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_enter(&dv->sdev_contents, RW_WRITER);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw error = secpolicy_vnode_setattr(cred, vp, vap,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw dv->sdev_attr, flags, sdev_unlocked_access, dv);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&parent->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai get = dv->sdev_attr;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & AT_MODE) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai get->va_mode &= S_IFMT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai get->va_mode |= vap->va_mode & ~S_IFMT;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((mask & AT_UID) || (mask & AT_GID)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & AT_UID)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai get->va_uid = vap->va_uid;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & AT_GID)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai get->va_gid = vap->va_gid;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai /*
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai * a callback must be provided if the protocol is set
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai */
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if ((protocol & AT_UID) || (protocol & AT_GID)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai ASSERT(callback);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai error = callback(dv, get, protocol);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (error) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&parent->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (error);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & AT_ATIME)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai get->va_atime = vap->va_atime;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & AT_MTIME)
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai get->va_mtime = vap->va_mtime;
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai if (mask & (AT_MODE | AT_UID | AT_GID | AT_CTIME)) {
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai gethrestime(&get->va_ctime);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai }
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai sdev_vattr_merge(dv, get);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&dv->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai rw_exit(&parent->sdev_contents);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai return (0);
facf4a8d7b59fde89a8662b4f4c73a758e6c402cllai}
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz/*
d62bc4badc1c1f1549c961cfb8b420e650e1272byz * a generic inactive() function
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
3c5e027b0f15017d4b6afff01915ea70ae476223Eric Taylor/*ARGSUSED*/
d62bc4badc1c1f1549c961cfb8b420e650e1272byzvoid
d62bc4badc1c1f1549c961cfb8b420e650e1272byzdevname_inactive_func(struct vnode *vp, struct cred *cred,
d62bc4badc1c1f1549c961cfb8b420e650e1272byz void (*callback)(struct vnode *))
d62bc4badc1c1f1549c961cfb8b420e650e1272byz{
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int clean;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz struct sdev_node *dv = VTOSDEV(vp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz int state;
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_enter(&vp->v_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz ASSERT(vp->v_count >= 1);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vp->v_count == 1 && callback != NULL)
d62bc4badc1c1f1549c961cfb8b420e650e1272byz callback(vp);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi rw_enter(&dv->sdev_contents, RW_WRITER);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi state = dv->sdev_state;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi
d62bc4badc1c1f1549c961cfb8b420e650e1272byz clean = (vp->v_count == 1) && (state == SDEV_ZOMBIE);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz
d62bc4badc1c1f1549c961cfb8b420e650e1272byz /*
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.
d62bc4badc1c1f1549c961cfb8b420e650e1272byz */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (clean) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi /* Remove the . entry to ourselves */
d62bc4badc1c1f1549c961cfb8b420e650e1272byz if (vp->v_type == VDIR) {
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi decr_link(dv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi VERIFY(dv->sdev_nlink == 1);
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi decr_link(dv);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz --vp->v_count;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi rw_exit(&dv->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_exit(&vp->v_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz sdev_nodedestroy(dv, 0);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz } else {
d62bc4badc1c1f1549c961cfb8b420e650e1272byz --vp->v_count;
9e5aa9d8a21f8efa8ba9c9e4a0aa6edc66d07eb2Robert Mustacchi rw_exit(&dv->sdev_contents);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz mutex_exit(&vp->v_lock);
d62bc4badc1c1f1549c961cfb8b420e650e1272byz }
d62bc4badc1c1f1549c961cfb8b420e650e1272byz}