xref: /titanic_41/usr/src/uts/common/fs/dev/sdev_vtops.c (revision 0b42f15ac52b077791d4ba079e8c163c592c3fda)
1aecfc01dSrui zang - Sun Microsystems - Beijing China /*
2aecfc01dSrui zang - Sun Microsystems - Beijing China  * CDDL HEADER START
3aecfc01dSrui zang - Sun Microsystems - Beijing China  *
4aecfc01dSrui zang - Sun Microsystems - Beijing China  * The contents of this file are subject to the terms of the
5aecfc01dSrui zang - Sun Microsystems - Beijing China  * Common Development and Distribution License (the "License").
6aecfc01dSrui zang - Sun Microsystems - Beijing China  * You may not use this file except in compliance with the License.
7aecfc01dSrui zang - Sun Microsystems - Beijing China  *
8aecfc01dSrui zang - Sun Microsystems - Beijing China  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9aecfc01dSrui zang - Sun Microsystems - Beijing China  * or http://www.opensolaris.org/os/licensing.
10aecfc01dSrui zang - Sun Microsystems - Beijing China  * See the License for the specific language governing permissions
11aecfc01dSrui zang - Sun Microsystems - Beijing China  * and limitations under the License.
12aecfc01dSrui zang - Sun Microsystems - Beijing China  *
13aecfc01dSrui zang - Sun Microsystems - Beijing China  * When distributing Covered Code, include this CDDL HEADER in each
14aecfc01dSrui zang - Sun Microsystems - Beijing China  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15aecfc01dSrui zang - Sun Microsystems - Beijing China  * If applicable, add the following below this CDDL HEADER, with the
16aecfc01dSrui zang - Sun Microsystems - Beijing China  * fields enclosed by brackets "[]" replaced with your own identifying
17aecfc01dSrui zang - Sun Microsystems - Beijing China  * information: Portions Copyright [yyyy] [name of copyright owner]
18aecfc01dSrui zang - Sun Microsystems - Beijing China  *
19aecfc01dSrui zang - Sun Microsystems - Beijing China  * CDDL HEADER END
20aecfc01dSrui zang - Sun Microsystems - Beijing China  */
21aecfc01dSrui zang - Sun Microsystems - Beijing China /*
22ceeba6f9Srui zang - Sun Microsystems - Beijing China  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23aecfc01dSrui zang - Sun Microsystems - Beijing China  */
24aecfc01dSrui zang - Sun Microsystems - Beijing China 
25aecfc01dSrui zang - Sun Microsystems - Beijing China /*
26aecfc01dSrui zang - Sun Microsystems - Beijing China  * vnode ops for the /dev/vt directory
27aecfc01dSrui zang - Sun Microsystems - Beijing China  */
28aecfc01dSrui zang - Sun Microsystems - Beijing China 
29aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/types.h>
30aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/param.h>
31aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/sysmacros.h>
32aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/sunndi.h>
33aecfc01dSrui zang - Sun Microsystems - Beijing China #include <fs/fs_subr.h>
34aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/fs/dv_node.h>
35aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/fs/sdev_impl.h>
36aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/policy.h>
37aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/stat.h>
38aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/vfs_opreg.h>
39aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/tty.h>
40aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/vt_impl.h>
41aecfc01dSrui zang - Sun Microsystems - Beijing China #include <sys/note.h>
42aecfc01dSrui zang - Sun Microsystems - Beijing China 
43aecfc01dSrui zang - Sun Microsystems - Beijing China /* warlock in this file only cares about variables shared by vt and devfs */
44aecfc01dSrui zang - Sun Microsystems - Beijing China _NOTE(SCHEME_PROTECTS_DATA("Do not care", sdev_node vattr vnode))
45aecfc01dSrui zang - Sun Microsystems - Beijing China 
46aecfc01dSrui zang - Sun Microsystems - Beijing China #define	DEVVT_UID_DEFAULT	SDEV_UID_DEFAULT
47aecfc01dSrui zang - Sun Microsystems - Beijing China #define	DEVVT_GID_DEFAULT	(0)
48aecfc01dSrui zang - Sun Microsystems - Beijing China #define	DEVVT_DEVMODE_DEFAULT	(0600)
49aecfc01dSrui zang - Sun Microsystems - Beijing China #define	DEVVT_ACTIVE_NAME	"active"
50ceeba6f9Srui zang - Sun Microsystems - Beijing China #define	DEVVT_CONSUSER_NAME	"console_user"
51aecfc01dSrui zang - Sun Microsystems - Beijing China 
52aecfc01dSrui zang - Sun Microsystems - Beijing China #define	isdigit(ch)	((ch) >= '0' && (ch) <= '9')
53aecfc01dSrui zang - Sun Microsystems - Beijing China 
54aecfc01dSrui zang - Sun Microsystems - Beijing China /* attributes for VT nodes */
55aecfc01dSrui zang - Sun Microsystems - Beijing China static vattr_t devvt_vattr = {
56aecfc01dSrui zang - Sun Microsystems - Beijing China 	AT_TYPE|AT_MODE|AT_UID|AT_GID,		/* va_mask */
57aecfc01dSrui zang - Sun Microsystems - Beijing China 	VCHR,					/* va_type */
58aecfc01dSrui zang - Sun Microsystems - Beijing China 	S_IFCHR | DEVVT_DEVMODE_DEFAULT,	/* va_mode */
59aecfc01dSrui zang - Sun Microsystems - Beijing China 	DEVVT_UID_DEFAULT,			/* va_uid */
60aecfc01dSrui zang - Sun Microsystems - Beijing China 	DEVVT_GID_DEFAULT,			/* va_gid */
61aecfc01dSrui zang - Sun Microsystems - Beijing China 	0					/* 0 hereafter */
62aecfc01dSrui zang - Sun Microsystems - Beijing China };
63aecfc01dSrui zang - Sun Microsystems - Beijing China 
64aecfc01dSrui zang - Sun Microsystems - Beijing China struct vnodeops		*devvt_vnodeops;
65aecfc01dSrui zang - Sun Microsystems - Beijing China 
66aecfc01dSrui zang - Sun Microsystems - Beijing China struct vnodeops *
devvt_getvnodeops(void)67aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_getvnodeops(void)
68aecfc01dSrui zang - Sun Microsystems - Beijing China {
69aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (devvt_vnodeops);
70aecfc01dSrui zang - Sun Microsystems - Beijing China }
71aecfc01dSrui zang - Sun Microsystems - Beijing China 
72aecfc01dSrui zang - Sun Microsystems - Beijing China static int
devvt_str2minor(const char * nm,minor_t * mp)73aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_str2minor(const char *nm, minor_t *mp)
74aecfc01dSrui zang - Sun Microsystems - Beijing China {
75aecfc01dSrui zang - Sun Microsystems - Beijing China 	long uminor = 0;
76aecfc01dSrui zang - Sun Microsystems - Beijing China 	char *endptr = NULL;
77aecfc01dSrui zang - Sun Microsystems - Beijing China 
78aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (nm == NULL || !isdigit(*nm))
79aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (EINVAL);
80aecfc01dSrui zang - Sun Microsystems - Beijing China 
81aecfc01dSrui zang - Sun Microsystems - Beijing China 	*mp = 0;
82aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (ddi_strtol(nm, &endptr, 10, &uminor) != 0 ||
83aecfc01dSrui zang - Sun Microsystems - Beijing China 	    *endptr != '\0' || uminor < 0) {
84aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (EINVAL);
85aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
86aecfc01dSrui zang - Sun Microsystems - Beijing China 
87aecfc01dSrui zang - Sun Microsystems - Beijing China 	*mp = (minor_t)uminor;
88aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (0);
89aecfc01dSrui zang - Sun Microsystems - Beijing China }
90aecfc01dSrui zang - Sun Microsystems - Beijing China 
912b080a34SJerry Gilliam /*
922b080a34SJerry Gilliam  * Validate that a node is up-to-date and correct.
932b080a34SJerry Gilliam  * A validator may not update the node state or
942b080a34SJerry Gilliam  * contents as a read lock permits entry by
952b080a34SJerry Gilliam  * multiple threads.
962b080a34SJerry Gilliam  */
97aecfc01dSrui zang - Sun Microsystems - Beijing China int
devvt_validate(struct sdev_node * dv)98aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_validate(struct sdev_node *dv)
99aecfc01dSrui zang - Sun Microsystems - Beijing China {
100aecfc01dSrui zang - Sun Microsystems - Beijing China 	minor_t min;
101aecfc01dSrui zang - Sun Microsystems - Beijing China 	char *nm = dv->sdev_name;
1022b080a34SJerry Gilliam 	int rval;
103aecfc01dSrui zang - Sun Microsystems - Beijing China 
104aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(dv->sdev_state == SDEV_READY);
1052b080a34SJerry Gilliam 	ASSERT(RW_LOCK_HELD(&(dv->sdev_dotdot)->sdev_contents));
106aecfc01dSrui zang - Sun Microsystems - Beijing China 
107aecfc01dSrui zang - Sun Microsystems - Beijing China 	/* validate only READY nodes */
108aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (dv->sdev_state != SDEV_READY) {
109aecfc01dSrui zang - Sun Microsystems - Beijing China 		sdcmn_err(("dev fs: skipping: node not ready %s(%p)",
110aecfc01dSrui zang - Sun Microsystems - Beijing China 		    nm, (void *)dv));
111aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (SDEV_VTOR_SKIP);
112aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
113aecfc01dSrui zang - Sun Microsystems - Beijing China 
114aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vt_wc_attached() == (major_t)-1)
115aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (SDEV_VTOR_INVALID);
116aecfc01dSrui zang - Sun Microsystems - Beijing China 
117aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (strcmp(nm, DEVVT_ACTIVE_NAME) == 0) {
118aecfc01dSrui zang - Sun Microsystems - Beijing China 		char *link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
119aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) vt_getactive(link, MAXPATHLEN);
1202b080a34SJerry Gilliam 		rval = (strcmp(link, dv->sdev_symlink) == 0) ?
1212b080a34SJerry Gilliam 		    SDEV_VTOR_VALID : SDEV_VTOR_STALE;
122aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(link, MAXPATHLEN);
1232b080a34SJerry Gilliam 		return (rval);
124ceeba6f9Srui zang - Sun Microsystems - Beijing China 	}
125ceeba6f9Srui zang - Sun Microsystems - Beijing China 
126ceeba6f9Srui zang - Sun Microsystems - Beijing China 	if (strcmp(nm, DEVVT_CONSUSER_NAME) == 0) {
127ceeba6f9Srui zang - Sun Microsystems - Beijing China 		char *link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
128ceeba6f9Srui zang - Sun Microsystems - Beijing China 		(void) vt_getconsuser(link, MAXPATHLEN);
1292b080a34SJerry Gilliam 		rval = (strcmp(link, dv->sdev_symlink) == 0) ?
1302b080a34SJerry Gilliam 		    SDEV_VTOR_VALID : SDEV_VTOR_STALE;
131ceeba6f9Srui zang - Sun Microsystems - Beijing China 		kmem_free(link, MAXPATHLEN);
1322b080a34SJerry Gilliam 		return (rval);
133ceeba6f9Srui zang - Sun Microsystems - Beijing China 	}
134ceeba6f9Srui zang - Sun Microsystems - Beijing China 
135ceeba6f9Srui zang - Sun Microsystems - Beijing China 	if (devvt_str2minor(nm, &min) != 0) {
136aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (SDEV_VTOR_INVALID);
137aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
138aecfc01dSrui zang - Sun Microsystems - Beijing China 
139aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vt_minor_valid(min) == B_FALSE)
140aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (SDEV_VTOR_INVALID);
141aecfc01dSrui zang - Sun Microsystems - Beijing China 
142aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (SDEV_VTOR_VALID);
143aecfc01dSrui zang - Sun Microsystems - Beijing China }
144aecfc01dSrui zang - Sun Microsystems - Beijing China 
145aecfc01dSrui zang - Sun Microsystems - Beijing China /*
146aecfc01dSrui zang - Sun Microsystems - Beijing China  * This callback is invoked from devname_lookup_func() to create
147aecfc01dSrui zang - Sun Microsystems - Beijing China  * a entry when the node is not found in the cache.
148aecfc01dSrui zang - Sun Microsystems - Beijing China  */
149aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED*/
150aecfc01dSrui zang - Sun Microsystems - Beijing China static int
devvt_create_rvp(struct sdev_node * ddv,char * nm,void ** arg,cred_t * cred,void * whatever,char * whichever)151aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_create_rvp(struct sdev_node *ddv, char *nm,
152aecfc01dSrui zang - Sun Microsystems - Beijing China     void **arg, cred_t *cred, void *whatever, char *whichever)
153aecfc01dSrui zang - Sun Microsystems - Beijing China {
154aecfc01dSrui zang - Sun Microsystems - Beijing China 	minor_t min;
155aecfc01dSrui zang - Sun Microsystems - Beijing China 	major_t maj;
156aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vattr *vap = (struct vattr *)arg;
157aecfc01dSrui zang - Sun Microsystems - Beijing China 
158aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((maj = vt_wc_attached()) == (major_t)-1)
159aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (SDEV_VTOR_INVALID);
160aecfc01dSrui zang - Sun Microsystems - Beijing China 
161aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (strcmp(nm, DEVVT_ACTIVE_NAME) == 0) {
162aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) vt_getactive((char *)*arg, MAXPATHLEN);
163aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (0);
164aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
165aecfc01dSrui zang - Sun Microsystems - Beijing China 
166ceeba6f9Srui zang - Sun Microsystems - Beijing China 	if (strcmp(nm, DEVVT_CONSUSER_NAME) == 0) {
167ceeba6f9Srui zang - Sun Microsystems - Beijing China 		(void) vt_getconsuser((char *)*arg, MAXPATHLEN);
168ceeba6f9Srui zang - Sun Microsystems - Beijing China 		return (0);
169ceeba6f9Srui zang - Sun Microsystems - Beijing China 	}
170aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (devvt_str2minor(nm, &min) != 0)
171aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (-1);
172aecfc01dSrui zang - Sun Microsystems - Beijing China 
173aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (vt_minor_valid(min) == B_FALSE)
174aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (-1);
175aecfc01dSrui zang - Sun Microsystems - Beijing China 
176aecfc01dSrui zang - Sun Microsystems - Beijing China 	*vap = devvt_vattr;
177aecfc01dSrui zang - Sun Microsystems - Beijing China 	vap->va_rdev = makedevice(maj, min);
178aecfc01dSrui zang - Sun Microsystems - Beijing China 
179aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (0);
180aecfc01dSrui zang - Sun Microsystems - Beijing China }
181aecfc01dSrui zang - Sun Microsystems - Beijing China 
182aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED3*/
183aecfc01dSrui zang - Sun Microsystems - Beijing China static int
devvt_lookup(struct vnode * dvp,char * nm,struct vnode ** vpp,struct pathname * pnp,int flags,struct vnode * rdir,struct cred * cred,caller_context_t * ct,int * direntflags,pathname_t * realpnp)184aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_lookup(struct vnode *dvp, char *nm, struct vnode **vpp,
185aecfc01dSrui zang - Sun Microsystems - Beijing China     struct pathname *pnp, int flags, struct vnode *rdir, struct cred *cred,
186aecfc01dSrui zang - Sun Microsystems - Beijing China     caller_context_t *ct, int *direntflags, pathname_t *realpnp)
187aecfc01dSrui zang - Sun Microsystems - Beijing China {
188aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct sdev_node *sdvp = VTOSDEV(dvp);
189aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct sdev_node *dv;
190aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vnode *rvp = NULL;
191aecfc01dSrui zang - Sun Microsystems - Beijing China 	int type, error;
192aecfc01dSrui zang - Sun Microsystems - Beijing China 
193ceeba6f9Srui zang - Sun Microsystems - Beijing China 	if ((strcmp(nm, DEVVT_ACTIVE_NAME) == 0) ||
194ceeba6f9Srui zang - Sun Microsystems - Beijing China 	    (strcmp(nm, DEVVT_CONSUSER_NAME) == 0)) {
195aecfc01dSrui zang - Sun Microsystems - Beijing China 		type = SDEV_VLINK;
196aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else {
197aecfc01dSrui zang - Sun Microsystems - Beijing China 		type = SDEV_VATTR;
198aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
199aecfc01dSrui zang - Sun Microsystems - Beijing China 
200aecfc01dSrui zang - Sun Microsystems - Beijing China /* Give warlock a more clear call graph */
201aecfc01dSrui zang - Sun Microsystems - Beijing China #ifndef __lock_lint
202aecfc01dSrui zang - Sun Microsystems - Beijing China 	error = devname_lookup_func(sdvp, nm, vpp, cred,
203aecfc01dSrui zang - Sun Microsystems - Beijing China 	    devvt_create_rvp, type);
204aecfc01dSrui zang - Sun Microsystems - Beijing China #else
205aecfc01dSrui zang - Sun Microsystems - Beijing China 	devvt_create_rvp(0, 0, 0, 0, 0, 0);
206aecfc01dSrui zang - Sun Microsystems - Beijing China #endif
207aecfc01dSrui zang - Sun Microsystems - Beijing China 
208aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (error == 0) {
209aecfc01dSrui zang - Sun Microsystems - Beijing China 		switch ((*vpp)->v_type) {
210aecfc01dSrui zang - Sun Microsystems - Beijing China 		case VCHR:
211aecfc01dSrui zang - Sun Microsystems - Beijing China 			dv = VTOSDEV(VTOS(*vpp)->s_realvp);
212aecfc01dSrui zang - Sun Microsystems - Beijing China 			ASSERT(VOP_REALVP(SDEVTOV(dv), &rvp, NULL) == ENOSYS);
213aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
214aecfc01dSrui zang - Sun Microsystems - Beijing China 		case VDIR:
215aecfc01dSrui zang - Sun Microsystems - Beijing China 		case VLNK:
216aecfc01dSrui zang - Sun Microsystems - Beijing China 			dv = VTOSDEV(*vpp);
217aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
218aecfc01dSrui zang - Sun Microsystems - Beijing China 		default:
219aecfc01dSrui zang - Sun Microsystems - Beijing China 			cmn_err(CE_PANIC, "devvt_lookup: Unsupported node "
220aecfc01dSrui zang - Sun Microsystems - Beijing China 			    "type: %p: %d", (void *)(*vpp), (*vpp)->v_type);
221aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
222aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
223aecfc01dSrui zang - Sun Microsystems - Beijing China 		ASSERT(SDEV_HELD(dv));
224aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
225aecfc01dSrui zang - Sun Microsystems - Beijing China 
226aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (error);
227aecfc01dSrui zang - Sun Microsystems - Beijing China }
228aecfc01dSrui zang - Sun Microsystems - Beijing China 
229aecfc01dSrui zang - Sun Microsystems - Beijing China static void
devvt_create_snode(struct sdev_node * ddv,char * nm,struct cred * cred,int type)230aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_create_snode(struct sdev_node *ddv, char *nm, struct cred *cred, int type)
231aecfc01dSrui zang - Sun Microsystems - Beijing China {
232aecfc01dSrui zang - Sun Microsystems - Beijing China 	int error;
233aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct sdev_node *sdv = NULL;
234bb5fffbeSJerry Gilliam 	struct vattr vattr;
235bb5fffbeSJerry Gilliam 	struct vattr *vap = &vattr;
236aecfc01dSrui zang - Sun Microsystems - Beijing China 	major_t maj;
237aecfc01dSrui zang - Sun Microsystems - Beijing China 	minor_t min;
238aecfc01dSrui zang - Sun Microsystems - Beijing China 
2392b080a34SJerry Gilliam 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
2402b080a34SJerry Gilliam 
241aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((maj = vt_wc_attached()) == (major_t)-1)
242aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
243aecfc01dSrui zang - Sun Microsystems - Beijing China 
244aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (strcmp(nm, DEVVT_ACTIVE_NAME) != 0 &&
245ceeba6f9Srui zang - Sun Microsystems - Beijing China 	    strcmp(nm, DEVVT_CONSUSER_NAME) != 0 &&
246aecfc01dSrui zang - Sun Microsystems - Beijing China 	    devvt_str2minor(nm, &min) != 0)
247aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
248aecfc01dSrui zang - Sun Microsystems - Beijing China 
249aecfc01dSrui zang - Sun Microsystems - Beijing China 	error = sdev_mknode(ddv, nm, &sdv, NULL, NULL, NULL, cred, SDEV_INIT);
250aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (error || !sdv) {
251aecfc01dSrui zang - Sun Microsystems - Beijing China 		return;
252aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
253aecfc01dSrui zang - Sun Microsystems - Beijing China 
254aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&sdv->sdev_lookup_lock);
255aecfc01dSrui zang - Sun Microsystems - Beijing China 	SDEV_BLOCK_OTHERS(sdv, SDEV_LOOKUP);
256aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&sdv->sdev_lookup_lock);
257aecfc01dSrui zang - Sun Microsystems - Beijing China 
258aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (type & SDEV_VATTR) {
259bb5fffbeSJerry Gilliam 		*vap = devvt_vattr;
260aecfc01dSrui zang - Sun Microsystems - Beijing China 		vap->va_rdev = makedevice(maj, min);
261aecfc01dSrui zang - Sun Microsystems - Beijing China 		error = sdev_mknode(ddv, nm, &sdv, vap, NULL,
262aecfc01dSrui zang - Sun Microsystems - Beijing China 		    NULL, cred, SDEV_READY);
263aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else if (type & SDEV_VLINK) {
264aecfc01dSrui zang - Sun Microsystems - Beijing China 		char *link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
265aecfc01dSrui zang - Sun Microsystems - Beijing China 
266aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) vt_getactive(link, MAXPATHLEN);
267bb5fffbeSJerry Gilliam 		*vap = sdev_vattr_lnk;
268aecfc01dSrui zang - Sun Microsystems - Beijing China 		vap->va_size = strlen(link);
269aecfc01dSrui zang - Sun Microsystems - Beijing China 		error = sdev_mknode(ddv, nm, &sdv, vap, NULL,
270aecfc01dSrui zang - Sun Microsystems - Beijing China 		    (void *)link, cred, SDEV_READY);
271aecfc01dSrui zang - Sun Microsystems - Beijing China 
272aecfc01dSrui zang - Sun Microsystems - Beijing China 		kmem_free(link, MAXPATHLEN);
273aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
274aecfc01dSrui zang - Sun Microsystems - Beijing China 
275*9e5aa9d8SRobert Mustacchi 	if (error != 0) {
276*9e5aa9d8SRobert Mustacchi 		SDEV_RELE(sdv);
277*9e5aa9d8SRobert Mustacchi 		return;
278*9e5aa9d8SRobert Mustacchi 	}
279*9e5aa9d8SRobert Mustacchi 
280aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&sdv->sdev_lookup_lock);
281aecfc01dSrui zang - Sun Microsystems - Beijing China 	SDEV_UNBLOCK_OTHERS(sdv, SDEV_LOOKUP);
282aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&sdv->sdev_lookup_lock);
283aecfc01dSrui zang - Sun Microsystems - Beijing China 
284aecfc01dSrui zang - Sun Microsystems - Beijing China }
285aecfc01dSrui zang - Sun Microsystems - Beijing China 
286aecfc01dSrui zang - Sun Microsystems - Beijing China static void
devvt_rebuild_stale_link(struct sdev_node * ddv,struct sdev_node * dv)2872b080a34SJerry Gilliam devvt_rebuild_stale_link(struct sdev_node *ddv, struct sdev_node *dv)
2882b080a34SJerry Gilliam {
2892b080a34SJerry Gilliam 	char *link;
2902b080a34SJerry Gilliam 
2912b080a34SJerry Gilliam 	ASSERT(RW_WRITE_HELD(&ddv->sdev_contents));
2922b080a34SJerry Gilliam 
2932b080a34SJerry Gilliam 	ASSERT((strcmp(dv->sdev_name, DEVVT_ACTIVE_NAME) == 0) ||
2942b080a34SJerry Gilliam 	    (strcmp(dv->sdev_name, DEVVT_CONSUSER_NAME) == 0));
2952b080a34SJerry Gilliam 
2962b080a34SJerry Gilliam 	link = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
2972b080a34SJerry Gilliam 	if (strcmp(dv->sdev_name, DEVVT_ACTIVE_NAME) == 0) {
2982b080a34SJerry Gilliam 		(void) vt_getactive(link, MAXPATHLEN);
2992b080a34SJerry Gilliam 	} else if (strcmp(dv->sdev_name, DEVVT_CONSUSER_NAME) == 0) {
3002b080a34SJerry Gilliam 		(void) vt_getconsuser(link, MAXPATHLEN);
3012b080a34SJerry Gilliam 	}
3022b080a34SJerry Gilliam 
3032b080a34SJerry Gilliam 	if (strcmp(link, dv->sdev_symlink) != 0) {
3042b080a34SJerry Gilliam 		strfree(dv->sdev_symlink);
3052b080a34SJerry Gilliam 		dv->sdev_symlink = strdup(link);
3062b080a34SJerry Gilliam 		dv->sdev_attr->va_size = strlen(link);
3072b080a34SJerry Gilliam 	}
3082b080a34SJerry Gilliam 	kmem_free(link, MAXPATHLEN);
3092b080a34SJerry Gilliam }
3102b080a34SJerry Gilliam 
3112b080a34SJerry Gilliam /*
3122b080a34SJerry Gilliam  * First step in refreshing directory contents.
3132b080a34SJerry Gilliam  * Remove each invalid entry and rebuild the link
3142b080a34SJerry Gilliam  * reference for each stale entry.
3152b080a34SJerry Gilliam  */
3162b080a34SJerry Gilliam static void
devvt_prunedir(struct sdev_node * ddv)317aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_prunedir(struct sdev_node *ddv)
318aecfc01dSrui zang - Sun Microsystems - Beijing China {
319aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vnode *vp;
320aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct sdev_node *dv, *next = NULL;
321aecfc01dSrui zang - Sun Microsystems - Beijing China 	int (*vtor)(struct sdev_node *) = NULL;
322aecfc01dSrui zang - Sun Microsystems - Beijing China 
323aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(ddv->sdev_flags & SDEV_VTOR);
324aecfc01dSrui zang - Sun Microsystems - Beijing China 
325aecfc01dSrui zang - Sun Microsystems - Beijing China 	vtor = (int (*)(struct sdev_node *))sdev_get_vtor(ddv);
326aecfc01dSrui zang - Sun Microsystems - Beijing China 	ASSERT(vtor);
327aecfc01dSrui zang - Sun Microsystems - Beijing China 
328aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (dv = SDEV_FIRST_ENTRY(ddv); dv; dv = next) {
329aecfc01dSrui zang - Sun Microsystems - Beijing China 		next = SDEV_NEXT_ENTRY(ddv, dv);
330aecfc01dSrui zang - Sun Microsystems - Beijing China 
331aecfc01dSrui zang - Sun Microsystems - Beijing China 		switch (vtor(dv)) {
332aecfc01dSrui zang - Sun Microsystems - Beijing China 		case SDEV_VTOR_VALID:
3332b080a34SJerry Gilliam 			break;
334aecfc01dSrui zang - Sun Microsystems - Beijing China 		case SDEV_VTOR_SKIP:
3352b080a34SJerry Gilliam 			break;
336aecfc01dSrui zang - Sun Microsystems - Beijing China 		case SDEV_VTOR_INVALID:
3372b080a34SJerry Gilliam 			vp = SDEVTOV(dv);
3382b080a34SJerry Gilliam 			if (vp->v_count != 0)
3392b080a34SJerry Gilliam 				break;
3402b080a34SJerry Gilliam 			/* remove the cached node */
3412b080a34SJerry Gilliam 			SDEV_HOLD(dv);
3422b080a34SJerry Gilliam 			(void) sdev_cache_update(ddv, &dv,
3432b080a34SJerry Gilliam 			    dv->sdev_name, SDEV_CACHE_DELETE);
344*9e5aa9d8SRobert Mustacchi 			SDEV_RELE(dv);
3452b080a34SJerry Gilliam 			break;
346b127ac41SPhilip Kirk 		case SDEV_VTOR_STALE:
3472b080a34SJerry Gilliam 			devvt_rebuild_stale_link(ddv, dv);
348aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
349aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
350aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
351aecfc01dSrui zang - Sun Microsystems - Beijing China }
352aecfc01dSrui zang - Sun Microsystems - Beijing China 
353aecfc01dSrui zang - Sun Microsystems - Beijing China static void
devvt_cleandir(struct vnode * dvp,struct cred * cred)354aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_cleandir(struct vnode *dvp, struct cred *cred)
355aecfc01dSrui zang - Sun Microsystems - Beijing China {
356aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct sdev_node *sdvp = VTOSDEV(dvp);
357aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct sdev_node *dv, *next = NULL;
358aecfc01dSrui zang - Sun Microsystems - Beijing China 	int min, cnt;
359ceeba6f9Srui zang - Sun Microsystems - Beijing China 	char found = 0;
360aecfc01dSrui zang - Sun Microsystems - Beijing China 
361aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_enter(&vc_lock);
362aecfc01dSrui zang - Sun Microsystems - Beijing China 	cnt = VC_INSTANCES_COUNT;
363aecfc01dSrui zang - Sun Microsystems - Beijing China 	mutex_exit(&vc_lock);
364aecfc01dSrui zang - Sun Microsystems - Beijing China 
365aecfc01dSrui zang - Sun Microsystems - Beijing China /* We have to fool warlock this way, otherwise it will complain */
366aecfc01dSrui zang - Sun Microsystems - Beijing China #ifndef	__lock_lint
367aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (rw_tryupgrade(&sdvp->sdev_contents) == NULL) {
368aecfc01dSrui zang - Sun Microsystems - Beijing China 		rw_exit(&sdvp->sdev_contents);
369aecfc01dSrui zang - Sun Microsystems - Beijing China 		rw_enter(&sdvp->sdev_contents, RW_WRITER);
370aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
371aecfc01dSrui zang - Sun Microsystems - Beijing China #else
372aecfc01dSrui zang - Sun Microsystems - Beijing China 	rw_enter(&sdvp->sdev_contents, RW_WRITER);
373aecfc01dSrui zang - Sun Microsystems - Beijing China #endif
374aecfc01dSrui zang - Sun Microsystems - Beijing China 
3752b080a34SJerry Gilliam 	/* 1.  prune invalid nodes and rebuild stale symlinks */
3762b080a34SJerry Gilliam 	devvt_prunedir(sdvp);
3772b080a34SJerry Gilliam 
3782b080a34SJerry Gilliam 	/* 2. create missing nodes */
379aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (min = 0; min < cnt; min++) {
380aecfc01dSrui zang - Sun Microsystems - Beijing China 		char nm[16];
381aecfc01dSrui zang - Sun Microsystems - Beijing China 
382aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (vt_minor_valid(min) == B_FALSE)
383aecfc01dSrui zang - Sun Microsystems - Beijing China 			continue;
384aecfc01dSrui zang - Sun Microsystems - Beijing China 
385aecfc01dSrui zang - Sun Microsystems - Beijing China 		(void) snprintf(nm, sizeof (nm), "%d", min);
386aecfc01dSrui zang - Sun Microsystems - Beijing China 		found = 0;
387aecfc01dSrui zang - Sun Microsystems - Beijing China 		for (dv = SDEV_FIRST_ENTRY(sdvp); dv; dv = next) {
388aecfc01dSrui zang - Sun Microsystems - Beijing China 			next = SDEV_NEXT_ENTRY(sdvp, dv);
389aecfc01dSrui zang - Sun Microsystems - Beijing China 
3902b080a34SJerry Gilliam 			/* validate only ready nodes */
391aecfc01dSrui zang - Sun Microsystems - Beijing China 			if (dv->sdev_state != SDEV_READY)
392aecfc01dSrui zang - Sun Microsystems - Beijing China 				continue;
393aecfc01dSrui zang - Sun Microsystems - Beijing China 			if (strcmp(nm, dv->sdev_name) == 0) {
394aecfc01dSrui zang - Sun Microsystems - Beijing China 				found = 1;
395aecfc01dSrui zang - Sun Microsystems - Beijing China 				break;
396aecfc01dSrui zang - Sun Microsystems - Beijing China 			}
397aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
398aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (!found) {
399aecfc01dSrui zang - Sun Microsystems - Beijing China 			devvt_create_snode(sdvp, nm, cred, SDEV_VATTR);
400aecfc01dSrui zang - Sun Microsystems - Beijing China 		}
401aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
402aecfc01dSrui zang - Sun Microsystems - Beijing China 
4032b080a34SJerry Gilliam 	/* 3. create active link node and console user link node */
404aecfc01dSrui zang - Sun Microsystems - Beijing China 	found = 0;
405aecfc01dSrui zang - Sun Microsystems - Beijing China 	for (dv = SDEV_FIRST_ENTRY(sdvp); dv; dv = next) {
406aecfc01dSrui zang - Sun Microsystems - Beijing China 		next = SDEV_NEXT_ENTRY(sdvp, dv);
407aecfc01dSrui zang - Sun Microsystems - Beijing China 
4082b080a34SJerry Gilliam 		/* validate only ready nodes */
409aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (dv->sdev_state != SDEV_READY)
410aecfc01dSrui zang - Sun Microsystems - Beijing China 			continue;
411ceeba6f9Srui zang - Sun Microsystems - Beijing China 		if ((strcmp(dv->sdev_name, DEVVT_ACTIVE_NAME) == NULL))
412ceeba6f9Srui zang - Sun Microsystems - Beijing China 			found |= 0x01;
413ceeba6f9Srui zang - Sun Microsystems - Beijing China 		if ((strcmp(dv->sdev_name, DEVVT_CONSUSER_NAME) == NULL))
414ceeba6f9Srui zang - Sun Microsystems - Beijing China 			found |= 0x02;
415ceeba6f9Srui zang - Sun Microsystems - Beijing China 
416ceeba6f9Srui zang - Sun Microsystems - Beijing China 		if ((found & 0x01) && (found & 0x02))
417aecfc01dSrui zang - Sun Microsystems - Beijing China 			break;
418aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
419ceeba6f9Srui zang - Sun Microsystems - Beijing China 	if (!(found & 0x01))
420aecfc01dSrui zang - Sun Microsystems - Beijing China 		devvt_create_snode(sdvp, DEVVT_ACTIVE_NAME, cred, SDEV_VLINK);
421ceeba6f9Srui zang - Sun Microsystems - Beijing China 	if (!(found & 0x02))
422ceeba6f9Srui zang - Sun Microsystems - Beijing China 		devvt_create_snode(sdvp, DEVVT_CONSUSER_NAME, cred, SDEV_VLINK);
423ceeba6f9Srui zang - Sun Microsystems - Beijing China 
424aecfc01dSrui zang - Sun Microsystems - Beijing China #ifndef	__lock_lint
425aecfc01dSrui zang - Sun Microsystems - Beijing China 	rw_downgrade(&sdvp->sdev_contents);
426aecfc01dSrui zang - Sun Microsystems - Beijing China #else
427aecfc01dSrui zang - Sun Microsystems - Beijing China 	rw_exit(&sdvp->sdev_contents);
428aecfc01dSrui zang - Sun Microsystems - Beijing China #endif
429aecfc01dSrui zang - Sun Microsystems - Beijing China }
430aecfc01dSrui zang - Sun Microsystems - Beijing China 
431aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED4*/
432aecfc01dSrui zang - Sun Microsystems - Beijing China static int
devvt_readdir(struct vnode * dvp,struct uio * uiop,struct cred * cred,int * eofp,caller_context_t * ct,int flags)433aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_readdir(struct vnode *dvp, struct uio *uiop, struct cred *cred,
434aecfc01dSrui zang - Sun Microsystems - Beijing China     int *eofp, caller_context_t *ct, int flags)
435aecfc01dSrui zang - Sun Microsystems - Beijing China {
436aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (uiop->uio_offset == 0) {
437aecfc01dSrui zang - Sun Microsystems - Beijing China 		devvt_cleandir(dvp, cred);
438aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
439aecfc01dSrui zang - Sun Microsystems - Beijing China 
440aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (devname_readdir_func(dvp, uiop, cred, eofp, 0));
441aecfc01dSrui zang - Sun Microsystems - Beijing China }
442aecfc01dSrui zang - Sun Microsystems - Beijing China 
443aecfc01dSrui zang - Sun Microsystems - Beijing China /*
444aecfc01dSrui zang - Sun Microsystems - Beijing China  * We allow create to find existing nodes
445aecfc01dSrui zang - Sun Microsystems - Beijing China  *	- if the node doesn't exist - EROFS
446aecfc01dSrui zang - Sun Microsystems - Beijing China  *	- creating an existing dir read-only succeeds, otherwise EISDIR
447aecfc01dSrui zang - Sun Microsystems - Beijing China  *	- exclusive creates fail - EEXIST
448aecfc01dSrui zang - Sun Microsystems - Beijing China  */
449aecfc01dSrui zang - Sun Microsystems - Beijing China /*ARGSUSED2*/
450aecfc01dSrui zang - Sun Microsystems - Beijing China static int
devvt_create(struct vnode * dvp,char * nm,struct vattr * vap,vcexcl_t excl,int mode,struct vnode ** vpp,struct cred * cred,int flag,caller_context_t * ct,vsecattr_t * vsecp)451aecfc01dSrui zang - Sun Microsystems - Beijing China devvt_create(struct vnode *dvp, char *nm, struct vattr *vap, vcexcl_t excl,
452aecfc01dSrui zang - Sun Microsystems - Beijing China     int mode, struct vnode **vpp, struct cred *cred, int flag,
453aecfc01dSrui zang - Sun Microsystems - Beijing China     caller_context_t *ct, vsecattr_t *vsecp)
454aecfc01dSrui zang - Sun Microsystems - Beijing China {
455aecfc01dSrui zang - Sun Microsystems - Beijing China 	int error;
456aecfc01dSrui zang - Sun Microsystems - Beijing China 	struct vnode *vp;
457aecfc01dSrui zang - Sun Microsystems - Beijing China 
458aecfc01dSrui zang - Sun Microsystems - Beijing China 	*vpp = NULL;
459aecfc01dSrui zang - Sun Microsystems - Beijing China 
460aecfc01dSrui zang - Sun Microsystems - Beijing China 	if ((error = devvt_lookup(dvp, nm, &vp, NULL, 0, NULL, cred, ct, NULL,
461aecfc01dSrui zang - Sun Microsystems - Beijing China 	    NULL)) != 0) {
462aecfc01dSrui zang - Sun Microsystems - Beijing China 		if (error == ENOENT)
463aecfc01dSrui zang - Sun Microsystems - Beijing China 			error = EROFS;
464aecfc01dSrui zang - Sun Microsystems - Beijing China 		return (error);
465aecfc01dSrui zang - Sun Microsystems - Beijing China 	}
466aecfc01dSrui zang - Sun Microsystems - Beijing China 
467aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (excl == EXCL)
468aecfc01dSrui zang - Sun Microsystems - Beijing China 		error = EEXIST;
469aecfc01dSrui zang - Sun Microsystems - Beijing China 	else if (vp->v_type == VDIR && (mode & VWRITE))
470aecfc01dSrui zang - Sun Microsystems - Beijing China 		error = EISDIR;
471aecfc01dSrui zang - Sun Microsystems - Beijing China 	else
472aecfc01dSrui zang - Sun Microsystems - Beijing China 		error = VOP_ACCESS(vp, mode, 0, cred, ct);
473aecfc01dSrui zang - Sun Microsystems - Beijing China 
474aecfc01dSrui zang - Sun Microsystems - Beijing China 	if (error) {
475aecfc01dSrui zang - Sun Microsystems - Beijing China 		VN_RELE(vp);
476aecfc01dSrui zang - Sun Microsystems - Beijing China 	} else
477aecfc01dSrui zang - Sun Microsystems - Beijing China 		*vpp = vp;
478aecfc01dSrui zang - Sun Microsystems - Beijing China 
479aecfc01dSrui zang - Sun Microsystems - Beijing China 	return (error);
480aecfc01dSrui zang - Sun Microsystems - Beijing China }
481aecfc01dSrui zang - Sun Microsystems - Beijing China 
482aecfc01dSrui zang - Sun Microsystems - Beijing China const fs_operation_def_t devvt_vnodeops_tbl[] = {
483aecfc01dSrui zang - Sun Microsystems - Beijing China 	VOPNAME_READDIR,	{ .vop_readdir = devvt_readdir },
484aecfc01dSrui zang - Sun Microsystems - Beijing China 	VOPNAME_LOOKUP,		{ .vop_lookup = devvt_lookup },
485aecfc01dSrui zang - Sun Microsystems - Beijing China 	VOPNAME_CREATE,		{ .vop_create = devvt_create },
486aecfc01dSrui zang - Sun Microsystems - Beijing China 	VOPNAME_REMOVE,		{ .error = fs_nosys },
487aecfc01dSrui zang - Sun Microsystems - Beijing China 	VOPNAME_MKDIR,		{ .error = fs_nosys },
488aecfc01dSrui zang - Sun Microsystems - Beijing China 	VOPNAME_RMDIR,		{ .error = fs_nosys },
489aecfc01dSrui zang - Sun Microsystems - Beijing China 	VOPNAME_SYMLINK,	{ .error = fs_nosys },
490aecfc01dSrui zang - Sun Microsystems - Beijing China 	VOPNAME_SETSECATTR,	{ .error = fs_nosys },
491aecfc01dSrui zang - Sun Microsystems - Beijing China 	NULL,			NULL
492aecfc01dSrui zang - Sun Microsystems - Beijing China };
493