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