1 /* 2 * Copyright (c) 1990, 1992 Jan-Simon Pendry 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Jan-Simon Pendry. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * $Id: kernfs_vnops.c,v 1.10 1993/06/07 05:25:25 cgd Exp $ 37 */ 38 39 /* 40 * Kernel parameter filesystem 41 */ 42 43 #include "param.h" 44 #include "systm.h" 45 #include "kernel.h" 46 #include "types.h" 47 #include "time.h" 48 #include "proc.h" 49 #include "file.h" 50 #include "vnode.h" 51 #include "stat.h" 52 #include "mount.h" 53 #include "namei.h" 54 #include "buf.h" 55 #include "miscfs/kernfs/kernfs.h" 56 57 #include "../ufs/dir.h" /* For readdir() XXX */ 58 59 struct kernfs_target kernfs_targets[] = { 60 /* NOTE: The name must be less than UIO_MX-16 chars in length */ 61 DIR_TARGET(".", 0, KTT_NULL, KTM_DIR_PERMS ) 62 DIR_TARGET("..", 0, KTT_NULL, KTM_DIR_PERMS ) 63 REG_TARGET("copyright", copyright, KTT_STRING, KTM_RO_PERMS ) 64 REG_TARGET("hostname", 0, KTT_HOSTNAME, KTM_RW_PERMS ) 65 REG_TARGET("hz", &hz, KTT_INT, KTM_RO_PERMS ) 66 REG_TARGET("loadavg", 0, KTT_AVENRUN, KTM_RO_PERMS ) 67 REG_TARGET("physmem", &physmem, KTT_INT, KTM_RO_PERMS ) 68 DIR_TARGET("root", 0, KTT_NULL, KTM_DIR_PERMS ) 69 BLK_TARGET("rootdev", 0, KTT_NULL, KTM_RO_PERMS ) 70 CHR_TARGET("rrootdev", 0, KTT_NULL, KTM_RO_PERMS ) 71 REG_TARGET("time", 0, KTT_TIME, KTM_RO_PERMS ) 72 REG_TARGET("version", version, KTT_STRING, KTM_RO_PERMS ) 73 }; 74 75 static int nkernfs_targets = sizeof(kernfs_targets) / sizeof(kernfs_targets[0]); 76 77 static int 78 kernfs_xread(kt, buf, len, lenp) 79 struct kernfs_target *kt; 80 char *buf; 81 int len; 82 int *lenp; 83 { 84 int xlen; 85 86 switch (kt->kt_tag) { 87 case KTT_TIME: { 88 struct timeval tv; 89 microtime(&tv); 90 sprintf(buf, "%d %d\n", tv.tv_sec, tv.tv_usec); 91 break; 92 } 93 94 case KTT_INT: { 95 int *ip = kt->kt_data; 96 sprintf(buf, "%d\n", *ip); 97 break; 98 } 99 100 case KTT_STRING: { 101 char *cp = kt->kt_data; 102 int xlen = strlen(cp) + 1; 103 104 if (xlen >= len) 105 return (EINVAL); 106 107 bcopy(cp, buf, xlen); 108 break; 109 } 110 111 case KTT_HOSTNAME: { 112 char *cp = hostname; 113 int xlen = hostnamelen; 114 115 if (xlen + 2 > len) /* extra space for null and newline */ 116 return (EINVAL); 117 118 bcopy(cp, buf, xlen); /* safer than sprintf */ 119 buf[xlen] = '\n'; 120 buf[xlen+1] = '\0'; 121 break; 122 } 123 124 case KTT_AVENRUN: 125 sprintf(buf, "%d %d %d %d\n", 126 averunnable[0], 127 averunnable[1], 128 averunnable[2], 129 FSCALE); 130 break; 131 132 default: 133 return (EINVAL); 134 } 135 136 *lenp = strlen(buf); 137 return (0); 138 } 139 140 static int 141 kernfs_xwrite(kt, buf, len) 142 struct kernfs_target *kt; 143 char *buf; 144 int len; 145 { 146 switch (kt->kt_tag) { 147 case KTT_HOSTNAME: { 148 if (buf[len-1] == '\n') 149 --len; 150 bcopy(buf, hostname, len); 151 /* kernfs_write set buf[value_passed_as_len] = \0. 152 * therefore, buf len (hostnamelen) = len. 153 */ 154 hostnamelen = len; 155 hostname[hostnamelen] = '\0'; /* null end of string. */ 156 return (0); 157 } 158 159 default: 160 return (EIO); 161 } 162 } 163 164 /* 165 * vp is the current namei directory 166 * ndp is the name to locate in that directory... 167 */ 168 kernfs_lookup(dvp, ndp, p) 169 struct vnode *dvp; 170 struct nameidata *ndp; 171 struct proc *p; 172 { 173 char *pname = ndp->ni_ptr; 174 int error = ENOENT; 175 int i; 176 struct vnode *fvp; 177 178 #ifdef KERNFS_DIAGNOSTIC 179 printf("kernfs_lookup(%s)\n", pname); 180 #endif 181 if (ndp->ni_namelen == 1 && *pname == '.') { 182 ndp->ni_dvp = dvp; 183 ndp->ni_vp = dvp; 184 VREF(dvp); 185 /*VOP_LOCK(dvp);*/ 186 return (0); 187 } 188 189 if (ndp->ni_namelen == 4 && bcmp(pname, "root", 4) == 0) { 190 ndp->ni_dvp = dvp; 191 ndp->ni_vp = rootdir; 192 VREF(rootdir); 193 VOP_LOCK(rootdir); 194 return (0); 195 } 196 197 /* 198 * /kern/rootdev is the root device 199 */ 200 if (ndp->ni_namelen == 7 && bcmp(pname, "rootdev", 7) == 0) { 201 if (vfinddev(rootdev, VBLK, &fvp)) 202 return (ENXIO); 203 ndp->ni_dvp = dvp; 204 ndp->ni_vp = fvp; 205 VREF(fvp); 206 VOP_LOCK(fvp); 207 return (0); 208 } 209 210 /* 211 * /kern/rrootdev is the root device 212 */ 213 if (ndp->ni_namelen == 8 && bcmp(pname, "rrootdev", 7) == 0) { 214 ndp->ni_dvp = dvp; 215 ndp->ni_vp = rrootdevvp; 216 VREF(rrootdevvp); 217 VOP_LOCK(rrootdevvp); 218 return (0); 219 } 220 221 for (i = 0; i < nkernfs_targets; i++) { 222 struct kernfs_target *kt = &kernfs_targets[i]; 223 if (ndp->ni_namelen == strlen(kt->kt_name) && 224 bcmp(kt->kt_name, pname, ndp->ni_namelen) == 0) { 225 error = 0; 226 break; 227 } 228 } 229 230 #ifdef KERNFS_DIAGNOSTIC 231 printf("kernfs_lookup: i = %d, error = %d\n", i, error); 232 #endif 233 234 if (error) 235 goto bad; 236 237 #ifdef KERNFS_DIAGNOSTIC 238 printf("kernfs_lookup: allocate new vnode\n"); 239 #endif 240 error = getnewvnode(VT_KERNFS, dvp->v_mount, &kernfs_vnodeops, &fvp); 241 if (error) 242 goto bad; 243 VTOKERN(fvp)->kf_kt = &kernfs_targets[i]; 244 fvp->v_type = VTOKERN(fvp)->kf_kt->kt_vtype; 245 ndp->ni_dvp = dvp; 246 ndp->ni_vp = fvp; 247 #ifdef KERNFS_DIAGNOSTIC 248 printf("kernfs_lookup: newvp = %x\n", fvp); 249 #endif 250 return (0); 251 252 bad:; 253 ndp->ni_dvp = dvp; 254 ndp->ni_vp = NULL; 255 #ifdef KERNFS_DIAGNOSTIC 256 printf("kernfs_lookup: error = %d\n", error); 257 #endif 258 return (error); 259 } 260 261 kernfs_open(vp, mode, cred, p) 262 struct vnode *vp; 263 int mode; 264 struct ucred *cred; 265 struct proc *p; 266 { 267 /* if access succeeded, this always does, too */ 268 269 return (0); 270 } 271 272 /* 273 * Check mode permission on target pointer. Mode is READ, WRITE or EXEC. 274 * The mode is shifted to select the owner/group/other fields. The 275 * super user is granted all permissions. 276 */ 277 kernfs_access(vp, mode, cred, p) 278 struct vnode *vp; 279 register int mode; 280 struct ucred *cred; 281 struct proc *p; 282 { 283 struct kernfs_target *kt = VTOKERN(vp)->kf_kt; 284 register gid_t *gp; 285 int i, error; 286 287 #ifdef KERN_DIAGNOSTIC 288 if (!VOP_ISLOCKED(vp)) { 289 vprint("kernfs_access: not locked", vp); 290 panic("kernfs_access: not locked"); 291 } 292 #endif 293 /* 294 * If you're the super-user, you always get access. 295 */ 296 if (cred->cr_uid == 0) 297 return (0); 298 /* 299 * Access check is based on only one of owner, group, public. 300 * If not owner, then check group. If not a member of the 301 * group, then check public access. 302 */ 303 if (cred->cr_uid != /* kt->kt_uid XXX */ 0) { 304 mode >>= 3; 305 gp = cred->cr_groups; 306 for (i = 0; i < cred->cr_ngroups; i++, gp++) 307 if (/* kt->kt_gid XXX */ 0 == *gp) 308 goto found; 309 mode >>= 3; 310 found: 311 ; 312 } 313 if ((kt->kt_perms & mode) == mode) 314 return (0); 315 return (EACCES); 316 } 317 318 kernfs_getattr(vp, vap, cred, p) 319 struct vnode *vp; 320 struct vattr *vap; 321 struct ucred *cred; 322 struct proc *p; 323 { 324 int error = 0; 325 char strbuf[KSTRING]; 326 struct kernfs_target *kt = VTOKERN(vp)->kf_kt; 327 328 bzero((caddr_t) vap, sizeof(*vap)); 329 vattr_null(vap); 330 vap->va_uid = kt->kt_uid; 331 vap->va_gid = kt->kt_gid; 332 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 333 /* vap->va_qsize = 0; */ 334 vap->va_blocksize = DEV_BSIZE; 335 microtime(&vap->va_atime); 336 vap->va_mtime = vap->va_atime; 337 vap->va_ctime = vap->va_ctime; 338 vap->va_gen = 0; 339 vap->va_flags = 0; 340 vap->va_rdev = 0; 341 /* vap->va_qbytes = 0; */ 342 vap->va_bytes = 0; 343 vap->va_type = kt->kt_vtype; 344 vap->va_mode = kt->kt_perms; 345 346 if (vp->v_flag & VROOT) { 347 #ifdef KERNFS_DIAGNOSTIC 348 printf("kernfs_getattr: stat rootdir\n"); 349 #endif 350 vap->va_nlink = 2; 351 vap->va_fileid = 2; 352 vap->va_size = DEV_BSIZE; 353 } else { 354 #ifdef KERNFS_DIAGNOSTIC 355 printf("kernfs_getattr: stat target %s\n", kt->kt_name); 356 #endif 357 vap->va_nlink = 1; 358 vap->va_fileid = 3 + (kt - kernfs_targets) / sizeof(*kt); 359 error = kernfs_xread(kt, strbuf, sizeof(strbuf), &vap->va_size); 360 } 361 362 vp->v_type = vap->va_type; 363 #ifdef KERNFS_DIAGNOSTIC 364 printf("kernfs_getattr: return error %d\n", error); 365 #endif 366 return (error); 367 } 368 369 370 /* 371 * Change the mode on a file. 372 */ 373 kernfs_chmod1(vp, mode, p) 374 register struct vnode *vp; 375 register int mode; 376 struct proc *p; 377 { 378 register struct ucred *cred = p->p_ucred; 379 register struct kernfs_target *kt = VTOKERN(vp)->kf_kt; 380 int error; 381 382 if ((mode & kt->kt_maxperms) != mode) /* can't set ro var to rw */ 383 return (EPERM); 384 385 if (cred->cr_uid != kt->kt_uid && 386 (error = suser(cred, &p->p_acflag))) 387 return (error); 388 if (cred->cr_uid) { 389 if (vp->v_type != VDIR && (mode & S_ISVTX)) 390 return (EFTYPE); 391 if (!groupmember(kt->kt_gid, cred) && (mode & S_ISGID)) 392 return (EPERM); 393 } 394 kt->kt_perms &= ~07777; 395 kt->kt_perms |= mode & 07777; 396 /* ip->i_flag |= ICHG;*/ 397 return (0); 398 } 399 400 /* 401 * Perform chown operation on kernfs_target kt 402 */ 403 kernfs_chown1(vp, uid, gid, p) 404 register struct vnode *vp; 405 uid_t uid; 406 gid_t gid; 407 struct proc *p; 408 { 409 register struct kernfs_target *kt = VTOKERN(vp)->kf_kt; 410 register struct ucred *cred = p->p_ucred; 411 uid_t ouid; 412 gid_t ogid; 413 int error = 0; 414 415 if (uid == (u_short)VNOVAL) 416 uid = kt->kt_uid; 417 if (gid == (u_short)VNOVAL) 418 gid = kt->kt_gid; 419 /* 420 * If we don't own the file, are trying to change the owner 421 * of the file, or are not a member of the target group, 422 * the caller must be superuser or the call fails. 423 */ 424 if ((cred->cr_uid != kt->kt_uid || uid != kt->kt_uid || 425 !groupmember((gid_t)gid, cred)) && 426 (error = suser(cred, &p->p_acflag))) 427 return (error); 428 ouid = kt->kt_uid; 429 ogid = kt->kt_gid; 430 431 kt->kt_uid = uid; 432 kt->kt_gid = gid; 433 434 /* if (ouid != uid || ogid != gid) 435 ip->i_flag |= ICHG;*/ 436 if (ouid != uid && cred->cr_uid != 0) 437 kt->kt_perms &= ~S_ISUID; 438 if (ogid != gid && cred->cr_uid != 0) 439 kt->kt_perms &= ~S_ISGID; 440 return (0); 441 } 442 443 /* 444 * Set attribute vnode op. called from several syscalls 445 */ 446 kernfs_setattr(vp, vap, cred, p) 447 struct vnode *vp; 448 struct vattr *vap; 449 struct ucred *cred; 450 struct proc *p; 451 { 452 int error = 0; 453 454 /* 455 * Check for unsetable attributes. 456 */ 457 if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) || 458 (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) || 459 (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) || 460 ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { 461 return (EINVAL); 462 } 463 /* 464 * Go through the fields and update iff not VNOVAL. 465 */ 466 if (vap->va_uid != (u_short)VNOVAL || vap->va_gid != (u_short)VNOVAL) 467 if (error = kernfs_chown1(vp, vap->va_uid, vap->va_gid, p)) 468 return (error); 469 if (vap->va_size != VNOVAL) { 470 if (vp->v_type == VDIR) 471 return (EISDIR); 472 /* else just nod and smile... */ 473 } 474 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 475 /* if (cred->cr_uid != ip->i_uid && 476 (error = suser(cred, &p->p_acflag))) 477 return (error); 478 if (vap->va_atime.tv_sec != VNOVAL) 479 ip->i_flag |= IACC; 480 if (vap->va_mtime.tv_sec != VNOVAL) 481 ip->i_flag |= IUPD; 482 ip->i_flag |= ICHG; 483 if (error = iupdat(ip, &vap->va_atime, &vap->va_mtime, 1)) 484 return (error); 485 */ 486 } 487 if (vap->va_mode != (u_short)VNOVAL) 488 error = kernfs_chmod1(vp, (int)vap->va_mode, p); 489 if (vap->va_flags != VNOVAL) { 490 /* if (cred->cr_uid != ip->i_uid && 491 (error = suser(cred, &p->p_acflag))) 492 return (error); 493 if (cred->cr_uid == 0) { 494 ip->i_flags = vap->va_flags; 495 } else { 496 ip->i_flags &= 0xffff0000; 497 ip->i_flags |= (vap->va_flags & 0xffff); 498 } 499 ip->i_flag |= ICHG; 500 */ 501 } 502 return (error); 503 } 504 505 static int 506 kernfs_read(vp, uio, ioflag, cred) 507 struct vnode *vp; 508 struct uio *uio; 509 int ioflag; 510 struct ucred *cred; 511 { 512 struct kernfs_target *kt = VTOKERN(vp)->kf_kt; 513 char strbuf[KSTRING]; 514 int off = uio->uio_offset; 515 int len = 0; 516 char *cp = strbuf; 517 int error; 518 #ifdef KERNFS_DIAGNOSTIC 519 printf("kern_read %s\n", kt->kt_name); 520 #endif 521 522 error = kernfs_xread(kt, strbuf, sizeof(strbuf), &len); 523 if (error) 524 return (error); 525 cp = strbuf + off; 526 len -= off; 527 return (uiomove(cp, len, uio)); 528 } 529 530 static int 531 kernfs_write(vp, uio, ioflag, cred) 532 struct vnode *vp; 533 struct uio *uio; 534 int ioflag; 535 struct ucred *cred; 536 { 537 struct kernfs_target *kt = VTOKERN(vp)->kf_kt; 538 char strbuf[KSTRING]; 539 int len = uio->uio_resid; 540 char *cp = strbuf; 541 int xlen; 542 int error; 543 544 if (uio->uio_offset != 0) 545 return (EINVAL); 546 547 xlen = min(uio->uio_resid, KSTRING-1); 548 error = uiomove(strbuf, xlen, uio); 549 if (error) 550 return (error); 551 552 if (uio->uio_resid != 0) 553 return (EIO); 554 555 strbuf[xlen] = '\0'; 556 return (kernfs_xwrite(kt, strbuf, xlen)); 557 } 558 559 kernfs_readdir(vp, uio, cred, eofflagp) 560 struct vnode *vp; 561 struct uio *uio; 562 struct ucred *cred; 563 int *eofflagp; 564 { 565 struct filedesc *fdp; 566 int i; 567 int error; 568 569 i = uio->uio_offset / UIO_MX; 570 error = 0; 571 while (uio->uio_resid > 0) { 572 #ifdef KERNFS_DIAGNOSTIC 573 printf("kernfs_readdir: i = %d\n", i); 574 #endif 575 if (i >= nkernfs_targets) { 576 *eofflagp = 1; 577 break; 578 } 579 { 580 struct direct d; 581 struct direct *dp = &d; 582 struct kernfs_target *kt = &kernfs_targets[i]; 583 584 bzero((caddr_t) dp, UIO_MX); 585 586 dp->d_namlen = strlen(kt->kt_name); 587 bcopy(kt->kt_name, dp->d_name, dp->d_namlen+1); 588 589 #ifdef KERNFS_DIAGNOSTIC 590 printf("kernfs_readdir: name = %s, len = %d\n", 591 dp->d_name, dp->d_namlen); 592 #endif 593 /* 594 * Fill in the remaining fields 595 */ 596 dp->d_reclen = UIO_MX; 597 dp->d_ino = i + 3; 598 /* 599 * And ship to userland 600 */ 601 error = uiomove((caddr_t) dp, UIO_MX, uio); 602 if (error) 603 break; 604 } 605 i++; 606 } 607 608 uio->uio_offset = i * UIO_MX; 609 610 return (error); 611 } 612 613 kernfs_inactive(vp, p) 614 struct vnode *vp; 615 struct proc *p; 616 { 617 /* 618 * Clear out the v_type field to avoid 619 * nasty things happening in vgone(). 620 */ 621 vp->v_type = VNON; 622 #ifdef KERNFS_DIAGNOSTIC 623 printf("kernfs_inactive(%x)\n", vp); 624 #endif 625 return (0); 626 } 627 628 /* 629 * Print out the contents of a kernfs vnode. 630 */ 631 /* ARGSUSED */ 632 kernfs_print(vp) 633 struct vnode *vp; 634 { 635 printf("tag VT_KERNFS, kernfs vnode\n"); 636 } 637 638 /* 639 * kernfs vnode unsupported operation 640 */ 641 kernfs_enotsupp() 642 { 643 return (EOPNOTSUPP); 644 } 645 646 /* 647 * kernfs "should never get here" operation 648 */ 649 kernfs_badop() 650 { 651 panic("kernfs: bad op"); 652 /* NOTREACHED */ 653 } 654 655 /* 656 * kernfs vnode null operation 657 */ 658 kernfs_nullop() 659 { 660 return (0); 661 } 662 663 #define kernfs_create ((int (*) __P(( \ 664 struct nameidata *ndp, \ 665 struct vattr *vap, \ 666 struct proc *p))) kernfs_enotsupp) 667 #define kernfs_mknod ((int (*) __P(( \ 668 struct nameidata *ndp, \ 669 struct vattr *vap, \ 670 struct ucred *cred, \ 671 struct proc *p))) kernfs_enotsupp) 672 #define kernfs_close ((int (*) __P(( \ 673 struct vnode *vp, \ 674 int fflag, \ 675 struct ucred *cred, \ 676 struct proc *p))) nullop) 677 #define kernfs_ioctl ((int (*) __P(( \ 678 struct vnode *vp, \ 679 int command, \ 680 caddr_t data, \ 681 int fflag, \ 682 struct ucred *cred, \ 683 struct proc *p))) kernfs_enotsupp) 684 #define kernfs_select ((int (*) __P(( \ 685 struct vnode *vp, \ 686 int which, \ 687 int fflags, \ 688 struct ucred *cred, \ 689 struct proc *p))) kernfs_enotsupp) 690 #define kernfs_mmap ((int (*) __P(( \ 691 struct vnode *vp, \ 692 int fflags, \ 693 struct ucred *cred, \ 694 struct proc *p))) kernfs_enotsupp) 695 #define kernfs_fsync ((int (*) __P(( \ 696 struct vnode *vp, \ 697 int fflags, \ 698 struct ucred *cred, \ 699 int waitfor, \ 700 struct proc *p))) nullop) 701 #define kernfs_seek ((int (*) __P(( \ 702 struct vnode *vp, \ 703 off_t oldoff, \ 704 off_t newoff, \ 705 struct ucred *cred))) nullop) 706 #define kernfs_remove ((int (*) __P(( \ 707 struct nameidata *ndp, \ 708 struct proc *p))) kernfs_enotsupp) 709 #define kernfs_link ((int (*) __P(( \ 710 struct vnode *vp, \ 711 struct nameidata *ndp, \ 712 struct proc *p))) kernfs_enotsupp) 713 #define kernfs_rename ((int (*) __P(( \ 714 struct nameidata *fndp, \ 715 struct nameidata *tdnp, \ 716 struct proc *p))) kernfs_enotsupp) 717 #define kernfs_mkdir ((int (*) __P(( \ 718 struct nameidata *ndp, \ 719 struct vattr *vap, \ 720 struct proc *p))) kernfs_enotsupp) 721 #define kernfs_rmdir ((int (*) __P(( \ 722 struct nameidata *ndp, \ 723 struct proc *p))) kernfs_enotsupp) 724 #define kernfs_symlink ((int (*) __P(( \ 725 struct nameidata *ndp, \ 726 struct vattr *vap, \ 727 char *target, \ 728 struct proc *p))) kernfs_enotsupp) 729 #define kernfs_readlink ((int (*) __P(( \ 730 struct vnode *vp, \ 731 struct uio *uio, \ 732 struct ucred *cred))) kernfs_enotsupp) 733 #define kernfs_abortop ((int (*) __P(( \ 734 struct nameidata *ndp))) nullop) 735 #ifdef KERNFS_DIAGNOSTIC 736 int kernfs_reclaim(vp) 737 struct vnode *vp; 738 { 739 printf("kernfs_reclaim(%x)\n", vp); 740 return (0); 741 } 742 #else 743 #define kernfs_reclaim ((int (*) __P(( \ 744 struct vnode *vp))) nullop) 745 #endif 746 #define kernfs_lock ((int (*) __P(( \ 747 struct vnode *vp))) nullop) 748 #define kernfs_unlock ((int (*) __P(( \ 749 struct vnode *vp))) nullop) 750 #define kernfs_bmap ((int (*) __P(( \ 751 struct vnode *vp, \ 752 daddr_t bn, \ 753 struct vnode **vpp, \ 754 daddr_t *bnp))) kernfs_badop) 755 #define kernfs_strategy ((int (*) __P(( \ 756 struct buf *bp))) kernfs_badop) 757 #define kernfs_islocked ((int (*) __P(( \ 758 struct vnode *vp))) nullop) 759 #define kernfs_advlock ((int (*) __P(( \ 760 struct vnode *vp, \ 761 caddr_t id, \ 762 int op, \ 763 struct flock *fl, \ 764 int flags))) kernfs_enotsupp) 765 766 struct vnodeops kernfs_vnodeops = { 767 kernfs_lookup, /* lookup */ 768 kernfs_create, /* create */ 769 kernfs_mknod, /* mknod */ 770 kernfs_open, /* open */ 771 kernfs_close, /* close */ 772 kernfs_access, /* access */ 773 kernfs_getattr, /* getattr */ 774 kernfs_setattr, /* setattr */ 775 kernfs_read, /* read */ 776 kernfs_write, /* write */ 777 kernfs_ioctl, /* ioctl */ 778 kernfs_select, /* select */ 779 kernfs_mmap, /* mmap */ 780 kernfs_fsync, /* fsync */ 781 kernfs_seek, /* seek */ 782 kernfs_remove, /* remove */ 783 kernfs_link, /* link */ 784 kernfs_rename, /* rename */ 785 kernfs_mkdir, /* mkdir */ 786 kernfs_rmdir, /* rmdir */ 787 kernfs_symlink, /* symlink */ 788 kernfs_readdir, /* readdir */ 789 kernfs_readlink, /* readlink */ 790 kernfs_abortop, /* abortop */ 791 kernfs_inactive, /* inactive */ 792 kernfs_reclaim, /* reclaim */ 793 kernfs_lock, /* lock */ 794 kernfs_unlock, /* unlock */ 795 kernfs_bmap, /* bmap */ 796 kernfs_strategy, /* strategy */ 797 kernfs_print, /* print */ 798 kernfs_islocked, /* islocked */ 799 kernfs_advlock, /* advlock */ 800 }; 801