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