1*55344Spendry /*
2*55344Spendry  * Copyright (c) 1992 The Regents of the University of California
3*55344Spendry  * Copyright (c) 1990, 1992 Jan-Simon Pendry
4*55344Spendry  * All rights reserved.
5*55344Spendry  *
6*55344Spendry  * This code is derived from software donated to Berkeley by
7*55344Spendry  * Jan-Simon Pendry.
8*55344Spendry  *
9*55344Spendry  * %sccs.include.redist.c%
10*55344Spendry  *
11*55344Spendry  *	@(#)kernfs_vnops.c	7.1 (Berkeley) 07/18/92
12*55344Spendry  */
13*55344Spendry 
14*55344Spendry /*
15*55344Spendry  * Kernel parameter filesystem (/kern)
16*55344Spendry  */
17*55344Spendry 
18*55344Spendry #include <sys/param.h>
19*55344Spendry #include <sys/systm.h>
20*55344Spendry #include <sys/kernel.h>
21*55344Spendry #include <sys/vmmeter.h>
22*55344Spendry #include <sys/types.h>
23*55344Spendry #include <sys/time.h>
24*55344Spendry #include <sys/proc.h>
25*55344Spendry #include <sys/vnode.h>
26*55344Spendry #include <sys/malloc.h>
27*55344Spendry #include <sys/file.h>
28*55344Spendry #include <sys/stat.h>
29*55344Spendry #include <sys/mount.h>
30*55344Spendry #include <sys/namei.h>
31*55344Spendry #include <sys/buf.h>
32*55344Spendry #include <sys/dirent.h>
33*55344Spendry #include <miscfs/kernfs/kernfs.h>
34*55344Spendry 
35*55344Spendry #define KSTRING	256		/* Largest I/O available via this filesystem */
36*55344Spendry #define	UIO_MX 32
37*55344Spendry 
38*55344Spendry struct kern_target {
39*55344Spendry 	char *kt_name;
40*55344Spendry 	void *kt_data;
41*55344Spendry #define	KTT_NULL 1
42*55344Spendry #define	KTT_TIME 5
43*55344Spendry #define KTT_INT	17
44*55344Spendry #define	KTT_STRING 31
45*55344Spendry #define KTT_HOSTNAME 47
46*55344Spendry #define KTT_AVENRUN 53
47*55344Spendry 	int kt_tag;
48*55344Spendry #define	KTM_RO	0
49*55344Spendry #define	KTM_RO_MODE		(S_IRUSR|S_IRGRP|S_IROTH)
50*55344Spendry #define	KTM_RW	43
51*55344Spendry #define	KTM_RW_MODE		(S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
52*55344Spendry #define KTM_DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
53*55344Spendry 	int kt_rw;
54*55344Spendry 	int kt_vtype;
55*55344Spendry } kern_targets[] = {
56*55344Spendry /* NOTE: The name must be less than UIO_MX-16 chars in length */
57*55344Spendry 	/* name		data		tag		ro/rw */
58*55344Spendry 	{ ".",		0,		KTT_NULL,	KTM_RO,	VDIR },
59*55344Spendry 	{ "copyright",	copyright,	KTT_STRING,	KTM_RO,	VREG },
60*55344Spendry 	{ "hostname",	0,		KTT_HOSTNAME,	KTM_RW,	VREG },
61*55344Spendry 	{ "hz",		&hz,		KTT_INT,	KTM_RO,	VREG },
62*55344Spendry 	{ "loadavg",	0,		KTT_AVENRUN,	KTM_RO,	VREG },
63*55344Spendry 	{ "pagesize",	&cnt.v_page_size, KTT_INT,	KTM_RO,	VREG },
64*55344Spendry 	{ "physmem",	&physmem,	KTT_INT,	KTM_RO,	VREG },
65*55344Spendry 	{ "root",	0,		KTT_NULL,	KTM_RO,	VDIR },
66*55344Spendry 	{ "rootdev",	0,		KTT_NULL,	KTM_RO,	VBLK },
67*55344Spendry 	{ "time",	0,		KTT_TIME,	KTM_RO,	VREG },
68*55344Spendry 	{ "version",	version,	KTT_STRING,	KTM_RO,	VREG },
69*55344Spendry };
70*55344Spendry 
71*55344Spendry static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
72*55344Spendry 
73*55344Spendry static int
74*55344Spendry kernfs_xread(kt, buf, len, lenp)
75*55344Spendry 	struct kern_target *kt;
76*55344Spendry 	char *buf;
77*55344Spendry 	int len;
78*55344Spendry 	int *lenp;
79*55344Spendry {
80*55344Spendry 	int xlen;
81*55344Spendry 
82*55344Spendry 	switch (kt->kt_tag) {
83*55344Spendry 	case KTT_TIME: {
84*55344Spendry 		struct timeval tv;
85*55344Spendry 		microtime(&tv);
86*55344Spendry 		sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
87*55344Spendry 		break;
88*55344Spendry 	}
89*55344Spendry 
90*55344Spendry 	case KTT_INT: {
91*55344Spendry 		int *ip = kt->kt_data;
92*55344Spendry 		sprintf(buf, "%d\n", *ip);
93*55344Spendry 		break;
94*55344Spendry 	}
95*55344Spendry 
96*55344Spendry 	case KTT_STRING: {
97*55344Spendry 		char *cp = kt->kt_data;
98*55344Spendry 		int xlen = strlen(cp) + 1;
99*55344Spendry 
100*55344Spendry 		if (xlen >= len)
101*55344Spendry 			return (EINVAL);
102*55344Spendry 
103*55344Spendry 		bcopy(cp, buf, xlen);
104*55344Spendry 		break;
105*55344Spendry 	}
106*55344Spendry 
107*55344Spendry 	case KTT_HOSTNAME: {
108*55344Spendry 		char *cp = hostname;
109*55344Spendry 		int xlen = hostnamelen;
110*55344Spendry 
111*55344Spendry 		if (xlen >= len)
112*55344Spendry 			return (EINVAL);
113*55344Spendry 
114*55344Spendry 		sprintf(buf, "%s\n", cp);
115*55344Spendry 		break;
116*55344Spendry 	}
117*55344Spendry 
118*55344Spendry 	case KTT_AVENRUN:
119*55344Spendry 		sprintf(buf, "%ld %ld %ld %ld\n",
120*55344Spendry 				averunnable.ldavg[0],
121*55344Spendry 				averunnable.ldavg[1],
122*55344Spendry 				averunnable.ldavg[2],
123*55344Spendry 				averunnable.fscale);
124*55344Spendry 		break;
125*55344Spendry 
126*55344Spendry 	default:
127*55344Spendry 		return (EINVAL);
128*55344Spendry 	}
129*55344Spendry 
130*55344Spendry 	*lenp = strlen(buf);
131*55344Spendry 	return (0);
132*55344Spendry }
133*55344Spendry 
134*55344Spendry static int
135*55344Spendry kernfs_xwrite(kt, buf, len)
136*55344Spendry 	struct kern_target *kt;
137*55344Spendry 	char *buf;
138*55344Spendry 	int len;
139*55344Spendry {
140*55344Spendry 	switch (kt->kt_tag) {
141*55344Spendry 	case KTT_HOSTNAME: {
142*55344Spendry 		if (buf[len-1] == '\n')
143*55344Spendry 			--len;
144*55344Spendry 		bcopy(buf, hostname, len);
145*55344Spendry 		hostnamelen = len - 1;
146*55344Spendry 		return (0);
147*55344Spendry 	}
148*55344Spendry 
149*55344Spendry 	default:
150*55344Spendry 		return (EIO);
151*55344Spendry 	}
152*55344Spendry }
153*55344Spendry 
154*55344Spendry 
155*55344Spendry /*
156*55344Spendry  * vp is the current namei directory
157*55344Spendry  * ndp is the name to locate in that directory...
158*55344Spendry  */
159*55344Spendry kernfs_lookup(ap)
160*55344Spendry 	struct vop_lookup_args /* {
161*55344Spendry 		struct vnode * a_dvp;
162*55344Spendry 		struct vnode ** a_vpp;
163*55344Spendry 		struct componentname * a_cnp;
164*55344Spendry 	} */ *ap;
165*55344Spendry {
166*55344Spendry 	struct vnode **vpp = ap->a_vpp;
167*55344Spendry 	struct vnode *dvp = ap->a_dvp;
168*55344Spendry 	struct componentname *cnp = ap->a_cnp;
169*55344Spendry 	char *pname;
170*55344Spendry 	struct proc *p;
171*55344Spendry 	int error;
172*55344Spendry 	struct vnode *fvp;
173*55344Spendry 	int i;
174*55344Spendry 
175*55344Spendry #ifdef KERNFS_DIAGNOSTIC
176*55344Spendry 	printf("kernfs_lookup(%x)\n", ap);
177*55344Spendry 	printf("kernfs_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp);
178*55344Spendry #endif
179*55344Spendry 	pname = cnp->cn_nameptr;
180*55344Spendry #ifdef KERNFS_DIAGNOSTIC
181*55344Spendry 	printf("kernfs_lookup(%s)\n", pname);
182*55344Spendry #endif
183*55344Spendry 	if (cnp->cn_namelen == 1 && *pname == '.') {
184*55344Spendry 		*vpp = dvp;
185*55344Spendry 		VREF(dvp);
186*55344Spendry 		/*VOP_LOCK(dvp);*/
187*55344Spendry 		return (0);
188*55344Spendry 	}
189*55344Spendry 
190*55344Spendry 	if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) {
191*55344Spendry 		*vpp = rootdir;
192*55344Spendry 		VREF(rootdir);
193*55344Spendry 		VOP_LOCK(rootdir);
194*55344Spendry 		return (0);
195*55344Spendry 	}
196*55344Spendry 
197*55344Spendry 	/*
198*55344Spendry 	 * /kern/rootdev is the root device
199*55344Spendry 	 */
200*55344Spendry 	if (cnp->cn_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
201*55344Spendry 		*vpp = rootvp;
202*55344Spendry 		VREF(rootvp);
203*55344Spendry 		VOP_LOCK(rootvp);
204*55344Spendry 		return (0);
205*55344Spendry 	}
206*55344Spendry 
207*55344Spendry 	for (i = 0; i < nkern_targets; i++) {
208*55344Spendry 		struct kern_target *kt = &kern_targets[i];
209*55344Spendry 		if (cnp->cn_namelen == strlen(kt->kt_name) &&
210*55344Spendry 		    bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) {
211*55344Spendry 			error = 0;
212*55344Spendry 			break;
213*55344Spendry 		}
214*55344Spendry 	}
215*55344Spendry 
216*55344Spendry #ifdef KERNFS_DIAGNOSTIC
217*55344Spendry 	printf("kernfs_lookup: i = %d, error = %d\n", i, error);
218*55344Spendry #endif
219*55344Spendry 
220*55344Spendry 	if (error)
221*55344Spendry 		goto bad;
222*55344Spendry 
223*55344Spendry #ifdef KERNFS_DIAGNOSTIC
224*55344Spendry 	printf("kernfs_lookup: allocate new vnode\n");
225*55344Spendry #endif
226*55344Spendry 	error = getnewvnode(VT_UFS, dvp->v_mount, kernfs_vnodeop_p, &fvp);
227*55344Spendry 	if (error)
228*55344Spendry 		goto bad;
229*55344Spendry 	MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP, M_WAITOK);
230*55344Spendry 	VTOKERN(fvp)->kf_kt = &kern_targets[i];
231*55344Spendry 	fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
232*55344Spendry 	*vpp = fvp;
233*55344Spendry #ifdef KERNFS_DIAGNOSTIC
234*55344Spendry 	printf("kernfs_lookup: newvp = %x\n", fvp);
235*55344Spendry #endif
236*55344Spendry 	return (0);
237*55344Spendry 
238*55344Spendry bad:;
239*55344Spendry 	*vpp = NULL;
240*55344Spendry #ifdef KERNFS_DIAGNOSTIC
241*55344Spendry 	printf("kernfs_lookup: error = %d\n", error);
242*55344Spendry #endif
243*55344Spendry 	return (error);
244*55344Spendry }
245*55344Spendry 
246*55344Spendry kernfs_open(ap)
247*55344Spendry 	struct vop_open_args /* {
248*55344Spendry 		struct vnode *a_vp;
249*55344Spendry 		int  a_mode;
250*55344Spendry 		struct ucred *a_cred;
251*55344Spendry 		struct proc *a_p;
252*55344Spendry 	} */ *ap;
253*55344Spendry {
254*55344Spendry 	struct vnode *vp = ap->a_vp;
255*55344Spendry 
256*55344Spendry 	/*
257*55344Spendry 	 * Can always open the root (modulo perms)
258*55344Spendry 	 */
259*55344Spendry 	if (vp->v_flag & VROOT)
260*55344Spendry 		return (0);
261*55344Spendry 
262*55344Spendry #ifdef KERNFS_DIAGNOSTIC
263*55344Spendry 	printf("kernfs_open, mode = %x, file = %s\n",
264*55344Spendry 			ap->a_mode, VTOKERN(vp)->kf_kt->kt_name);
265*55344Spendry #endif
266*55344Spendry 
267*55344Spendry 	if ((ap->a_mode & FWRITE) && VTOKERN(vp)->kf_kt->kt_rw != KTM_RW)
268*55344Spendry 		return (EBADF);
269*55344Spendry 
270*55344Spendry 	return (0);
271*55344Spendry }
272*55344Spendry 
273*55344Spendry static int
274*55344Spendry kernfs_access(ap)
275*55344Spendry 	struct vop_access_args /* {
276*55344Spendry 		struct vnode *a_vp;
277*55344Spendry 		int  a_mode;
278*55344Spendry 		struct ucred *a_cred;
279*55344Spendry 		struct proc *a_p;
280*55344Spendry 	} */ *ap;
281*55344Spendry {
282*55344Spendry 	struct vnode *vp = ap->a_vp;
283*55344Spendry 	struct ucred *cred = ap->a_cred;
284*55344Spendry 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
285*55344Spendry 	mode_t mode = ap->a_mode;
286*55344Spendry 
287*55344Spendry 	if (mode & VEXEC) {
288*55344Spendry 		if (vp->v_flag & VROOT)
289*55344Spendry 			return (0);
290*55344Spendry 		return (EACCES);
291*55344Spendry 	}
292*55344Spendry 
293*55344Spendry 	if (cred->cr_uid == 0) {
294*55344Spendry 		if ((mode & VWRITE) && (kt->kt_rw != KTM_RW))
295*55344Spendry 			return (EROFS);
296*55344Spendry 		return (0);
297*55344Spendry 	}
298*55344Spendry 
299*55344Spendry 	if (mode & VWRITE)
300*55344Spendry 		return (EACCES);
301*55344Spendry 
302*55344Spendry 	return (0);
303*55344Spendry }
304*55344Spendry 
305*55344Spendry 
306*55344Spendry kernfs_getattr(ap)
307*55344Spendry 	struct vop_getattr_args /* {
308*55344Spendry 		struct vnode *a_vp;
309*55344Spendry 		struct vattr *a_vap;
310*55344Spendry 		struct ucred *a_cred;
311*55344Spendry 		struct proc *a_p;
312*55344Spendry 	} */ *ap;
313*55344Spendry {
314*55344Spendry 	struct vnode *vp = ap->a_vp;
315*55344Spendry 	struct vattr *vap = ap->a_vap;
316*55344Spendry 	int error = 0;
317*55344Spendry 	char strbuf[KSTRING];
318*55344Spendry 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
319*55344Spendry 
320*55344Spendry 	bzero((caddr_t) vap, sizeof(*vap));
321*55344Spendry 	vattr_null(vap);
322*55344Spendry 	vap->va_uid = 0;
323*55344Spendry 	vap->va_gid = 0;
324*55344Spendry 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
325*55344Spendry 	/* vap->va_qsize = 0; */
326*55344Spendry 	vap->va_blocksize = DEV_BSIZE;
327*55344Spendry 	microtime(&vap->va_atime);
328*55344Spendry 	vap->va_mtime = vap->va_atime;
329*55344Spendry 	vap->va_ctime = vap->va_ctime;
330*55344Spendry 	vap->va_gen = 0;
331*55344Spendry 	vap->va_flags = 0;
332*55344Spendry 	vap->va_rdev = 0;
333*55344Spendry 	/* vap->va_qbytes = 0; */
334*55344Spendry 	vap->va_bytes = 0;
335*55344Spendry 
336*55344Spendry 	if (vp->v_flag & VROOT) {
337*55344Spendry #ifdef KERNFS_DIAGNOSTIC
338*55344Spendry 		printf("kernfs_getattr: stat rootdir\n");
339*55344Spendry #endif
340*55344Spendry 		vap->va_type = VDIR;
341*55344Spendry 		vap->va_mode = KTM_DIR_MODE;
342*55344Spendry 		vap->va_nlink = 2;
343*55344Spendry 		vap->va_fileid = 2;
344*55344Spendry 		vap->va_size = DEV_BSIZE;
345*55344Spendry 	} else {
346*55344Spendry 		int nbytes;
347*55344Spendry #ifdef KERNFS_DIAGNOSTIC
348*55344Spendry 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
349*55344Spendry #endif
350*55344Spendry 		vap->va_type = kt->kt_vtype;
351*55344Spendry 		vap->va_mode = (kt->kt_rw ? KTM_RW_MODE : KTM_RO_MODE);
352*55344Spendry 		vap->va_nlink = 1;
353*55344Spendry 		vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
354*55344Spendry 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &nbytes);
355*55344Spendry 		vap->va_size = nbytes;
356*55344Spendry 	}
357*55344Spendry 
358*55344Spendry 	vp->v_type = vap->va_type;
359*55344Spendry #ifdef KERNFS_DIAGNOSTIC
360*55344Spendry 	printf("kernfs_getattr: return error %d\n", error);
361*55344Spendry #endif
362*55344Spendry 	return (error);
363*55344Spendry }
364*55344Spendry 
365*55344Spendry kernfs_setattr(ap)
366*55344Spendry 	struct vop_setattr_args /* {
367*55344Spendry 		struct vnode *a_vp;
368*55344Spendry 		struct vattr *a_vap;
369*55344Spendry 		struct ucred *a_cred;
370*55344Spendry 		struct proc *a_p;
371*55344Spendry 	} */ *ap;
372*55344Spendry {
373*55344Spendry 
374*55344Spendry 	/*
375*55344Spendry 	 * Silently ignore attribute changes.
376*55344Spendry 	 * This allows for open with truncate to have no
377*55344Spendry 	 * effect until some data is written.  I want to
378*55344Spendry 	 * do it this way because all writes are atomic.
379*55344Spendry 	 */
380*55344Spendry 	return (0);
381*55344Spendry }
382*55344Spendry 
383*55344Spendry static int
384*55344Spendry kernfs_read(ap)
385*55344Spendry 	struct vop_read_args /* {
386*55344Spendry 		struct vnode *a_vp;
387*55344Spendry 		struct uio *a_uio;
388*55344Spendry 		int  a_ioflag;
389*55344Spendry 		struct ucred *a_cred;
390*55344Spendry 	} */ *ap;
391*55344Spendry {
392*55344Spendry 	struct vnode *vp = ap->a_vp;
393*55344Spendry 	struct uio *uio = ap->a_uio;
394*55344Spendry 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
395*55344Spendry 	char strbuf[KSTRING];
396*55344Spendry 	int off = uio->uio_offset;
397*55344Spendry 	int len = 0;
398*55344Spendry 	char *cp = strbuf;
399*55344Spendry 	int error;
400*55344Spendry #ifdef KERNFS_DIAGNOSTIC
401*55344Spendry 	printf("kern_read %s\n", kt->kt_name);
402*55344Spendry #endif
403*55344Spendry 
404*55344Spendry 	error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
405*55344Spendry 	if (error)
406*55344Spendry 		return (error);
407*55344Spendry 	cp = strbuf + off;
408*55344Spendry 	len -= off;
409*55344Spendry 	return (uiomove(cp, len, uio));
410*55344Spendry }
411*55344Spendry 
412*55344Spendry static int
413*55344Spendry kernfs_write(ap)
414*55344Spendry 	struct vop_write_args /* {
415*55344Spendry 		struct vnode *a_vp;
416*55344Spendry 		struct uio *a_uio;
417*55344Spendry 		int  a_ioflag;
418*55344Spendry 		struct ucred *a_cred;
419*55344Spendry 	} */ *ap;
420*55344Spendry {
421*55344Spendry 	struct vnode *vp = ap->a_vp;
422*55344Spendry 	struct uio *uio = ap->a_uio;
423*55344Spendry 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
424*55344Spendry 	char strbuf[KSTRING];
425*55344Spendry 	int len = uio->uio_resid;
426*55344Spendry 	char *cp = strbuf;
427*55344Spendry 	int xlen;
428*55344Spendry 	int error;
429*55344Spendry 
430*55344Spendry 	if (uio->uio_offset != 0)
431*55344Spendry 		return (EINVAL);
432*55344Spendry 
433*55344Spendry 	xlen = min(uio->uio_resid, KSTRING-1);
434*55344Spendry 	error = uiomove(strbuf, xlen, uio);
435*55344Spendry 	if (error)
436*55344Spendry 		return (error);
437*55344Spendry 
438*55344Spendry 	if (uio->uio_resid != 0)
439*55344Spendry 		return (EIO);
440*55344Spendry 
441*55344Spendry 	strbuf[xlen] = '\0';
442*55344Spendry 	return (kernfs_xwrite(kt, strbuf, xlen));
443*55344Spendry }
444*55344Spendry 
445*55344Spendry 
446*55344Spendry kernfs_readdir(ap)
447*55344Spendry 	struct vop_readdir_args /* {
448*55344Spendry 		struct vnode *a_vp;
449*55344Spendry 		struct uio *a_uio;
450*55344Spendry 		struct ucred *a_cred;
451*55344Spendry 	} */ *ap;
452*55344Spendry {
453*55344Spendry 	struct uio *uio = ap->a_uio;
454*55344Spendry 	int i;
455*55344Spendry 	int error;
456*55344Spendry 
457*55344Spendry 	i = uio->uio_offset / UIO_MX;
458*55344Spendry 	error = 0;
459*55344Spendry 	while (uio->uio_resid > 0 && i < nkern_targets) {
460*55344Spendry 		struct dirent d;
461*55344Spendry 		struct dirent *dp = &d;
462*55344Spendry 		struct kern_target *kt = &kern_targets[i];
463*55344Spendry #ifdef KERNFS_DIAGNOSTIC
464*55344Spendry 		printf("kernfs_readdir: i = %d\n", i);
465*55344Spendry #endif
466*55344Spendry 
467*55344Spendry 		bzero((caddr_t) dp, UIO_MX);
468*55344Spendry 
469*55344Spendry 		dp->d_namlen = strlen(kt->kt_name);
470*55344Spendry 		bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
471*55344Spendry 
472*55344Spendry #ifdef KERNFS_DIAGNOSTIC
473*55344Spendry 		printf("kernfs_readdir: name = %s, len = %d\n",
474*55344Spendry 				dp->d_name, dp->d_namlen);
475*55344Spendry #endif
476*55344Spendry 		/*
477*55344Spendry 		 * Fill in the remaining fields
478*55344Spendry 		 */
479*55344Spendry 		dp->d_reclen = UIO_MX;
480*55344Spendry 		dp->d_fileno = i + 3;
481*55344Spendry 		dp->d_type = DT_UNKNOWN;	/* XXX */
482*55344Spendry 		/*
483*55344Spendry 		 * And ship to userland
484*55344Spendry 		 */
485*55344Spendry 		error = uiomove((caddr_t) dp, UIO_MX, uio);
486*55344Spendry 		if (error)
487*55344Spendry 			break;
488*55344Spendry 		i++;
489*55344Spendry 	}
490*55344Spendry 
491*55344Spendry 	uio->uio_offset = i * UIO_MX;
492*55344Spendry 
493*55344Spendry 	return (error);
494*55344Spendry }
495*55344Spendry 
496*55344Spendry kernfs_inactive(ap)
497*55344Spendry 	struct vop_inactive_args /* {
498*55344Spendry 		struct vnode *a_vp;
499*55344Spendry 	} */ *ap;
500*55344Spendry {
501*55344Spendry 	struct vnode *vp = ap->a_vp;
502*55344Spendry 
503*55344Spendry 	/*
504*55344Spendry 	 * Clear out the v_type field to avoid
505*55344Spendry 	 * nasty things happening in vgone().
506*55344Spendry 	 */
507*55344Spendry 	vp->v_type = VNON;
508*55344Spendry #ifdef KERNFS_DIAGNOSTIC
509*55344Spendry 	printf("kernfs_inactive(%x)\n", vp);
510*55344Spendry #endif
511*55344Spendry 	return (0);
512*55344Spendry }
513*55344Spendry 
514*55344Spendry kernfs_reclaim(ap)
515*55344Spendry 	struct vop_reclaim_args /* {
516*55344Spendry 		struct vnode *a_vp;
517*55344Spendry 	} */ *ap;
518*55344Spendry {
519*55344Spendry 	struct vnode *vp = ap->a_vp;
520*55344Spendry 	printf("kernfs_reclaim(%x)\n", vp);
521*55344Spendry 	if (vp->v_data) {
522*55344Spendry 		FREE(vp->v_data, M_TEMP);
523*55344Spendry 		vp->v_data = 0;
524*55344Spendry 	}
525*55344Spendry 	return (0);
526*55344Spendry }
527*55344Spendry 
528*55344Spendry /*
529*55344Spendry  * Print out the contents of a /dev/fd vnode.
530*55344Spendry  */
531*55344Spendry /* ARGSUSED */
532*55344Spendry kernfs_print(ap)
533*55344Spendry 	struct vop_print_args /* {
534*55344Spendry 		struct vnode *a_vp;
535*55344Spendry 	} */ *ap;
536*55344Spendry {
537*55344Spendry 
538*55344Spendry 	printf("tag VT_NON, kernfs vnode\n");
539*55344Spendry 	return (0);
540*55344Spendry }
541*55344Spendry 
542*55344Spendry /*void*/
543*55344Spendry kernfs_vfree(ap)
544*55344Spendry 	struct vop_vfree_args /* {
545*55344Spendry 		struct vnode *a_pvp;
546*55344Spendry 		ino_t a_ino;
547*55344Spendry 		int a_mode;
548*55344Spendry 	} */ *ap;
549*55344Spendry {
550*55344Spendry 
551*55344Spendry 	return (0);
552*55344Spendry }
553*55344Spendry 
554*55344Spendry /*
555*55344Spendry  * /dev/fd vnode unsupported operation
556*55344Spendry  */
557*55344Spendry kernfs_enotsupp()
558*55344Spendry {
559*55344Spendry 
560*55344Spendry 	return (EOPNOTSUPP);
561*55344Spendry }
562*55344Spendry 
563*55344Spendry /*
564*55344Spendry  * /dev/fd "should never get here" operation
565*55344Spendry  */
566*55344Spendry kernfs_badop()
567*55344Spendry {
568*55344Spendry 
569*55344Spendry 	panic("kernfs: bad op");
570*55344Spendry 	/* NOTREACHED */
571*55344Spendry }
572*55344Spendry 
573*55344Spendry /*
574*55344Spendry  * /dev/fd vnode null operation
575*55344Spendry  */
576*55344Spendry kernfs_nullop()
577*55344Spendry {
578*55344Spendry 
579*55344Spendry 	return (0);
580*55344Spendry }
581*55344Spendry 
582*55344Spendry #define kernfs_create ((int (*) __P((struct  vop_create_args *)))kernfs_enotsupp)
583*55344Spendry #define kernfs_mknod ((int (*) __P((struct  vop_mknod_args *)))kernfs_enotsupp)
584*55344Spendry #define kernfs_close ((int (*) __P((struct  vop_close_args *)))nullop)
585*55344Spendry #define kernfs_ioctl ((int (*) __P((struct  vop_ioctl_args *)))kernfs_enotsupp)
586*55344Spendry #define kernfs_select ((int (*) __P((struct  vop_select_args *)))kernfs_enotsupp)
587*55344Spendry #define kernfs_mmap ((int (*) __P((struct  vop_mmap_args *)))kernfs_enotsupp)
588*55344Spendry #define kernfs_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
589*55344Spendry #define kernfs_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
590*55344Spendry #define kernfs_remove ((int (*) __P((struct  vop_remove_args *)))kernfs_enotsupp)
591*55344Spendry #define kernfs_link ((int (*) __P((struct  vop_link_args *)))kernfs_enotsupp)
592*55344Spendry #define kernfs_rename ((int (*) __P((struct  vop_rename_args *)))kernfs_enotsupp)
593*55344Spendry #define kernfs_mkdir ((int (*) __P((struct  vop_mkdir_args *)))kernfs_enotsupp)
594*55344Spendry #define kernfs_rmdir ((int (*) __P((struct  vop_rmdir_args *)))kernfs_enotsupp)
595*55344Spendry #define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp)
596*55344Spendry #define kernfs_readlink \
597*55344Spendry 	((int (*) __P((struct  vop_readlink_args *)))kernfs_enotsupp)
598*55344Spendry #define kernfs_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
599*55344Spendry #define kernfs_lock ((int (*) __P((struct  vop_lock_args *)))nullop)
600*55344Spendry #define kernfs_unlock ((int (*) __P((struct  vop_unlock_args *)))nullop)
601*55344Spendry #define kernfs_bmap ((int (*) __P((struct  vop_bmap_args *)))kernfs_badop)
602*55344Spendry #define kernfs_strategy ((int (*) __P((struct  vop_strategy_args *)))kernfs_badop)
603*55344Spendry #define kernfs_islocked ((int (*) __P((struct  vop_islocked_args *)))nullop)
604*55344Spendry #define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))kernfs_enotsupp)
605*55344Spendry #define kernfs_blkatoff \
606*55344Spendry 	((int (*) __P((struct  vop_blkatoff_args *)))kernfs_enotsupp)
607*55344Spendry #define kernfs_valloc ((int(*) __P(( \
608*55344Spendry 		struct vnode *pvp, \
609*55344Spendry 		int mode, \
610*55344Spendry 		struct ucred *cred, \
611*55344Spendry 		struct vnode **vpp))) kernfs_enotsupp)
612*55344Spendry #define kernfs_truncate \
613*55344Spendry 	((int (*) __P((struct  vop_truncate_args *)))kernfs_enotsupp)
614*55344Spendry #define kernfs_update ((int (*) __P((struct  vop_update_args *)))kernfs_enotsupp)
615*55344Spendry #define kernfs_bwrite ((int (*) __P((struct  vop_bwrite_args *)))kernfs_enotsupp)
616*55344Spendry 
617*55344Spendry int (**kernfs_vnodeop_p)();
618*55344Spendry struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = {
619*55344Spendry 	{ &vop_default_desc, vn_default_error },
620*55344Spendry 	{ &vop_lookup_desc, kernfs_lookup },	/* lookup */
621*55344Spendry 	{ &vop_create_desc, kernfs_create },	/* create */
622*55344Spendry 	{ &vop_mknod_desc, kernfs_mknod },	/* mknod */
623*55344Spendry 	{ &vop_open_desc, kernfs_open },		/* open */
624*55344Spendry 	{ &vop_close_desc, kernfs_close },	/* close */
625*55344Spendry 	{ &vop_access_desc, kernfs_access },	/* access */
626*55344Spendry 	{ &vop_getattr_desc, kernfs_getattr },	/* getattr */
627*55344Spendry 	{ &vop_setattr_desc, kernfs_setattr },	/* setattr */
628*55344Spendry 	{ &vop_read_desc, kernfs_read },		/* read */
629*55344Spendry 	{ &vop_write_desc, kernfs_write },	/* write */
630*55344Spendry 	{ &vop_ioctl_desc, kernfs_ioctl },	/* ioctl */
631*55344Spendry 	{ &vop_select_desc, kernfs_select },	/* select */
632*55344Spendry 	{ &vop_mmap_desc, kernfs_mmap },		/* mmap */
633*55344Spendry 	{ &vop_fsync_desc, kernfs_fsync },	/* fsync */
634*55344Spendry 	{ &vop_seek_desc, kernfs_seek },		/* seek */
635*55344Spendry 	{ &vop_remove_desc, kernfs_remove },	/* remove */
636*55344Spendry 	{ &vop_link_desc, kernfs_link },		/* link */
637*55344Spendry 	{ &vop_rename_desc, kernfs_rename },	/* rename */
638*55344Spendry 	{ &vop_mkdir_desc, kernfs_mkdir },	/* mkdir */
639*55344Spendry 	{ &vop_rmdir_desc, kernfs_rmdir },	/* rmdir */
640*55344Spendry 	{ &vop_symlink_desc, kernfs_symlink },	/* symlink */
641*55344Spendry 	{ &vop_readdir_desc, kernfs_readdir },	/* readdir */
642*55344Spendry 	{ &vop_readlink_desc, kernfs_readlink },	/* readlink */
643*55344Spendry 	{ &vop_abortop_desc, kernfs_abortop },	/* abortop */
644*55344Spendry 	{ &vop_inactive_desc, kernfs_inactive },	/* inactive */
645*55344Spendry 	{ &vop_reclaim_desc, kernfs_reclaim },	/* reclaim */
646*55344Spendry 	{ &vop_lock_desc, kernfs_lock },		/* lock */
647*55344Spendry 	{ &vop_unlock_desc, kernfs_unlock },	/* unlock */
648*55344Spendry 	{ &vop_bmap_desc, kernfs_bmap },		/* bmap */
649*55344Spendry 	{ &vop_strategy_desc, kernfs_strategy },	/* strategy */
650*55344Spendry 	{ &vop_print_desc, kernfs_print },	/* print */
651*55344Spendry 	{ &vop_islocked_desc, kernfs_islocked },	/* islocked */
652*55344Spendry 	{ &vop_advlock_desc, kernfs_advlock },	/* advlock */
653*55344Spendry 	{ &vop_blkatoff_desc, kernfs_blkatoff },	/* blkatoff */
654*55344Spendry 	{ &vop_valloc_desc, kernfs_valloc },	/* valloc */
655*55344Spendry 	{ &vop_vfree_desc, kernfs_vfree },	/* vfree */
656*55344Spendry 	{ &vop_truncate_desc, kernfs_truncate },	/* truncate */
657*55344Spendry 	{ &vop_update_desc, kernfs_update },	/* update */
658*55344Spendry 	{ &vop_bwrite_desc, kernfs_bwrite },	/* bwrite */
659*55344Spendry 	{ (struct vnodeop_desc*)NULL, (int(*)())NULL }
660*55344Spendry };
661*55344Spendry struct vnodeopv_desc kernfs_vnodeop_opv_desc =
662*55344Spendry 	{ &kernfs_vnodeop_p, kernfs_vnodeop_entries };
663