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.7 (Berkeley) 06/04/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 int *a_eofflag; 484 u_long *a_cookies; 485 int a_ncookies; 486 } */ *ap; 487 { 488 struct uio *uio = ap->a_uio; 489 int i; 490 int error; 491 492 /* 493 * We don't allow exporting kernfs mounts, and currently local 494 * requests do not need cookies. 495 */ 496 if (ap->a_ncookies) 497 panic("kernfs_readdir: not hungry"); 498 499 i = uio->uio_offset / UIO_MX; 500 error = 0; 501 while (uio->uio_resid > 0 && i < nkern_targets) { 502 struct dirent d; 503 struct dirent *dp = &d; 504 struct kern_target *kt = &kern_targets[i]; 505 #ifdef KERNFS_DIAGNOSTIC 506 printf("kernfs_readdir: i = %d\n", i); 507 #endif 508 509 bzero((caddr_t) dp, UIO_MX); 510 511 dp->d_namlen = strlen(kt->kt_name); 512 bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1); 513 514 #ifdef KERNFS_DIAGNOSTIC 515 printf("kernfs_readdir: name = %s, len = %d\n", 516 dp->d_name, dp->d_namlen); 517 #endif 518 /* 519 * Fill in the remaining fields 520 */ 521 dp->d_reclen = UIO_MX; 522 dp->d_fileno = i + 3; 523 dp->d_type = DT_UNKNOWN; /* XXX */ 524 /* 525 * And ship to userland 526 */ 527 error = uiomove((caddr_t) dp, UIO_MX, uio); 528 if (error) 529 break; 530 i++; 531 } 532 533 uio->uio_offset = i * UIO_MX; 534 535 return (error); 536 } 537 538 kernfs_inactive(ap) 539 struct vop_inactive_args /* { 540 struct vnode *a_vp; 541 } */ *ap; 542 { 543 struct vnode *vp = ap->a_vp; 544 545 /* 546 * Clear out the v_type field to avoid 547 * nasty things happening in vgone(). 548 */ 549 vp->v_type = VNON; 550 #ifdef KERNFS_DIAGNOSTIC 551 printf("kernfs_inactive(%x)\n", vp); 552 #endif 553 return (0); 554 } 555 556 kernfs_reclaim(ap) 557 struct vop_reclaim_args /* { 558 struct vnode *a_vp; 559 } */ *ap; 560 { 561 struct vnode *vp = ap->a_vp; 562 #ifdef KERNFS_DIAGNOSTIC 563 printf("kernfs_reclaim(%x)\n", vp); 564 #endif 565 if (vp->v_data) { 566 FREE(vp->v_data, M_TEMP); 567 vp->v_data = 0; 568 } 569 return (0); 570 } 571 572 /* 573 * Return POSIX pathconf information applicable to special devices. 574 */ 575 kernfs_pathconf(ap) 576 struct vop_pathconf_args /* { 577 struct vnode *a_vp; 578 int a_name; 579 int *a_retval; 580 } */ *ap; 581 { 582 583 switch (ap->a_name) { 584 case _PC_LINK_MAX: 585 *ap->a_retval = LINK_MAX; 586 return (0); 587 case _PC_MAX_CANON: 588 *ap->a_retval = MAX_CANON; 589 return (0); 590 case _PC_MAX_INPUT: 591 *ap->a_retval = MAX_INPUT; 592 return (0); 593 case _PC_PIPE_BUF: 594 *ap->a_retval = PIPE_BUF; 595 return (0); 596 case _PC_CHOWN_RESTRICTED: 597 *ap->a_retval = 1; 598 return (0); 599 case _PC_VDISABLE: 600 *ap->a_retval = _POSIX_VDISABLE; 601 return (0); 602 default: 603 return (EINVAL); 604 } 605 /* NOTREACHED */ 606 } 607 608 /* 609 * Print out the contents of a /dev/fd vnode. 610 */ 611 /* ARGSUSED */ 612 kernfs_print(ap) 613 struct vop_print_args /* { 614 struct vnode *a_vp; 615 } */ *ap; 616 { 617 618 printf("tag VT_KERNFS, kernfs vnode\n"); 619 return (0); 620 } 621 622 /*void*/ 623 kernfs_vfree(ap) 624 struct vop_vfree_args /* { 625 struct vnode *a_pvp; 626 ino_t a_ino; 627 int a_mode; 628 } */ *ap; 629 { 630 631 return (0); 632 } 633 634 /* 635 * /dev/fd vnode unsupported operation 636 */ 637 kernfs_enotsupp() 638 { 639 640 return (EOPNOTSUPP); 641 } 642 643 /* 644 * /dev/fd "should never get here" operation 645 */ 646 kernfs_badop() 647 { 648 649 panic("kernfs: bad op"); 650 /* NOTREACHED */ 651 } 652 653 /* 654 * kernfs vnode null operation 655 */ 656 kernfs_nullop() 657 { 658 659 return (0); 660 } 661 662 #define kernfs_create ((int (*) __P((struct vop_create_args *)))kernfs_enotsupp) 663 #define kernfs_mknod ((int (*) __P((struct vop_mknod_args *)))kernfs_enotsupp) 664 #define kernfs_close ((int (*) __P((struct vop_close_args *)))nullop) 665 #define kernfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))kernfs_enotsupp) 666 #define kernfs_select ((int (*) __P((struct vop_select_args *)))kernfs_enotsupp) 667 #define kernfs_mmap ((int (*) __P((struct vop_mmap_args *)))kernfs_enotsupp) 668 #define kernfs_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 669 #define kernfs_seek ((int (*) __P((struct vop_seek_args *)))nullop) 670 #define kernfs_remove ((int (*) __P((struct vop_remove_args *)))kernfs_enotsupp) 671 #define kernfs_link ((int (*) __P((struct vop_link_args *)))kernfs_enotsupp) 672 #define kernfs_rename ((int (*) __P((struct vop_rename_args *)))kernfs_enotsupp) 673 #define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))kernfs_enotsupp) 674 #define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))kernfs_enotsupp) 675 #define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp) 676 #define kernfs_readlink \ 677 ((int (*) __P((struct vop_readlink_args *)))kernfs_enotsupp) 678 #define kernfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) 679 #define kernfs_lock ((int (*) __P((struct vop_lock_args *)))nullop) 680 #define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) 681 #define kernfs_bmap ((int (*) __P((struct vop_bmap_args *)))kernfs_badop) 682 #define kernfs_strategy ((int (*) __P((struct vop_strategy_args *)))kernfs_badop) 683 #define kernfs_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) 684 #define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))kernfs_enotsupp) 685 #define kernfs_blkatoff \ 686 ((int (*) __P((struct vop_blkatoff_args *)))kernfs_enotsupp) 687 #define kernfs_valloc ((int(*) __P(( \ 688 struct vnode *pvp, \ 689 int mode, \ 690 struct ucred *cred, \ 691 struct vnode **vpp))) kernfs_enotsupp) 692 #define kernfs_truncate \ 693 ((int (*) __P((struct vop_truncate_args *)))kernfs_enotsupp) 694 #define kernfs_update ((int (*) __P((struct vop_update_args *)))kernfs_enotsupp) 695 #define kernfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))kernfs_enotsupp) 696 697 int (**kernfs_vnodeop_p)(); 698 struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { 699 { &vop_default_desc, vn_default_error }, 700 { &vop_lookup_desc, kernfs_lookup }, /* lookup */ 701 { &vop_create_desc, kernfs_create }, /* create */ 702 { &vop_mknod_desc, kernfs_mknod }, /* mknod */ 703 { &vop_open_desc, kernfs_open }, /* open */ 704 { &vop_close_desc, kernfs_close }, /* close */ 705 { &vop_access_desc, kernfs_access }, /* access */ 706 { &vop_getattr_desc, kernfs_getattr }, /* getattr */ 707 { &vop_setattr_desc, kernfs_setattr }, /* setattr */ 708 { &vop_read_desc, kernfs_read }, /* read */ 709 { &vop_write_desc, kernfs_write }, /* write */ 710 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ 711 { &vop_select_desc, kernfs_select }, /* select */ 712 { &vop_mmap_desc, kernfs_mmap }, /* mmap */ 713 { &vop_fsync_desc, kernfs_fsync }, /* fsync */ 714 { &vop_seek_desc, kernfs_seek }, /* seek */ 715 { &vop_remove_desc, kernfs_remove }, /* remove */ 716 { &vop_link_desc, kernfs_link }, /* link */ 717 { &vop_rename_desc, kernfs_rename }, /* rename */ 718 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */ 719 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */ 720 { &vop_symlink_desc, kernfs_symlink }, /* symlink */ 721 { &vop_readdir_desc, kernfs_readdir }, /* readdir */ 722 { &vop_readlink_desc, kernfs_readlink },/* readlink */ 723 { &vop_abortop_desc, kernfs_abortop }, /* abortop */ 724 { &vop_inactive_desc, kernfs_inactive },/* inactive */ 725 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */ 726 { &vop_lock_desc, kernfs_lock }, /* lock */ 727 { &vop_unlock_desc, kernfs_unlock }, /* unlock */ 728 { &vop_bmap_desc, kernfs_bmap }, /* bmap */ 729 { &vop_strategy_desc, kernfs_strategy },/* strategy */ 730 { &vop_print_desc, kernfs_print }, /* print */ 731 { &vop_islocked_desc, kernfs_islocked },/* islocked */ 732 { &vop_pathconf_desc, kernfs_pathconf },/* pathconf */ 733 { &vop_advlock_desc, kernfs_advlock }, /* advlock */ 734 { &vop_blkatoff_desc, kernfs_blkatoff },/* blkatoff */ 735 { &vop_valloc_desc, kernfs_valloc }, /* valloc */ 736 { &vop_vfree_desc, kernfs_vfree }, /* vfree */ 737 { &vop_truncate_desc, kernfs_truncate },/* truncate */ 738 { &vop_update_desc, kernfs_update }, /* update */ 739 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ 740 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 741 }; 742 struct vnodeopv_desc kernfs_vnodeop_opv_desc = 743 { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; 744