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