1 /* $NetBSD: kernfs_vnops.c,v 1.48 1996/10/25 21:58:00 cgd 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 62 #include <miscfs/genfs/genfs.h> 63 #include <miscfs/kernfs/kernfs.h> 64 65 #define KSTRING 256 /* Largest I/O available via this filesystem */ 66 #define UIO_MX 32 67 68 #define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH) 69 #define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) 70 #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 71 72 struct kern_target { 73 u_char kt_type; 74 u_char kt_namlen; 75 char *kt_name; 76 void *kt_data; 77 #define KTT_NULL 1 78 #define KTT_TIME 5 79 #define KTT_INT 17 80 #define KTT_STRING 31 81 #define KTT_HOSTNAME 47 82 #define KTT_AVENRUN 53 83 #define KTT_DEVICE 71 84 #define KTT_MSGBUF 89 85 u_char kt_tag; 86 u_char kt_vtype; 87 mode_t kt_mode; 88 } kern_targets[] = { 89 /* NOTE: The name must be less than UIO_MX-16 chars in length */ 90 #define N(s) sizeof(s)-1, s 91 /* name data tag type ro/rw */ 92 { DT_DIR, N("."), 0, KTT_NULL, VDIR, DIR_MODE }, 93 { DT_DIR, N(".."), 0, KTT_NULL, VDIR, DIR_MODE }, 94 { DT_REG, N("boottime"), &boottime.tv_sec, KTT_INT, VREG, READ_MODE }, 95 { DT_REG, N("copyright"), copyright, KTT_STRING, VREG, READ_MODE }, 96 { DT_REG, N("hostname"), 0, KTT_HOSTNAME, VREG, WRITE_MODE }, 97 { DT_REG, N("hz"), &hz, KTT_INT, VREG, READ_MODE }, 98 { DT_REG, N("loadavg"), 0, KTT_AVENRUN, VREG, READ_MODE }, 99 { DT_REG, N("msgbuf"), 0, KTT_MSGBUF, VREG, READ_MODE }, 100 { DT_REG, N("pagesize"), &cnt.v_page_size, KTT_INT, VREG, READ_MODE }, 101 { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE }, 102 #if 0 103 { DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE }, 104 #endif 105 { DT_BLK, N("rootdev"), &rootdev, KTT_DEVICE, VBLK, READ_MODE }, 106 { DT_CHR, N("rrootdev"), &rrootdev, KTT_DEVICE, VCHR, READ_MODE }, 107 { DT_REG, N("time"), 0, KTT_TIME, VREG, READ_MODE }, 108 { DT_REG, N("version"), version, KTT_STRING, VREG, READ_MODE }, 109 #undef N 110 }; 111 static int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); 112 113 int kernfs_lookup __P((void *)); 114 #define kernfs_create genfs_eopnotsupp 115 #define kernfs_mknod genfs_eopnotsupp 116 #define kernfs_open genfs_nullop 117 #define kernfs_close genfs_nullop 118 int kernfs_access __P((void *)); 119 int kernfs_getattr __P((void *)); 120 int kernfs_setattr __P((void *)); 121 int kernfs_read __P((void *)); 122 int kernfs_write __P((void *)); 123 #define kernfs_ioctl genfs_eopnotsupp 124 #define kernfs_poll genfs_poll 125 #define kernfs_mmap genfs_eopnotsupp 126 #define kernfs_fsync genfs_nullop 127 #define kernfs_seek genfs_nullop 128 #define kernfs_remove genfs_eopnotsupp 129 int kernfs_link __P((void *)); 130 #define kernfs_rename genfs_eopnotsupp 131 #define kernfs_mkdir genfs_eopnotsupp 132 #define kernfs_rmdir genfs_eopnotsupp 133 int kernfs_symlink __P((void *)); 134 int kernfs_readdir __P((void *)); 135 #define kernfs_readlink genfs_eopnotsupp 136 #define kernfs_abortop genfs_abortop 137 int kernfs_inactive __P((void *)); 138 int kernfs_reclaim __P((void *)); 139 #define kernfs_lock genfs_nullop 140 #define kernfs_unlock genfs_nullop 141 #define kernfs_bmap genfs_badop 142 #define kernfs_strategy genfs_badop 143 int kernfs_print __P((void *)); 144 #define kernfs_islocked genfs_nullop 145 int kernfs_pathconf __P((void *)); 146 #define kernfs_advlock genfs_eopnotsupp 147 #define kernfs_blkatoff genfs_eopnotsupp 148 #define kernfs_valloc genfs_eopnotsupp 149 #define kernfs_vfree genfs_nullop 150 #define kernfs_truncate genfs_eopnotsupp 151 #define kernfs_update genfs_nullop 152 #define kernfs_bwrite genfs_eopnotsupp 153 154 int kernfs_xread __P((struct kern_target *, int, char **, int)); 155 int kernfs_xwrite __P((struct kern_target *, char *, int)); 156 157 int (**kernfs_vnodeop_p) __P((void *)); 158 struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { 159 { &vop_default_desc, vn_default_error }, 160 { &vop_lookup_desc, kernfs_lookup }, /* lookup */ 161 { &vop_create_desc, kernfs_create }, /* create */ 162 { &vop_mknod_desc, kernfs_mknod }, /* mknod */ 163 { &vop_open_desc, kernfs_open }, /* open */ 164 { &vop_close_desc, kernfs_close }, /* close */ 165 { &vop_access_desc, kernfs_access }, /* access */ 166 { &vop_getattr_desc, kernfs_getattr }, /* getattr */ 167 { &vop_setattr_desc, kernfs_setattr }, /* setattr */ 168 { &vop_read_desc, kernfs_read }, /* read */ 169 { &vop_write_desc, kernfs_write }, /* write */ 170 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ 171 { &vop_poll_desc, kernfs_poll }, /* poll */ 172 { &vop_mmap_desc, kernfs_mmap }, /* mmap */ 173 { &vop_fsync_desc, kernfs_fsync }, /* fsync */ 174 { &vop_seek_desc, kernfs_seek }, /* seek */ 175 { &vop_remove_desc, kernfs_remove }, /* remove */ 176 { &vop_link_desc, kernfs_link }, /* link */ 177 { &vop_rename_desc, kernfs_rename }, /* rename */ 178 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */ 179 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */ 180 { &vop_symlink_desc, kernfs_symlink }, /* symlink */ 181 { &vop_readdir_desc, kernfs_readdir }, /* readdir */ 182 { &vop_readlink_desc, kernfs_readlink }, /* readlink */ 183 { &vop_abortop_desc, kernfs_abortop }, /* abortop */ 184 { &vop_inactive_desc, kernfs_inactive }, /* inactive */ 185 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */ 186 { &vop_lock_desc, kernfs_lock }, /* lock */ 187 { &vop_unlock_desc, kernfs_unlock }, /* unlock */ 188 { &vop_bmap_desc, kernfs_bmap }, /* bmap */ 189 { &vop_strategy_desc, kernfs_strategy }, /* strategy */ 190 { &vop_print_desc, kernfs_print }, /* print */ 191 { &vop_islocked_desc, kernfs_islocked }, /* islocked */ 192 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */ 193 { &vop_advlock_desc, kernfs_advlock }, /* advlock */ 194 { &vop_blkatoff_desc, kernfs_blkatoff }, /* blkatoff */ 195 { &vop_valloc_desc, kernfs_valloc }, /* valloc */ 196 { &vop_vfree_desc, kernfs_vfree }, /* vfree */ 197 { &vop_truncate_desc, kernfs_truncate }, /* truncate */ 198 { &vop_update_desc, kernfs_update }, /* update */ 199 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ 200 { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } 201 }; 202 struct vnodeopv_desc kernfs_vnodeop_opv_desc = 203 { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; 204 205 int 206 kernfs_xread(kt, off, bufp, len) 207 struct kern_target *kt; 208 int off; 209 char **bufp; 210 int len; 211 { 212 213 switch (kt->kt_tag) { 214 case KTT_TIME: { 215 struct timeval tv; 216 217 microtime(&tv); 218 sprintf(*bufp, "%ld %ld\n", tv.tv_sec, tv.tv_usec); 219 break; 220 } 221 222 case KTT_INT: { 223 int *ip = kt->kt_data; 224 225 sprintf(*bufp, "%d\n", *ip); 226 break; 227 } 228 229 case KTT_STRING: { 230 char *cp = kt->kt_data; 231 232 *bufp = cp; 233 break; 234 } 235 236 case KTT_MSGBUF: { 237 extern struct msgbuf *msgbufp; 238 long n; 239 240 if (off >= MSG_BSIZE) 241 return (0); 242 n = msgbufp->msg_bufx + off; 243 if (n >= MSG_BSIZE) 244 n -= MSG_BSIZE; 245 len = min(MSG_BSIZE - n, MSG_BSIZE - off); 246 *bufp = msgbufp->msg_bufc + n; 247 return (len); 248 } 249 250 case KTT_HOSTNAME: { 251 char *cp = hostname; 252 int xlen = hostnamelen; 253 254 if (xlen >= (len-2)) 255 return (EINVAL); 256 257 bcopy(cp, *bufp, xlen); 258 (*bufp)[xlen] = '\n'; 259 (*bufp)[xlen+1] = '\0'; 260 break; 261 } 262 263 case KTT_AVENRUN: 264 averunnable.fscale = FSCALE; 265 sprintf(*bufp, "%d %d %d %ld\n", 266 averunnable.ldavg[0], averunnable.ldavg[1], 267 averunnable.ldavg[2], averunnable.fscale); 268 break; 269 270 default: 271 return (0); 272 } 273 274 len = strlen(*bufp); 275 if (len <= off) 276 return (0); 277 *bufp += off; 278 return (len - off); 279 } 280 281 int 282 kernfs_xwrite(kt, buf, len) 283 struct kern_target *kt; 284 char *buf; 285 int len; 286 { 287 288 switch (kt->kt_tag) { 289 case KTT_HOSTNAME: 290 if (buf[len-1] == '\n') 291 --len; 292 bcopy(buf, hostname, len); 293 hostname[len] = '\0'; 294 hostnamelen = len; 295 return (0); 296 297 default: 298 return (EIO); 299 } 300 } 301 302 303 /* 304 * vp is the current namei directory 305 * ndp is the name to locate in that directory... 306 */ 307 int 308 kernfs_lookup(v) 309 void *v; 310 { 311 struct vop_lookup_args /* { 312 struct vnode * a_dvp; 313 struct vnode ** a_vpp; 314 struct componentname * a_cnp; 315 } */ *ap = v; 316 struct componentname *cnp = ap->a_cnp; 317 struct vnode **vpp = ap->a_vpp; 318 struct vnode *dvp = ap->a_dvp; 319 const char *pname = cnp->cn_nameptr; 320 struct kern_target *kt; 321 struct vnode *fvp; 322 int error, i; 323 324 #ifdef KERNFS_DIAGNOSTIC 325 printf("kernfs_lookup(%x)\n", ap); 326 printf("kernfs_lookup(dp = %x, vpp = %x, cnp = %x)\n", dvp, vpp, ap->a_cnp); 327 printf("kernfs_lookup(%s)\n", pname); 328 #endif 329 330 *vpp = NULLVP; 331 332 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 333 return (EROFS); 334 335 if (cnp->cn_namelen == 1 && *pname == '.') { 336 *vpp = dvp; 337 VREF(dvp); 338 /*VOP_LOCK(dvp);*/ 339 return (0); 340 } 341 342 #if 0 343 if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) { 344 *vpp = rootdir; 345 VREF(rootdir); 346 VOP_LOCK(rootdir); 347 return (0); 348 } 349 #endif 350 351 for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) { 352 if (cnp->cn_namelen == kt->kt_namlen && 353 bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) 354 goto found; 355 } 356 357 #ifdef KERNFS_DIAGNOSTIC 358 printf("kernfs_lookup: i = %d, failed", i); 359 #endif 360 361 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 362 363 found: 364 if (kt->kt_tag == KTT_DEVICE) { 365 dev_t *dp = kt->kt_data; 366 loop: 367 if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) 368 return (ENOENT); 369 *vpp = fvp; 370 if (vget(fvp, 1)) 371 goto loop; 372 return (0); 373 } 374 375 #ifdef KERNFS_DIAGNOSTIC 376 printf("kernfs_lookup: allocate new vnode\n"); 377 #endif 378 error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp); 379 if (error) 380 return (error); 381 382 MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP, 383 M_WAITOK); 384 VTOKERN(fvp)->kf_kt = kt; 385 fvp->v_type = kt->kt_vtype; 386 *vpp = fvp; 387 388 #ifdef KERNFS_DIAGNOSTIC 389 printf("kernfs_lookup: newvp = %x\n", fvp); 390 #endif 391 return (0); 392 } 393 394 int 395 kernfs_access(v) 396 void *v; 397 { 398 struct vop_access_args /* { 399 struct vnode *a_vp; 400 int a_mode; 401 struct ucred *a_cred; 402 struct proc *a_p; 403 } */ *ap = v; 404 struct vnode *vp = ap->a_vp; 405 mode_t fmode = 406 (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_kt->kt_mode; 407 408 return (vaccess(fmode, (uid_t)0, (gid_t)0, ap->a_mode, ap->a_cred)); 409 } 410 411 int 412 kernfs_getattr(v) 413 void *v; 414 { 415 struct vop_getattr_args /* { 416 struct vnode *a_vp; 417 struct vattr *a_vap; 418 struct ucred *a_cred; 419 struct proc *a_p; 420 } */ *ap = v; 421 struct vnode *vp = ap->a_vp; 422 struct vattr *vap = ap->a_vap; 423 struct timeval tv; 424 int error = 0; 425 char strbuf[KSTRING], *buf; 426 427 bzero((caddr_t) vap, sizeof(*vap)); 428 vattr_null(vap); 429 vap->va_uid = 0; 430 vap->va_gid = 0; 431 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 432 vap->va_size = 0; 433 vap->va_blocksize = DEV_BSIZE; 434 microtime(&tv); 435 TIMEVAL_TO_TIMESPEC(&tv, &vap->va_atime); 436 vap->va_mtime = vap->va_atime; 437 vap->va_ctime = vap->va_ctime; 438 vap->va_gen = 0; 439 vap->va_flags = 0; 440 vap->va_rdev = 0; 441 vap->va_bytes = 0; 442 443 if (vp->v_flag & VROOT) { 444 #ifdef KERNFS_DIAGNOSTIC 445 printf("kernfs_getattr: stat rootdir\n"); 446 #endif 447 vap->va_type = VDIR; 448 vap->va_mode = DIR_MODE; 449 vap->va_nlink = 2; 450 vap->va_fileid = 2; 451 vap->va_size = DEV_BSIZE; 452 } else { 453 struct kern_target *kt = VTOKERN(vp)->kf_kt; 454 int nbytes, total; 455 #ifdef KERNFS_DIAGNOSTIC 456 printf("kernfs_getattr: stat target %s\n", kt->kt_name); 457 #endif 458 vap->va_type = kt->kt_vtype; 459 vap->va_mode = kt->kt_mode; 460 vap->va_nlink = 1; 461 vap->va_fileid = 3 + (kt - kern_targets); 462 total = 0; 463 while (buf = strbuf, 464 nbytes = kernfs_xread(kt, total, &buf, sizeof(strbuf))) 465 total += nbytes; 466 vap->va_size = total; 467 } 468 469 #ifdef KERNFS_DIAGNOSTIC 470 printf("kernfs_getattr: return error %d\n", error); 471 #endif 472 return (error); 473 } 474 475 /*ARGSUSED*/ 476 int 477 kernfs_setattr(v) 478 void *v; 479 { 480 /* 481 * Silently ignore attribute changes. 482 * This allows for open with truncate to have no 483 * effect until some data is written. I want to 484 * do it this way because all writes are atomic. 485 */ 486 return (0); 487 } 488 489 int 490 kernfs_read(v) 491 void *v; 492 { 493 struct vop_read_args /* { 494 struct vnode *a_vp; 495 struct uio *a_uio; 496 int a_ioflag; 497 struct ucred *a_cred; 498 } */ *ap = v; 499 struct vnode *vp = ap->a_vp; 500 struct uio *uio = ap->a_uio; 501 struct kern_target *kt; 502 char strbuf[KSTRING], *buf; 503 int off, len; 504 int error; 505 506 if (vp->v_type == VDIR) 507 return (EOPNOTSUPP); 508 509 kt = VTOKERN(vp)->kf_kt; 510 511 #ifdef KERNFS_DIAGNOSTIC 512 printf("kern_read %s\n", kt->kt_name); 513 #endif 514 515 off = uio->uio_offset; 516 #if 0 517 while (buf = strbuf, 518 #else 519 if (buf = strbuf, 520 #endif 521 len = kernfs_xread(kt, off, &buf, sizeof(strbuf))) { 522 if ((error = uiomove(buf, len, uio)) != 0) 523 return (error); 524 off += len; 525 } 526 return (0); 527 } 528 529 int 530 kernfs_write(v) 531 void *v; 532 { 533 struct vop_write_args /* { 534 struct vnode *a_vp; 535 struct uio *a_uio; 536 int a_ioflag; 537 struct ucred *a_cred; 538 } */ *ap = v; 539 struct vnode *vp = ap->a_vp; 540 struct uio *uio = ap->a_uio; 541 struct kern_target *kt; 542 int error, xlen; 543 char strbuf[KSTRING]; 544 545 if (vp->v_type == VDIR) 546 return (EOPNOTSUPP); 547 548 kt = VTOKERN(vp)->kf_kt; 549 550 if (uio->uio_offset != 0) 551 return (EINVAL); 552 553 xlen = min(uio->uio_resid, KSTRING-1); 554 if ((error = uiomove(strbuf, xlen, uio)) != 0) 555 return (error); 556 557 if (uio->uio_resid != 0) 558 return (EIO); 559 560 strbuf[xlen] = '\0'; 561 xlen = strlen(strbuf); 562 return (kernfs_xwrite(kt, strbuf, xlen)); 563 } 564 565 int 566 kernfs_readdir(v) 567 void *v; 568 { 569 struct vop_readdir_args /* { 570 struct vnode *a_vp; 571 struct uio *a_uio; 572 struct ucred *a_cred; 573 int *a_eofflag; 574 u_long *a_cookies; 575 int a_ncookies; 576 } */ *ap = v; 577 struct uio *uio = ap->a_uio; 578 struct dirent d; 579 struct kern_target *kt; 580 int i; 581 int error; 582 u_long *cookies = ap->a_cookies; 583 int ncookies = ap->a_ncookies; 584 585 if (ap->a_vp->v_type != VDIR) 586 return (ENOTDIR); 587 588 if (uio->uio_resid < UIO_MX) 589 return (EINVAL); 590 if (uio->uio_offset < 0) 591 return (EINVAL); 592 593 error = 0; 594 i = uio->uio_offset; 595 bzero((caddr_t)&d, UIO_MX); 596 d.d_reclen = UIO_MX; 597 598 for (kt = &kern_targets[i]; 599 uio->uio_resid >= UIO_MX && i < nkern_targets; kt++, i++) { 600 #ifdef KERNFS_DIAGNOSTIC 601 printf("kernfs_readdir: i = %d\n", i); 602 #endif 603 604 if (kt->kt_tag == KTT_DEVICE) { 605 dev_t *dp = kt->kt_data; 606 struct vnode *fvp; 607 608 if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) 609 continue; 610 } 611 612 d.d_fileno = i + 3; 613 d.d_namlen = kt->kt_namlen; 614 bcopy(kt->kt_name, d.d_name, kt->kt_namlen + 1); 615 d.d_type = kt->kt_type; 616 617 if ((error = uiomove((caddr_t)&d, UIO_MX, uio)) != 0) 618 break; 619 if (ncookies-- > 0) 620 *cookies++ = i + 1; 621 } 622 623 uio->uio_offset = i; 624 return (error); 625 } 626 627 int 628 kernfs_inactive(v) 629 void *v; 630 { 631 struct vop_inactive_args /* { 632 struct vnode *a_vp; 633 } */ *ap = v; 634 struct vnode *vp = ap->a_vp; 635 636 #ifdef KERNFS_DIAGNOSTIC 637 printf("kernfs_inactive(%x)\n", vp); 638 #endif 639 /* 640 * Clear out the v_type field to avoid 641 * nasty things happening in vgone(). 642 */ 643 vp->v_type = VNON; 644 return (0); 645 } 646 647 int 648 kernfs_reclaim(v) 649 void *v; 650 { 651 struct vop_reclaim_args /* { 652 struct vnode *a_vp; 653 } */ *ap = v; 654 struct vnode *vp = ap->a_vp; 655 656 #ifdef KERNFS_DIAGNOSTIC 657 printf("kernfs_reclaim(%x)\n", vp); 658 #endif 659 if (vp->v_data) { 660 FREE(vp->v_data, M_TEMP); 661 vp->v_data = 0; 662 } 663 return (0); 664 } 665 666 /* 667 * Return POSIX pathconf information applicable to special devices. 668 */ 669 int 670 kernfs_pathconf(v) 671 void *v; 672 { 673 struct vop_pathconf_args /* { 674 struct vnode *a_vp; 675 int a_name; 676 register_t *a_retval; 677 } */ *ap = v; 678 679 switch (ap->a_name) { 680 case _PC_LINK_MAX: 681 *ap->a_retval = LINK_MAX; 682 return (0); 683 case _PC_MAX_CANON: 684 *ap->a_retval = MAX_CANON; 685 return (0); 686 case _PC_MAX_INPUT: 687 *ap->a_retval = MAX_INPUT; 688 return (0); 689 case _PC_PIPE_BUF: 690 *ap->a_retval = PIPE_BUF; 691 return (0); 692 case _PC_CHOWN_RESTRICTED: 693 *ap->a_retval = 1; 694 return (0); 695 case _PC_VDISABLE: 696 *ap->a_retval = _POSIX_VDISABLE; 697 return (0); 698 default: 699 return (EINVAL); 700 } 701 /* NOTREACHED */ 702 } 703 704 /* 705 * Print out the contents of a /dev/fd vnode. 706 */ 707 /* ARGSUSED */ 708 int 709 kernfs_print(v) 710 void *v; 711 { 712 713 printf("tag VT_KERNFS, kernfs vnode\n"); 714 return (0); 715 } 716 717 int 718 kernfs_link(v) 719 void *v; 720 { 721 struct vop_link_args /* { 722 struct vnode *a_dvp; 723 struct vnode *a_vp; 724 struct componentname *a_cnp; 725 } */ *ap = v; 726 727 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 728 vput(ap->a_dvp); 729 return (EROFS); 730 } 731 732 int 733 kernfs_symlink(v) 734 void *v; 735 { 736 struct vop_symlink_args /* { 737 struct vnode *a_dvp; 738 struct vnode **a_vpp; 739 struct componentname *a_cnp; 740 struct vattr *a_vap; 741 char *a_target; 742 } */ *ap = v; 743 744 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 745 vput(ap->a_dvp); 746 return (EROFS); 747 } 748