1 /* $NetBSD: kernfs_vnops.c,v 1.28 1994/07/21 10:22:20 mycroft Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software donated to Berkeley by 8 * Jan-Simon Pendry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kernfs_vnops.c 8.9 (Berkeley) 6/15/94 39 */ 40 41 /* 42 * Kernel parameter filesystem (/kern) 43 */ 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/kernel.h> 48 #include <sys/vmmeter.h> 49 #include <sys/types.h> 50 #include <sys/time.h> 51 #include <sys/proc.h> 52 #include <sys/vnode.h> 53 #include <sys/malloc.h> 54 #include <sys/file.h> 55 #include <sys/stat.h> 56 #include <sys/mount.h> 57 #include <sys/namei.h> 58 #include <sys/buf.h> 59 #include <sys/dirent.h> 60 #include <sys/msgbuf.h> 61 #include <miscfs/kernfs/kernfs.h> 62 63 #define KSTRING 256 /* Largest I/O available via this filesystem */ 64 #define UIO_MX 32 65 66 #define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH) 67 #define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) 68 #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 69 70 struct kern_target { 71 u_char kt_type; 72 u_char kt_namlen; 73 char *kt_name; 74 void *kt_data; 75 #define KTT_NULL 1 76 #define KTT_TIME 5 77 #define KTT_INT 17 78 #define KTT_STRING 31 79 #define KTT_HOSTNAME 47 80 #define KTT_AVENRUN 53 81 #define KTT_DEVICE 71 82 #define KTT_MSGBUF 89 83 u_char kt_tag; 84 u_char kt_vtype; 85 mode_t kt_mode; 86 } kern_targets[] = { 87 /* NOTE: The name must be less than UIO_MX-16 chars in length */ 88 #define N(s) sizeof(s)-1, s 89 /* name data tag type ro/rw */ 90 { DT_DIR, N("."), 0, KTT_NULL, VDIR, DIR_MODE }, 91 { DT_DIR, N(".."), 0, KTT_NULL, VDIR, DIR_MODE }, 92 { DT_REG, N("boottime"), &boottime.tv_sec, KTT_INT, VREG, READ_MODE }, 93 { DT_REG, N("copyright"), copyright, KTT_STRING, VREG, READ_MODE }, 94 { DT_REG, N("hostname"), 0, KTT_HOSTNAME, VREG, WRITE_MODE }, 95 { DT_REG, N("hz"), &hz, KTT_INT, VREG, READ_MODE }, 96 { DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE }, 97 { DT_REG, N("msgbuf"), 0, KTT_MSGBUF, VREG, READ_MODE }, 98 { DT_REG, N("pagesize"), &cnt.v_page_size, KTT_INT, VREG, READ_MODE }, 99 { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE }, 100 #if 0 101 { DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE }, 102 #endif 103 { DT_BLK, N("rootdev"), &rootdev, KTT_DEVICE, VBLK, READ_MODE }, 104 { DT_CHR, N("rrootdev"), &rrootdev, KTT_DEVICE, VCHR, READ_MODE }, 105 { DT_REG, N("time"), 0, KTT_TIME, VREG, READ_MODE }, 106 { DT_REG, N("version"), version, KTT_STRING, VREG, READ_MODE }, 107 #undef N 108 }; 109 static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); 110 111 int 112 kernfs_xread(kt, off, bufp, len) 113 struct kern_target *kt; 114 int off; 115 char **bufp; 116 int len; 117 { 118 119 switch (kt->kt_tag) { 120 case KTT_TIME: { 121 struct timeval tv; 122 123 microtime(&tv); 124 sprintf(*bufp, "%d %d\n", tv.tv_sec, tv.tv_usec); 125 break; 126 } 127 128 case KTT_INT: { 129 int *ip = kt->kt_data; 130 131 sprintf(*bufp, "%d\n", *ip); 132 break; 133 } 134 135 case KTT_STRING: { 136 char *cp = kt->kt_data; 137 138 *bufp = cp; 139 break; 140 } 141 142 case KTT_MSGBUF: { 143 extern struct msgbuf *msgbufp; 144 long n; 145 146 if (off >= MSG_BSIZE) 147 return (0); 148 n = msgbufp->msg_bufx + off; 149 if (n >= MSG_BSIZE) 150 n -= MSG_BSIZE; 151 len = min(MSG_BSIZE - n, MSG_BSIZE - off); 152 *bufp = msgbufp->msg_bufc + n; 153 return (len); 154 } 155 156 case KTT_HOSTNAME: { 157 char *cp = hostname; 158 int xlen = hostnamelen; 159 160 if (xlen >= (len-2)) 161 return (EINVAL); 162 163 bcopy(cp, *bufp, xlen); 164 (*bufp)[xlen] = '\n'; 165 (*bufp)[xlen+1] = '\0'; 166 break; 167 } 168 169 case KTT_AVENRUN: 170 sprintf(*bufp, "%ld %ld %ld %ld\n", 171 averunnable.ldavg[0], averunnable.ldavg[1], 172 averunnable.ldavg[2], averunnable.fscale); 173 break; 174 175 default: 176 return (0); 177 } 178 179 len = strlen(*bufp); 180 if (len <= off) 181 return (0); 182 *bufp += off; 183 return (len - off); 184 } 185 186 int 187 kernfs_xwrite(kt, buf, len) 188 struct kern_target *kt; 189 char *buf; 190 int len; 191 { 192 193 switch (kt->kt_tag) { 194 case KTT_HOSTNAME: 195 if (buf[len-1] == '\n') 196 --len; 197 bcopy(buf, hostname, len); 198 hostname[len] = '\0'; 199 hostnamelen = len; 200 return (0); 201 202 default: 203 return (EIO); 204 } 205 } 206 207 208 /* 209 * vp is the current namei directory 210 * ndp is the name to locate in that directory... 211 */ 212 kernfs_lookup(ap) 213 struct vop_lookup_args /* { 214 struct vnode * a_dvp; 215 struct vnode ** a_vpp; 216 struct componentname * a_cnp; 217 } */ *ap; 218 { 219 struct componentname *cnp = ap->a_cnp; 220 struct vnode **vpp = ap->a_vpp; 221 struct vnode *dvp = ap->a_dvp; 222 char *pname = cnp->cn_nameptr; 223 struct kern_target *kt; 224 struct vnode *fvp; 225 int error, i; 226 227 #ifdef KERNFS_DIAGNOSTIC 228 printf("kernfs_lookup(%x)\n", ap); 229 printf("kernfs_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp); 230 printf("kernfs_lookup(%s)\n", pname); 231 #endif 232 233 if (cnp->cn_namelen == 1 && *pname == '.') { 234 *vpp = dvp; 235 VREF(dvp); 236 /*VOP_LOCK(dvp);*/ 237 return (0); 238 } 239 240 #if 0 241 if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) { 242 *vpp = rootdir; 243 VREF(rootdir); 244 VOP_LOCK(rootdir); 245 return (0); 246 } 247 #endif 248 249 *vpp = NULLVP; 250 251 for (error = ENOENT, kt = kern_targets, i = 0; i < nkern_targets; 252 kt++, i++) { 253 if (cnp->cn_namelen == kt->kt_namlen && 254 bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) { 255 error = 0; 256 break; 257 } 258 } 259 260 #ifdef KERNFS_DIAGNOSTIC 261 printf("kernfs_lookup: i = %d, error = %d\n", i, error); 262 #endif 263 264 if (error) 265 return (error); 266 267 if (kt->kt_tag == KTT_DEVICE) { 268 dev_t *dp = kt->kt_data; 269 loop: 270 if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) 271 return (ENOENT); 272 *vpp = fvp; 273 if (vget(fvp, 1)) 274 goto loop; 275 return (0); 276 } 277 278 #ifdef KERNFS_DIAGNOSTIC 279 printf("kernfs_lookup: allocate new vnode\n"); 280 #endif 281 if (error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, 282 &fvp)) 283 return (error); 284 285 MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP, 286 M_WAITOK); 287 VTOKERN(fvp)->kf_kt = kt; 288 fvp->v_type = kt->kt_vtype; 289 *vpp = fvp; 290 291 #ifdef KERNFS_DIAGNOSTIC 292 printf("kernfs_lookup: newvp = %x\n", fvp); 293 #endif 294 return (0); 295 } 296 297 kernfs_open(ap) 298 struct vop_open_args /* { 299 struct vnode *a_vp; 300 int a_mode; 301 struct ucred *a_cred; 302 struct proc *a_p; 303 } */ *ap; 304 { 305 306 /* Only need to check access permissions. */ 307 return (0); 308 } 309 310 int 311 kernfs_access(ap) 312 struct vop_access_args /* { 313 struct vnode *a_vp; 314 int a_mode; 315 struct ucred *a_cred; 316 struct proc *a_p; 317 } */ *ap; 318 { 319 struct vnode *vp = ap->a_vp; 320 struct ucred *cred = ap->a_cred; 321 mode_t amode = ap->a_mode; 322 mode_t fmode = 323 (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_kt->kt_mode; 324 mode_t mask = 0; 325 gid_t *gp; 326 int i; 327 328 /* Some files are simply not modifiable. */ 329 if ((amode & VWRITE) && (fmode & (S_IWUSR|S_IWGRP|S_IWOTH)) == 0) 330 return (EPERM); 331 332 /* Root can do anything else. */ 333 if (cred->cr_uid == 0) 334 return (0); 335 336 /* Check for group 0 (wheel) permissions. */ 337 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) 338 if (*gp == 0) { 339 if (amode & VEXEC) 340 mask |= S_IXGRP; 341 if (amode & VREAD) 342 mask |= S_IRGRP; 343 if (amode & VWRITE) 344 mask |= S_IWGRP; 345 return ((fmode & mask) == mask ? 0 : EACCES); 346 } 347 348 /* Otherwise, check everyone else. */ 349 if (amode & VEXEC) 350 mask |= S_IXOTH; 351 if (amode & VREAD) 352 mask |= S_IROTH; 353 if (amode & VWRITE) 354 mask |= S_IWOTH; 355 return ((fmode & mask) == mask ? 0 : EACCES); 356 } 357 358 kernfs_getattr(ap) 359 struct vop_getattr_args /* { 360 struct vnode *a_vp; 361 struct vattr *a_vap; 362 struct ucred *a_cred; 363 struct proc *a_p; 364 } */ *ap; 365 { 366 struct vnode *vp = ap->a_vp; 367 struct vattr *vap = ap->a_vap; 368 int error = 0; 369 char strbuf[KSTRING], *buf; 370 371 bzero((caddr_t) vap, sizeof(*vap)); 372 vattr_null(vap); 373 vap->va_uid = 0; 374 vap->va_gid = 0; 375 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 376 vap->va_size = 0; 377 vap->va_blocksize = DEV_BSIZE; 378 microtime(&vap->va_atime); 379 vap->va_mtime = vap->va_atime; 380 vap->va_ctime = vap->va_ctime; 381 vap->va_gen = 0; 382 vap->va_flags = 0; 383 vap->va_rdev = 0; 384 vap->va_bytes = 0; 385 386 if (vp->v_flag & VROOT) { 387 #ifdef KERNFS_DIAGNOSTIC 388 printf("kernfs_getattr: stat rootdir\n"); 389 #endif 390 vap->va_type = VDIR; 391 vap->va_mode = DIR_MODE; 392 vap->va_nlink = 2; 393 vap->va_fileid = 2; 394 vap->va_size = DEV_BSIZE; 395 } else { 396 struct kern_target *kt = VTOKERN(vp)->kf_kt; 397 int nbytes, total; 398 #ifdef KERNFS_DIAGNOSTIC 399 printf("kernfs_getattr: stat target %s\n", kt->kt_name); 400 #endif 401 vap->va_type = kt->kt_vtype; 402 vap->va_mode = kt->kt_mode; 403 vap->va_nlink = 1; 404 vap->va_fileid = 1 + (kt - kern_targets) / sizeof(*kt); 405 total = 0; 406 while (buf = strbuf, 407 nbytes = kernfs_xread(kt, total, &buf, sizeof(strbuf))) 408 total += nbytes; 409 vap->va_size = total; 410 } 411 412 #ifdef KERNFS_DIAGNOSTIC 413 printf("kernfs_getattr: return error %d\n", error); 414 #endif 415 return (error); 416 } 417 418 kernfs_setattr(ap) 419 struct vop_setattr_args /* { 420 struct vnode *a_vp; 421 struct vattr *a_vap; 422 struct ucred *a_cred; 423 struct proc *a_p; 424 } */ *ap; 425 { 426 427 /* 428 * Silently ignore attribute changes. 429 * This allows for open with truncate to have no 430 * effect until some data is written. I want to 431 * do it this way because all writes are atomic. 432 */ 433 return (0); 434 } 435 436 int 437 kernfs_read(ap) 438 struct vop_read_args /* { 439 struct vnode *a_vp; 440 struct uio *a_uio; 441 int a_ioflag; 442 struct ucred *a_cred; 443 } */ *ap; 444 { 445 struct vnode *vp = ap->a_vp; 446 struct uio *uio = ap->a_uio; 447 struct kern_target *kt; 448 char strbuf[KSTRING], *buf; 449 int off, len; 450 int error; 451 452 if (vp->v_type == VDIR) 453 return (EOPNOTSUPP); 454 455 kt = VTOKERN(vp)->kf_kt; 456 457 #ifdef KERNFS_DIAGNOSTIC 458 printf("kern_read %s\n", kt->kt_name); 459 #endif 460 461 off = uio->uio_offset; 462 #if 0 463 while (buf = strbuf, 464 #else 465 if (buf = strbuf, 466 #endif 467 len = kernfs_xread(kt, off, &buf, sizeof(strbuf))) { 468 if (error = uiomove(buf, len, uio)) 469 return (error); 470 off += len; 471 } 472 return (0); 473 } 474 475 int 476 kernfs_write(ap) 477 struct vop_write_args /* { 478 struct vnode *a_vp; 479 struct uio *a_uio; 480 int a_ioflag; 481 struct ucred *a_cred; 482 } */ *ap; 483 { 484 struct vnode *vp = ap->a_vp; 485 struct uio *uio = ap->a_uio; 486 struct kern_target *kt; 487 int error, xlen; 488 char strbuf[KSTRING]; 489 490 if (vp->v_type == VDIR) 491 return (EOPNOTSUPP); 492 493 kt = VTOKERN(vp)->kf_kt; 494 495 if (uio->uio_offset != 0) 496 return (EINVAL); 497 498 xlen = min(uio->uio_resid, KSTRING-1); 499 if (error = uiomove(strbuf, xlen, uio)) 500 return (error); 501 502 if (uio->uio_resid != 0) 503 return (EIO); 504 505 strbuf[xlen] = '\0'; 506 xlen = strlen(strbuf); 507 return (kernfs_xwrite(kt, strbuf, xlen)); 508 } 509 510 kernfs_readdir(ap) 511 struct vop_readdir_args /* { 512 struct vnode *a_vp; 513 struct uio *a_uio; 514 struct ucred *a_cred; 515 int *a_eofflag; 516 u_long *a_cookies; 517 int a_ncookies; 518 } */ *ap; 519 { 520 struct uio *uio = ap->a_uio; 521 struct kern_target *kt; 522 struct dirent d; 523 int i; 524 int error; 525 526 if (ap->a_vp->v_type != VDIR) 527 return (ENOTDIR); 528 529 /* 530 * We don't allow exporting kernfs mounts, and currently local 531 * requests do not need cookies. 532 */ 533 if (ap->a_ncookies != NULL) 534 panic("kernfs_readdir: not hungry"); 535 536 i = uio->uio_offset / UIO_MX; 537 error = 0; 538 for (kt = &kern_targets[i]; 539 uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) { 540 struct dirent *dp = &d; 541 #ifdef KERNFS_DIAGNOSTIC 542 printf("kernfs_readdir: i = %d\n", i); 543 #endif 544 545 if (kt->kt_tag == KTT_DEVICE) { 546 dev_t *dp = kt->kt_data; 547 struct vnode *fvp; 548 549 if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) 550 continue; 551 } 552 553 bzero((caddr_t)dp, UIO_MX); 554 dp->d_namlen = kt->kt_namlen; 555 bcopy(kt->kt_name, dp->d_name, kt->kt_namlen+1); 556 557 #ifdef KERNFS_DIAGNOSTIC 558 printf("kernfs_readdir: name = %s, len = %d\n", 559 dp->d_name, dp->d_namlen); 560 #endif 561 /* 562 * Fill in the remaining fields 563 */ 564 dp->d_reclen = UIO_MX; 565 dp->d_fileno = i + 3; 566 dp->d_type = kt->kt_type; 567 /* 568 * And ship to userland 569 */ 570 if (error = uiomove((caddr_t)dp, UIO_MX, uio)) 571 break; 572 } 573 574 uio->uio_offset = i * UIO_MX; 575 576 return (error); 577 } 578 579 kernfs_inactive(ap) 580 struct vop_inactive_args /* { 581 struct vnode *a_vp; 582 } */ *ap; 583 { 584 struct vnode *vp = ap->a_vp; 585 586 #ifdef KERNFS_DIAGNOSTIC 587 printf("kernfs_inactive(%x)\n", vp); 588 #endif 589 /* 590 * Clear out the v_type field to avoid 591 * nasty things happening in vgone(). 592 */ 593 vp->v_type = VNON; 594 return (0); 595 } 596 597 kernfs_reclaim(ap) 598 struct vop_reclaim_args /* { 599 struct vnode *a_vp; 600 } */ *ap; 601 { 602 struct vnode *vp = ap->a_vp; 603 604 #ifdef KERNFS_DIAGNOSTIC 605 printf("kernfs_reclaim(%x)\n", vp); 606 #endif 607 if (vp->v_data) { 608 FREE(vp->v_data, M_TEMP); 609 vp->v_data = 0; 610 } 611 return (0); 612 } 613 614 /* 615 * Return POSIX pathconf information applicable to special devices. 616 */ 617 kernfs_pathconf(ap) 618 struct vop_pathconf_args /* { 619 struct vnode *a_vp; 620 int a_name; 621 int *a_retval; 622 } */ *ap; 623 { 624 625 switch (ap->a_name) { 626 case _PC_LINK_MAX: 627 *ap->a_retval = LINK_MAX; 628 return (0); 629 case _PC_MAX_CANON: 630 *ap->a_retval = MAX_CANON; 631 return (0); 632 case _PC_MAX_INPUT: 633 *ap->a_retval = MAX_INPUT; 634 return (0); 635 case _PC_PIPE_BUF: 636 *ap->a_retval = PIPE_BUF; 637 return (0); 638 case _PC_CHOWN_RESTRICTED: 639 *ap->a_retval = 1; 640 return (0); 641 case _PC_VDISABLE: 642 *ap->a_retval = _POSIX_VDISABLE; 643 return (0); 644 default: 645 return (EINVAL); 646 } 647 /* NOTREACHED */ 648 } 649 650 /* 651 * Print out the contents of a /dev/fd vnode. 652 */ 653 /* ARGSUSED */ 654 kernfs_print(ap) 655 struct vop_print_args /* { 656 struct vnode *a_vp; 657 } */ *ap; 658 { 659 660 printf("tag VT_KERNFS, kernfs vnode\n"); 661 return (0); 662 } 663 664 /*void*/ 665 kernfs_vfree(ap) 666 struct vop_vfree_args /* { 667 struct vnode *a_pvp; 668 ino_t a_ino; 669 int a_mode; 670 } */ *ap; 671 { 672 673 return (0); 674 } 675 676 /* 677 * /dev/fd vnode unsupported operation 678 */ 679 kernfs_enotsupp() 680 { 681 682 return (EOPNOTSUPP); 683 } 684 685 /* 686 * /dev/fd "should never get here" operation 687 */ 688 kernfs_badop() 689 { 690 691 panic("kernfs: bad op"); 692 /* NOTREACHED */ 693 } 694 695 /* 696 * kernfs vnode null operation 697 */ 698 kernfs_nullop() 699 { 700 701 return (0); 702 } 703 704 #define kernfs_create ((int (*) __P((struct vop_create_args *)))kernfs_enotsupp) 705 #define kernfs_mknod ((int (*) __P((struct vop_mknod_args *)))kernfs_enotsupp) 706 #define kernfs_close ((int (*) __P((struct vop_close_args *)))nullop) 707 #define kernfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))kernfs_enotsupp) 708 #define kernfs_select ((int (*) __P((struct vop_select_args *)))kernfs_enotsupp) 709 #define kernfs_mmap ((int (*) __P((struct vop_mmap_args *)))kernfs_enotsupp) 710 #define kernfs_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 711 #define kernfs_seek ((int (*) __P((struct vop_seek_args *)))nullop) 712 #define kernfs_remove ((int (*) __P((struct vop_remove_args *)))kernfs_enotsupp) 713 #define kernfs_link ((int (*) __P((struct vop_link_args *)))kernfs_enotsupp) 714 #define kernfs_rename ((int (*) __P((struct vop_rename_args *)))kernfs_enotsupp) 715 #define kernfs_mkdir ((int (*) __P((struct vop_mkdir_args *)))kernfs_enotsupp) 716 #define kernfs_rmdir ((int (*) __P((struct vop_rmdir_args *)))kernfs_enotsupp) 717 #define kernfs_symlink ((int (*) __P((struct vop_symlink_args *)))kernfs_enotsupp) 718 #define kernfs_readlink \ 719 ((int (*) __P((struct vop_readlink_args *)))kernfs_enotsupp) 720 #define kernfs_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) 721 #define kernfs_lock ((int (*) __P((struct vop_lock_args *)))nullop) 722 #define kernfs_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) 723 #define kernfs_bmap ((int (*) __P((struct vop_bmap_args *)))kernfs_badop) 724 #define kernfs_strategy ((int (*) __P((struct vop_strategy_args *)))kernfs_badop) 725 #define kernfs_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) 726 #define kernfs_advlock ((int (*) __P((struct vop_advlock_args *)))kernfs_enotsupp) 727 #define kernfs_blkatoff \ 728 ((int (*) __P((struct vop_blkatoff_args *)))kernfs_enotsupp) 729 #define kernfs_valloc ((int(*) __P(( \ 730 struct vnode *pvp, \ 731 int mode, \ 732 struct ucred *cred, \ 733 struct vnode **vpp))) kernfs_enotsupp) 734 #define kernfs_truncate \ 735 ((int (*) __P((struct vop_truncate_args *)))kernfs_enotsupp) 736 #define kernfs_update ((int (*) __P((struct vop_update_args *)))kernfs_enotsupp) 737 #define kernfs_bwrite ((int (*) __P((struct vop_bwrite_args *)))kernfs_enotsupp) 738 739 int (**kernfs_vnodeop_p)(); 740 struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { 741 { &vop_default_desc, vn_default_error }, 742 { &vop_lookup_desc, kernfs_lookup }, /* lookup */ 743 { &vop_create_desc, kernfs_create }, /* create */ 744 { &vop_mknod_desc, kernfs_mknod }, /* mknod */ 745 { &vop_open_desc, kernfs_open }, /* open */ 746 { &vop_close_desc, kernfs_close }, /* close */ 747 { &vop_access_desc, kernfs_access }, /* access */ 748 { &vop_getattr_desc, kernfs_getattr }, /* getattr */ 749 { &vop_setattr_desc, kernfs_setattr }, /* setattr */ 750 { &vop_read_desc, kernfs_read }, /* read */ 751 { &vop_write_desc, kernfs_write }, /* write */ 752 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ 753 { &vop_select_desc, kernfs_select }, /* select */ 754 { &vop_mmap_desc, kernfs_mmap }, /* mmap */ 755 { &vop_fsync_desc, kernfs_fsync }, /* fsync */ 756 { &vop_seek_desc, kernfs_seek }, /* seek */ 757 { &vop_remove_desc, kernfs_remove }, /* remove */ 758 { &vop_link_desc, kernfs_link }, /* link */ 759 { &vop_rename_desc, kernfs_rename }, /* rename */ 760 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */ 761 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */ 762 { &vop_symlink_desc, kernfs_symlink }, /* symlink */ 763 { &vop_readdir_desc, kernfs_readdir }, /* readdir */ 764 { &vop_readlink_desc, kernfs_readlink },/* readlink */ 765 { &vop_abortop_desc, kernfs_abortop }, /* abortop */ 766 { &vop_inactive_desc, kernfs_inactive },/* inactive */ 767 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */ 768 { &vop_lock_desc, kernfs_lock }, /* lock */ 769 { &vop_unlock_desc, kernfs_unlock }, /* unlock */ 770 { &vop_bmap_desc, kernfs_bmap }, /* bmap */ 771 { &vop_strategy_desc, kernfs_strategy },/* strategy */ 772 { &vop_print_desc, kernfs_print }, /* print */ 773 { &vop_islocked_desc, kernfs_islocked },/* islocked */ 774 { &vop_pathconf_desc, kernfs_pathconf },/* pathconf */ 775 { &vop_advlock_desc, kernfs_advlock }, /* advlock */ 776 { &vop_blkatoff_desc, kernfs_blkatoff },/* blkatoff */ 777 { &vop_valloc_desc, kernfs_valloc }, /* valloc */ 778 { &vop_vfree_desc, kernfs_vfree }, /* vfree */ 779 { &vop_truncate_desc, kernfs_truncate },/* truncate */ 780 { &vop_update_desc, kernfs_update }, /* update */ 781 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ 782 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 783 }; 784 struct vnodeopv_desc kernfs_vnodeop_opv_desc = 785 { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; 786