xref: /netbsd-src/sys/miscfs/kernfs/kernfs_vnops.c (revision 811e6386f8c5e4a3521c7003da29ec8673e344fa)
1 /*
2  * Copyright (c) 1990, 1992 Jan-Simon Pendry
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Jan-Simon Pendry.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * $Id: kernfs_vnops.c,v 1.4 1993/03/27 00:37:11 cgd Exp $
37  */
38 
39 /*
40  * Kernel parameter filesystem
41  */
42 
43 #include "param.h"
44 #include "systm.h"
45 #include "kernel.h"
46 #include "types.h"
47 #include "time.h"
48 #include "proc.h"
49 #include "file.h"
50 #include "vnode.h"
51 #include "stat.h"
52 #include "mount.h"
53 #include "namei.h"
54 #include "buf.h"
55 #include "miscfs/kernfs/kernfs.h"
56 
57 #include "../ufs/dir.h"		/* For readdir() XXX */
58 
59 #define KSTRING	256		/* Largest I/O available via this filesystem */
60 #define	UIO_MX 32
61 
62 struct kern_target {
63 	char *kt_name;
64 	void *kt_data;
65 #define	KTT_NULL 1
66 #define	KTT_TIME 5
67 #define KTT_INT	17
68 #define	KTT_STRING 31
69 #define KTT_HOSTNAME 47
70 #define KTT_AVENRUN 53
71 	int kt_tag;
72 #define	KTM_RO	0
73 #define	KTM_RO_MODE		(S_IRUSR|S_IRGRP|S_IROTH)
74 #define	KTM_RW	43
75 #define	KTM_RW_MODE		(S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)
76 #define KTM_DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
77 	int kt_rw;
78 	int kt_vtype;
79 } kern_targets[] = {
80 /* NOTE: The name must be less than UIO_MX-16 chars in length */
81 	/* name		data		tag		ro/rw */
82 	{ ".",		0,		KTT_NULL,	KTM_RO,	VDIR },
83 	{ "..",		0,		KTT_NULL,	KTM_RO,	VDIR },
84 	{ "copyright",	copyright,	KTT_STRING,	KTM_RO,	VREG },
85 	{ "hostname",	0,		KTT_HOSTNAME,	KTM_RW,	VREG },
86 	{ "hz",		&hz,		KTT_INT,	KTM_RO,	VREG },
87 	{ "loadavg",	0,		KTT_AVENRUN,	KTM_RO,	VREG },
88 	{ "physmem",	&physmem,	KTT_INT,	KTM_RO,	VREG },
89 	{ "root",	0,		KTT_NULL,	KTM_RO,	VDIR },
90 	{ "rootdev",	0,		KTT_NULL,	KTM_RO,	VBLK },
91 	{ "rrootdev",	0,		KTT_NULL,	KTM_RO,	VCHR },
92 	{ "time",	0,		KTT_TIME,	KTM_RO,	VREG },
93 	{ "version",	version,	KTT_STRING,	KTM_RO,	VREG },
94 };
95 
96 static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]);
97 
98 static int
99 kernfs_xread(kt, buf, len, lenp)
100 	struct kern_target *kt;
101 	char *buf;
102 	int len;
103 	int *lenp;
104 {
105 	int xlen;
106 
107 	switch (kt->kt_tag) {
108 	case KTT_TIME: {
109 		struct timeval tv;
110 		microtime(&tv);
111 		sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec);
112 		break;
113 	}
114 
115 	case KTT_INT: {
116 		int *ip = kt->kt_data;
117 		sprintf(buf, "%d\n", *ip);
118 		break;
119 	}
120 
121 	case KTT_STRING: {
122 		char *cp = kt->kt_data;
123 		int xlen = strlen(cp) + 1;
124 
125 		if (xlen >= len)
126 			return (EINVAL);
127 
128 		bcopy(cp, buf, xlen);
129 		break;
130 	}
131 
132 	case KTT_HOSTNAME: {
133 		char *cp = hostname;
134 		int xlen = hostnamelen;
135 
136 		if (xlen >= len)
137 			return (EINVAL);
138 
139 		sprintf(buf, "%s\n", cp);
140 		break;
141 	}
142 
143 	case KTT_AVENRUN:
144 		sprintf(buf, "%d %d %d %d\n",
145 				averunnable[0],
146 				averunnable[1],
147 				averunnable[2],
148 				FSCALE);
149 		break;
150 
151 	default:
152 		return (EINVAL);
153 	}
154 
155 	*lenp = strlen(buf);
156 	return (0);
157 }
158 
159 static int
160 kernfs_xwrite(kt, buf, len)
161 	struct kern_target *kt;
162 	char *buf;
163 	int len;
164 {
165 	switch (kt->kt_tag) {
166 	case KTT_HOSTNAME: {
167 		if (buf[len-1] == '\n')
168 			--len;
169 		bcopy(buf, hostname, len);
170 		hostnamelen = len - 1;
171 		return (0);
172 	}
173 
174 	default:
175 		return (EIO);
176 	}
177 }
178 
179 /*
180  * vp is the current namei directory
181  * ndp is the name to locate in that directory...
182  */
183 kernfs_lookup(dvp, ndp, p)
184 	struct vnode *dvp;
185 	struct nameidata *ndp;
186 	struct proc *p;
187 {
188 	char *pname = ndp->ni_ptr;
189 	int error = ENOENT;
190 	int i;
191 	struct vnode *fvp;
192 
193 #ifdef KERNFS_DIAGNOSTIC
194 	printf("kernfs_lookup(%s)\n", pname);
195 #endif
196 	if (ndp->ni_namelen == 1 && *pname == '.') {
197 		ndp->ni_dvp = dvp;
198 		ndp->ni_vp = dvp;
199 		VREF(dvp);
200 		/*VOP_LOCK(dvp);*/
201 		return (0);
202 	}
203 
204 	if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) {
205 		ndp->ni_dvp = dvp;
206 		ndp->ni_vp = rootdir;
207 		VREF(rootdir);
208 		VOP_LOCK(rootdir);
209 		return (0);
210 	}
211 
212 	/*
213 	 * /kern/rootdev is the root device
214 	 */
215 	if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) {
216 		if (vfinddev(rootdev, VBLK, &fvp))
217 			return (ENXIO);
218 		ndp->ni_dvp = dvp;
219 		ndp->ni_vp = fvp;
220 		VREF(fvp);
221 		VOP_LOCK(fvp);
222 		return (0);
223 	}
224 
225 	/*
226 	 * /kern/rrootdev is the root device
227 	 */
228 	if (ndp->ni_namelen == 8 && bcmp(pname, "rrootdev", 7) == 0) {
229 		ndp->ni_dvp = dvp;
230 		ndp->ni_vp = rrootdevvp;
231 		VREF(rrootdevvp);
232 		VOP_LOCK(rrootdevvp);
233 		return (0);
234 	}
235 
236 	for (i = 0; i < nkern_targets; i++) {
237 		struct kern_target *kt = &kern_targets[i];
238 		if (ndp->ni_namelen == strlen(kt->kt_name) &&
239 		    bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) {
240 			error = 0;
241 			break;
242 		}
243 	}
244 
245 #ifdef KERNFS_DIAGNOSTIC
246 	printf("kernfs_lookup: i = %d, error = %d\n", i, error);
247 #endif
248 
249 	if (error)
250 		goto bad;
251 
252 #ifdef KERNFS_DIAGNOSTIC
253 	printf("kernfs_lookup: allocate new vnode\n");
254 #endif
255 	error = getnewvnode(VT_UFS, dvp->v_mount, &kernfs_vnodeops, &fvp);
256 	if (error)
257 		goto bad;
258 	VTOKERN(fvp)->kf_kt = &kern_targets[i];
259 	fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype;
260 	ndp->ni_dvp = dvp;
261 	ndp->ni_vp = fvp;
262 #ifdef KERNFS_DIAGNOSTIC
263 	printf("kernfs_lookup: newvp = %x\n", fvp);
264 #endif
265 	return (0);
266 
267 bad:;
268 	ndp->ni_dvp = dvp;
269 	ndp->ni_vp = NULL;
270 #ifdef KERNFS_DIAGNOSTIC
271 	printf("kernfs_lookup: error = %d\n", error);
272 #endif
273 	return (error);
274 }
275 
276 kernfs_open(vp, mode, cred, p)
277 	struct vnode *vp;
278 	int mode;
279 	struct ucred *cred;
280 	struct proc *p;
281 {
282 	int error;
283 	struct filedesc *fdp;
284 	struct file *fp;
285 	int dfd;
286 	int fd;
287 
288 #ifdef KERNFS_DIAGNOSTIC
289 	printf("kernfs_open\n");
290 #endif
291 
292 	/*
293 	 * Can always open the root (modulo perms)
294 	 */
295 	if (vp->v_flag & VROOT)
296 		return (0);
297 
298 #ifdef KERNFS_DIAGNOSTIC
299 	printf("kernfs_open, mode = %x, file = %s\n",
300 			mode, VTOKERN(vp)->kf_kt->kt_name);
301 #endif
302 
303 	if ((mode & FWRITE) && VTOKERN(vp)->kf_kt->kt_rw != KTM_RW)
304 		return (EBADF);
305 
306 	return (0);
307 }
308 
309 kernfs_getattr(vp, vap, cred, p)
310 	struct vnode *vp;
311 	struct vattr *vap;
312 	struct ucred *cred;
313 	struct proc *p;
314 {
315 	int error = 0;
316 	char strbuf[KSTRING];
317 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
318 
319 	bzero((caddr_t) vap, sizeof(*vap));
320 	vattr_null(vap);
321 	vap->va_uid = 0;
322 	vap->va_gid = 0;
323 	vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
324 	/* vap->va_qsize = 0; */
325 	vap->va_blocksize = DEV_BSIZE;
326 	microtime(&vap->va_atime);
327 	vap->va_mtime = vap->va_atime;
328 	vap->va_ctime = vap->va_ctime;
329 	vap->va_gen = 0;
330 	vap->va_flags = 0;
331 	vap->va_rdev = 0;
332 	/* vap->va_qbytes = 0; */
333 	vap->va_bytes = 0;
334 
335 	if (vp->v_flag & VROOT) {
336 #ifdef KERNFS_DIAGNOSTIC
337 		printf("kernfs_getattr: stat rootdir\n");
338 #endif
339 		vap->va_type = VDIR;
340 		vap->va_mode = KTM_DIR_MODE;
341 		vap->va_nlink = 2;
342 		vap->va_fileid = 2;
343 		vap->va_size = DEV_BSIZE;
344 	} else {
345 #ifdef KERNFS_DIAGNOSTIC
346 		printf("kernfs_getattr: stat target %s\n", kt->kt_name);
347 #endif
348 		vap->va_type = kt->kt_vtype;
349 		vap->va_mode = (kt->kt_rw ? KTM_RW_MODE : KTM_RO_MODE);
350 		vap->va_nlink = 1;
351 		vap->va_fileid = 3 + (kt - kern_targets) / sizeof(*kt);
352 		error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size);
353 	}
354 
355 	vp->v_type = vap->va_type;
356 #ifdef KERNFS_DIAGNOSTIC
357 	printf("kernfs_getattr: return error %d\n", error);
358 #endif
359 	return (error);
360 }
361 
362 kernfs_setattr(vp, vap, cred, p)
363 	struct vnode *vp;
364 	struct vattr *vap;
365 	struct ucred *cred;
366 	struct proc *p;
367 {
368 
369 	/*
370 	 * Silently ignore attribute changes.
371 	 * This allows for open with truncate to have no
372 	 * effect until some data is written.  I want to
373 	 * do it this way because all writes are atomic.
374 	 */
375 	return (0);
376 }
377 
378 static int
379 kernfs_read(vp, uio, ioflag, cred)
380 	struct vnode *vp;
381 	struct uio *uio;
382 	int ioflag;
383 	struct ucred *cred;
384 {
385 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
386 	char strbuf[KSTRING];
387 	int off = uio->uio_offset;
388 	int len = 0;
389 	char *cp = strbuf;
390 	int error;
391 #ifdef KERNFS_DIAGNOSTIC
392 	printf("kern_read %s\n", kt->kt_name);
393 #endif
394 
395 	error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len);
396 	if (error)
397 		return (error);
398 	cp = strbuf + off;
399 	len -= off;
400 	return (uiomove(cp, len, uio));
401 }
402 
403 static int
404 kernfs_write(vp, uio, ioflag, cred)
405 	struct vnode *vp;
406 	struct uio *uio;
407 	int ioflag;
408 	struct ucred *cred;
409 {
410 	struct kern_target *kt = VTOKERN(vp)->kf_kt;
411 	char strbuf[KSTRING];
412 	int len = uio->uio_resid;
413 	char *cp = strbuf;
414 	int xlen;
415 	int error;
416 
417 	if (uio->uio_offset != 0)
418 		return (EINVAL);
419 
420 	xlen = min(uio->uio_resid, KSTRING-1);
421 	error = uiomove(strbuf, xlen, uio);
422 	if (error)
423 		return (error);
424 
425 	if (uio->uio_resid != 0)
426 		return (EIO);
427 
428 	strbuf[xlen] = '\0';
429 	return (kernfs_xwrite(kt, strbuf, xlen));
430 }
431 
432 kernfs_readdir(vp, uio, cred, eofflagp)
433 	struct vnode *vp;
434 	struct uio *uio;
435 	struct ucred *cred;
436 	int *eofflagp;
437 {
438 	struct filedesc *fdp;
439 	int i;
440 	int error;
441 
442 	i = uio->uio_offset / UIO_MX;
443 	error = 0;
444 	while (uio->uio_resid > 0) {
445 #ifdef KERNFS_DIAGNOSTIC
446 		printf("kernfs_readdir: i = %d\n", i);
447 #endif
448 		if (i >= nkern_targets) {
449 			*eofflagp = 1;
450 			break;
451 		}
452 		{
453 			struct direct d;
454 			struct direct *dp = &d;
455 			struct kern_target *kt = &kern_targets[i];
456 
457 			bzero((caddr_t) dp, UIO_MX);
458 
459 			dp->d_namlen = strlen(kt->kt_name);
460 			bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1);
461 
462 #ifdef KERNFS_DIAGNOSTIC
463 			printf("kernfs_readdir: name = %s, len = %d\n",
464 					dp->d_name, dp->d_namlen);
465 #endif
466 			/*
467 			 * Fill in the remaining fields
468 			 */
469 			dp->d_reclen = UIO_MX;
470 			dp->d_ino = i + 3;
471 			/*
472 			 * And ship to userland
473 			 */
474 			error = uiomove((caddr_t) dp, UIO_MX, uio);
475 			if (error)
476 				break;
477 		}
478 		i++;
479 	}
480 
481 	uio->uio_offset = i * UIO_MX;
482 
483 	return (error);
484 }
485 
486 kernfs_inactive(vp, p)
487 	struct vnode *vp;
488 	struct proc *p;
489 {
490 	/*
491 	 * Clear out the v_type field to avoid
492 	 * nasty things happening in vgone().
493 	 */
494 	vp->v_type = VNON;
495 #ifdef KERNFS_DIAGNOSTIC
496 	printf("kernfs_inactive(%x)\n", vp);
497 #endif
498 	return (0);
499 }
500 
501 /*
502  * Print out the contents of a kernfs vnode.
503  */
504 /* ARGSUSED */
505 kernfs_print(vp)
506 	struct vnode *vp;
507 {
508 	printf("tag VT_NON, kernfs vnode\n");
509 }
510 
511 /*
512  * kernfs vnode unsupported operation
513  */
514 kernfs_enotsupp()
515 {
516 	return (EOPNOTSUPP);
517 }
518 
519 /*
520  * kernfs "should never get here" operation
521  */
522 kernfs_badop()
523 {
524 	panic("kernfs: bad op");
525 	/* NOTREACHED */
526 }
527 
528 /*
529  * kernfs vnode null operation
530  */
531 kernfs_nullop()
532 {
533 	return (0);
534 }
535 
536 #define kernfs_create ((int (*) __P(( \
537 		struct nameidata *ndp, \
538 		struct vattr *vap, \
539 		struct proc *p))) kernfs_enotsupp)
540 #define kernfs_mknod ((int (*) __P(( \
541 		struct nameidata *ndp, \
542 		struct vattr *vap, \
543 		struct ucred *cred, \
544 		struct proc *p))) kernfs_enotsupp)
545 #define kernfs_close ((int (*) __P(( \
546 		struct vnode *vp, \
547 		int fflag, \
548 		struct ucred *cred, \
549 		struct proc *p))) nullop)
550 #define kernfs_access ((int (*) __P(( \
551 		struct vnode *vp, \
552 		int mode, \
553 		struct ucred *cred, \
554 		struct proc *p))) nullop)
555 #define	kernfs_ioctl ((int (*) __P(( \
556 		struct vnode *vp, \
557 		int command, \
558 		caddr_t data, \
559 		int fflag, \
560 		struct ucred *cred, \
561 		struct proc *p))) kernfs_enotsupp)
562 #define	kernfs_select ((int (*) __P(( \
563 		struct vnode *vp, \
564 		int which, \
565 		int fflags, \
566 		struct ucred *cred, \
567 		struct proc *p))) kernfs_enotsupp)
568 #define kernfs_mmap ((int (*) __P(( \
569 		struct vnode *vp, \
570 		int fflags, \
571 		struct ucred *cred, \
572 		struct proc *p))) kernfs_enotsupp)
573 #define kernfs_fsync ((int (*) __P(( \
574 		struct vnode *vp, \
575 		int fflags, \
576 		struct ucred *cred, \
577 		int waitfor, \
578 		struct proc *p))) nullop)
579 #define kernfs_seek ((int (*) __P(( \
580 		struct vnode *vp, \
581 		off_t oldoff, \
582 		off_t newoff, \
583 		struct ucred *cred))) nullop)
584 #define kernfs_remove ((int (*) __P(( \
585 		struct nameidata *ndp, \
586 		struct proc *p))) kernfs_enotsupp)
587 #define kernfs_link ((int (*) __P(( \
588 		struct vnode *vp, \
589 		struct nameidata *ndp, \
590 		struct proc *p))) kernfs_enotsupp)
591 #define kernfs_rename ((int (*) __P(( \
592 		struct nameidata *fndp, \
593 		struct nameidata *tdnp, \
594 		struct proc *p))) kernfs_enotsupp)
595 #define kernfs_mkdir ((int (*) __P(( \
596 		struct nameidata *ndp, \
597 		struct vattr *vap, \
598 		struct proc *p))) kernfs_enotsupp)
599 #define kernfs_rmdir ((int (*) __P(( \
600 		struct nameidata *ndp, \
601 		struct proc *p))) kernfs_enotsupp)
602 #define kernfs_symlink ((int (*) __P(( \
603 		struct nameidata *ndp, \
604 		struct vattr *vap, \
605 		char *target, \
606 		struct proc *p))) kernfs_enotsupp)
607 #define kernfs_readlink ((int (*) __P(( \
608 		struct vnode *vp, \
609 		struct uio *uio, \
610 		struct ucred *cred))) kernfs_enotsupp)
611 #define kernfs_abortop ((int (*) __P(( \
612 		struct nameidata *ndp))) nullop)
613 #ifdef KERNFS_DIAGNOSTIC
614 int kernfs_reclaim(vp)
615 struct vnode *vp;
616 {
617 	printf("kernfs_reclaim(%x)\n", vp);
618 	return (0);
619 }
620 #else
621 #define kernfs_reclaim ((int (*) __P(( \
622 		struct vnode *vp))) nullop)
623 #endif
624 #define	kernfs_lock ((int (*) __P(( \
625 		struct vnode *vp))) nullop)
626 #define kernfs_unlock ((int (*) __P(( \
627 		struct vnode *vp))) nullop)
628 #define	kernfs_bmap ((int (*) __P(( \
629 		struct vnode *vp, \
630 		daddr_t bn, \
631 		struct vnode **vpp, \
632 		daddr_t *bnp))) kernfs_badop)
633 #define	kernfs_strategy ((int (*) __P(( \
634 		struct buf *bp))) kernfs_badop)
635 #define kernfs_islocked ((int (*) __P(( \
636 		struct vnode *vp))) nullop)
637 #define kernfs_advlock ((int (*) __P(( \
638 		struct vnode *vp, \
639 		caddr_t id, \
640 		int op, \
641 		struct flock *fl, \
642 		int flags))) kernfs_enotsupp)
643 
644 struct vnodeops kernfs_vnodeops = {
645 	kernfs_lookup,	/* lookup */
646 	kernfs_create,	/* create */
647 	kernfs_mknod,	/* mknod */
648 	kernfs_open,	/* open */
649 	kernfs_close,	/* close */
650 	kernfs_access,	/* access */
651 	kernfs_getattr,	/* getattr */
652 	kernfs_setattr,	/* setattr */
653 	kernfs_read,	/* read */
654 	kernfs_write,	/* write */
655 	kernfs_ioctl,	/* ioctl */
656 	kernfs_select,	/* select */
657 	kernfs_mmap,	/* mmap */
658 	kernfs_fsync,	/* fsync */
659 	kernfs_seek,	/* seek */
660 	kernfs_remove,	/* remove */
661 	kernfs_link,	/* link */
662 	kernfs_rename,	/* rename */
663 	kernfs_mkdir,	/* mkdir */
664 	kernfs_rmdir,	/* rmdir */
665 	kernfs_symlink,	/* symlink */
666 	kernfs_readdir,	/* readdir */
667 	kernfs_readlink,	/* readlink */
668 	kernfs_abortop,	/* abortop */
669 	kernfs_inactive,	/* inactive */
670 	kernfs_reclaim,	/* reclaim */
671 	kernfs_lock,	/* lock */
672 	kernfs_unlock,	/* unlock */
673 	kernfs_bmap,	/* bmap */
674 	kernfs_strategy,	/* strategy */
675 	kernfs_print,	/* print */
676 	kernfs_islocked,	/* islocked */
677 	kernfs_advlock,	/* advlock */
678 };
679