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