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