1 /* $NetBSD: kernfs_vnops.c,v 1.151 2014/04/08 17:56:10 christos 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. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95 35 */ 36 37 /* 38 * Kernel parameter filesystem (/kern) 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: kernfs_vnops.c,v 1.151 2014/04/08 17:56:10 christos Exp $"); 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/kernel.h> 47 #include <sys/vmmeter.h> 48 #include <sys/time.h> 49 #include <sys/proc.h> 50 #include <sys/vnode.h> 51 #include <sys/malloc.h> 52 #include <sys/file.h> 53 #include <sys/stat.h> 54 #include <sys/mount.h> 55 #include <sys/namei.h> 56 #include <sys/buf.h> 57 #include <sys/dirent.h> 58 #include <sys/msgbuf.h> 59 60 #include <miscfs/genfs/genfs.h> 61 #include <miscfs/kernfs/kernfs.h> 62 #include <miscfs/specfs/specdev.h> 63 64 #include <uvm/uvm_extern.h> 65 66 #define KSTRING 256 /* Largest I/O available via this filesystem */ 67 #define UIO_MX 32 68 69 #define READ_MODE (S_IRUSR|S_IRGRP|S_IROTH) 70 #define WRITE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) 71 #define UREAD_MODE (S_IRUSR) 72 #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 73 #define UDIR_MODE (S_IRUSR|S_IXUSR) 74 75 #define N(s) sizeof(s)-1, s 76 const struct kern_target kern_targets[] = { 77 /* NOTE: The name must be less than UIO_MX-16 chars in length */ 78 /* name data tag type ro/rw */ 79 { DT_DIR, N("."), 0, KFSkern, VDIR, DIR_MODE }, 80 { DT_DIR, N(".."), 0, KFSroot, VDIR, DIR_MODE }, 81 { DT_REG, N("boottime"), &boottime.tv_sec, KFSint, VREG, READ_MODE }, 82 /* XXXUNCONST */ 83 { DT_REG, N("copyright"), __UNCONST(copyright), 84 KFSstring, VREG, READ_MODE }, 85 { DT_REG, N("hostname"), 0, KFShostname, VREG, WRITE_MODE }, 86 { DT_REG, N("hz"), &hz, KFSint, VREG, READ_MODE }, 87 { DT_REG, N("loadavg"), 0, KFSavenrun, VREG, READ_MODE }, 88 { DT_REG, N("msgbuf"), 0, KFSmsgbuf, VREG, READ_MODE }, 89 { DT_REG, N("pagesize"), &uvmexp.pagesize, KFSint, VREG, READ_MODE }, 90 { DT_REG, N("physmem"), &physmem, KFSint, VREG, READ_MODE }, 91 #if 0 92 { DT_DIR, N("root"), 0, KFSnull, VDIR, DIR_MODE }, 93 #endif 94 { DT_BLK, N("rootdev"), &rootdev, KFSdevice, VBLK, READ_MODE }, 95 { DT_CHR, N("rrootdev"), &rrootdev, KFSdevice, VCHR, READ_MODE }, 96 { DT_REG, N("time"), 0, KFStime, VREG, READ_MODE }, 97 /* XXXUNCONST */ 98 { DT_REG, N("version"), __UNCONST(version), 99 KFSstring, VREG, READ_MODE }, 100 }; 101 const struct kern_target subdir_targets[] = { 102 /* NOTE: The name must be less than UIO_MX-16 chars in length */ 103 /* name data tag type ro/rw */ 104 { DT_DIR, N("."), 0, KFSsubdir, VDIR, DIR_MODE }, 105 { DT_DIR, N(".."), 0, KFSkern, VDIR, DIR_MODE }, 106 }; 107 #undef N 108 SIMPLEQ_HEAD(,dyn_kern_target) dyn_kern_targets = 109 SIMPLEQ_HEAD_INITIALIZER(dyn_kern_targets); 110 int nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); 111 const int static_nkern_targets = sizeof(kern_targets) / sizeof(kern_targets[0]); 112 int nkern_dirs = 2; 113 114 int kernfs_try_fileop(kfstype, kfsfileop, void *, int); 115 int kernfs_try_xread(kfstype, const struct kernfs_node *, char **, 116 size_t, int); 117 int kernfs_try_xwrite(kfstype, const struct kernfs_node *, char *, 118 size_t, int); 119 120 static int kernfs_default_xread(void *v); 121 static int kernfs_default_xwrite(void *v); 122 static int kernfs_default_fileop_getattr(void *); 123 124 /* must include all fileop's */ 125 const struct kernfs_fileop kernfs_default_fileops[] = { 126 { .kf_fileop = KERNFS_XREAD }, 127 { .kf_fileop = KERNFS_XWRITE }, 128 { .kf_fileop = KERNFS_FILEOP_OPEN }, 129 { .kf_fileop = KERNFS_FILEOP_GETATTR, 130 .kf_vop = kernfs_default_fileop_getattr }, 131 { .kf_fileop = KERNFS_FILEOP_IOCTL }, 132 { .kf_fileop = KERNFS_FILEOP_CLOSE }, 133 { .kf_fileop = KERNFS_FILEOP_READ, 134 .kf_vop = kernfs_default_xread }, 135 { .kf_fileop = KERNFS_FILEOP_WRITE, 136 .kf_vop = kernfs_default_xwrite }, 137 }; 138 139 int kernfs_lookup(void *); 140 #define kernfs_create genfs_eopnotsupp 141 #define kernfs_mknod genfs_eopnotsupp 142 int kernfs_open(void *); 143 int kernfs_close(void *); 144 int kernfs_access(void *); 145 int kernfs_getattr(void *); 146 int kernfs_setattr(void *); 147 int kernfs_read(void *); 148 int kernfs_write(void *); 149 #define kernfs_fcntl genfs_fcntl 150 int kernfs_ioctl(void *); 151 #define kernfs_poll genfs_poll 152 #define kernfs_revoke genfs_revoke 153 #define kernfs_fsync genfs_nullop 154 #define kernfs_seek genfs_nullop 155 #define kernfs_remove genfs_eopnotsupp 156 int kernfs_link(void *); 157 #define kernfs_rename genfs_eopnotsupp 158 #define kernfs_mkdir genfs_eopnotsupp 159 #define kernfs_rmdir genfs_eopnotsupp 160 int kernfs_symlink(void *); 161 int kernfs_readdir(void *); 162 #define kernfs_readlink genfs_eopnotsupp 163 #define kernfs_abortop genfs_abortop 164 int kernfs_inactive(void *); 165 int kernfs_reclaim(void *); 166 #define kernfs_lock genfs_lock 167 #define kernfs_unlock genfs_unlock 168 #define kernfs_bmap genfs_badop 169 #define kernfs_strategy genfs_badop 170 int kernfs_print(void *); 171 #define kernfs_islocked genfs_islocked 172 int kernfs_pathconf(void *); 173 #define kernfs_advlock genfs_einval 174 #define kernfs_bwrite genfs_eopnotsupp 175 #define kernfs_putpages genfs_putpages 176 177 static int kernfs_xread(struct kernfs_node *, int, char **, 178 size_t, size_t *); 179 static int kernfs_xwrite(const struct kernfs_node *, char *, size_t); 180 181 int (**kernfs_vnodeop_p)(void *); 182 const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { 183 { &vop_default_desc, vn_default_error }, 184 { &vop_lookup_desc, kernfs_lookup }, /* lookup */ 185 { &vop_create_desc, kernfs_create }, /* create */ 186 { &vop_mknod_desc, kernfs_mknod }, /* mknod */ 187 { &vop_open_desc, kernfs_open }, /* open */ 188 { &vop_close_desc, kernfs_close }, /* close */ 189 { &vop_access_desc, kernfs_access }, /* access */ 190 { &vop_getattr_desc, kernfs_getattr }, /* getattr */ 191 { &vop_setattr_desc, kernfs_setattr }, /* setattr */ 192 { &vop_read_desc, kernfs_read }, /* read */ 193 { &vop_write_desc, kernfs_write }, /* write */ 194 { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */ 195 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ 196 { &vop_poll_desc, kernfs_poll }, /* poll */ 197 { &vop_revoke_desc, kernfs_revoke }, /* revoke */ 198 { &vop_fsync_desc, kernfs_fsync }, /* fsync */ 199 { &vop_seek_desc, kernfs_seek }, /* seek */ 200 { &vop_remove_desc, kernfs_remove }, /* remove */ 201 { &vop_link_desc, kernfs_link }, /* link */ 202 { &vop_rename_desc, kernfs_rename }, /* rename */ 203 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */ 204 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */ 205 { &vop_symlink_desc, kernfs_symlink }, /* symlink */ 206 { &vop_readdir_desc, kernfs_readdir }, /* readdir */ 207 { &vop_readlink_desc, kernfs_readlink }, /* readlink */ 208 { &vop_abortop_desc, kernfs_abortop }, /* abortop */ 209 { &vop_inactive_desc, kernfs_inactive }, /* inactive */ 210 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */ 211 { &vop_lock_desc, kernfs_lock }, /* lock */ 212 { &vop_unlock_desc, kernfs_unlock }, /* unlock */ 213 { &vop_bmap_desc, kernfs_bmap }, /* bmap */ 214 { &vop_strategy_desc, kernfs_strategy }, /* strategy */ 215 { &vop_print_desc, kernfs_print }, /* print */ 216 { &vop_islocked_desc, kernfs_islocked }, /* islocked */ 217 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */ 218 { &vop_advlock_desc, kernfs_advlock }, /* advlock */ 219 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ 220 { &vop_putpages_desc, kernfs_putpages }, /* putpages */ 221 { NULL, NULL } 222 }; 223 const struct vnodeopv_desc kernfs_vnodeop_opv_desc = 224 { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; 225 226 static inline int 227 kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b) 228 { 229 if (a->kf_type < b->kf_type) 230 return -1; 231 if (a->kf_type > b->kf_type) 232 return 1; 233 if (a->kf_fileop < b->kf_fileop) 234 return -1; 235 if (a->kf_fileop > b->kf_fileop) 236 return 1; 237 return (0); 238 } 239 240 SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree = 241 SPLAY_INITIALIZER(kfsfileoptree); 242 SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare); 243 SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare); 244 245 kfstype 246 kernfs_alloctype(int nkf, const struct kernfs_fileop *kf) 247 { 248 static u_char nextfreetype = KFSlasttype; 249 struct kernfs_fileop *dkf, *fkf, skf; 250 int i; 251 252 /* XXX need to keep track of dkf's memory if we support 253 deallocating types */ 254 dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK); 255 memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops)); 256 257 for (i = 0; i < sizeof(kernfs_default_fileops) / 258 sizeof(kernfs_default_fileops[0]); i++) { 259 dkf[i].kf_type = nextfreetype; 260 SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]); 261 } 262 263 for (i = 0; i < nkf; i++) { 264 skf.kf_type = nextfreetype; 265 skf.kf_fileop = kf[i].kf_fileop; 266 if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 267 fkf->kf_vop = kf[i].kf_vop; 268 } 269 270 return nextfreetype++; 271 } 272 273 int 274 kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error) 275 { 276 struct kernfs_fileop *kf, skf; 277 278 skf.kf_type = type; 279 skf.kf_fileop = fileop; 280 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 281 if (kf->kf_vop) 282 return kf->kf_vop(v); 283 return error; 284 } 285 286 int 287 kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp, 288 size_t len, int error) 289 { 290 struct kernfs_fileop *kf, skf; 291 292 skf.kf_type = type; 293 skf.kf_fileop = KERNFS_XREAD; 294 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 295 if (kf->kf_xread) 296 return kf->kf_xread(kfs, bfp, len); 297 return error; 298 } 299 300 int 301 kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf, 302 size_t len, int error) 303 { 304 struct kernfs_fileop *kf, skf; 305 306 skf.kf_type = type; 307 skf.kf_fileop = KERNFS_XWRITE; 308 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 309 if (kf->kf_xwrite) 310 return kf->kf_xwrite(kfs, bf, len); 311 return error; 312 } 313 314 int 315 kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt) 316 { 317 struct kernfs_subdir *ks, *parent; 318 319 if (pkt == NULL) { 320 SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue); 321 nkern_targets++; 322 if (dkt->dkt_kt.kt_vtype == VDIR) 323 nkern_dirs++; 324 } else { 325 parent = (struct kernfs_subdir *)pkt->kt_data; 326 SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue); 327 parent->ks_nentries++; 328 if (dkt->dkt_kt.kt_vtype == VDIR) 329 parent->ks_dirs++; 330 } 331 if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) { 332 ks = malloc(sizeof(struct kernfs_subdir), 333 M_TEMP, M_WAITOK); 334 SIMPLEQ_INIT(&ks->ks_entries); 335 ks->ks_nentries = 2; /* . and .. */ 336 ks->ks_dirs = 2; 337 ks->ks_parent = pkt ? pkt : &kern_targets[0]; 338 dkt->dkt_kt.kt_data = ks; 339 } 340 return 0; 341 } 342 343 static int 344 kernfs_xread(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen) 345 { 346 const struct kern_target *kt; 347 int err; 348 349 kt = kfs->kfs_kt; 350 351 switch (kfs->kfs_type) { 352 case KFStime: { 353 struct timeval tv; 354 355 microtime(&tv); 356 snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec, 357 (long)tv.tv_usec); 358 break; 359 } 360 361 case KFSint: { 362 int *ip = kt->kt_data; 363 364 snprintf(*bufp, len, "%d\n", *ip); 365 break; 366 } 367 368 case KFSstring: { 369 char *cp = kt->kt_data; 370 371 *bufp = cp; 372 break; 373 } 374 375 case KFSmsgbuf: { 376 long n; 377 378 /* 379 * deal with cases where the message buffer has 380 * become corrupted. 381 */ 382 if (!msgbufenabled || msgbufp->msg_magic != MSG_MAGIC) { 383 msgbufenabled = 0; 384 return (ENXIO); 385 } 386 387 /* 388 * Note that reads of /kern/msgbuf won't necessarily yield 389 * consistent results, if the message buffer is modified 390 * while the read is in progress. The worst that can happen 391 * is that incorrect data will be read. There's no way 392 * that this can crash the system unless the values in the 393 * message buffer header are corrupted, but that'll cause 394 * the system to die anyway. 395 */ 396 if (off >= msgbufp->msg_bufs) { 397 *wrlen = 0; 398 return (0); 399 } 400 n = msgbufp->msg_bufx + off; 401 if (n >= msgbufp->msg_bufs) 402 n -= msgbufp->msg_bufs; 403 len = min(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off); 404 *bufp = msgbufp->msg_bufc + n; 405 *wrlen = len; 406 return (0); 407 } 408 409 case KFShostname: { 410 char *cp = hostname; 411 size_t xlen = hostnamelen; 412 413 if (xlen >= (len - 2)) 414 return (EINVAL); 415 416 memcpy(*bufp, cp, xlen); 417 (*bufp)[xlen] = '\n'; 418 (*bufp)[xlen+1] = '\0'; 419 break; 420 } 421 422 case KFSavenrun: 423 averunnable.fscale = FSCALE; 424 snprintf(*bufp, len, "%d %d %d %ld\n", 425 averunnable.ldavg[0], averunnable.ldavg[1], 426 averunnable.ldavg[2], averunnable.fscale); 427 break; 428 429 default: 430 err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len, 431 EOPNOTSUPP); 432 if (err) 433 return err; 434 } 435 436 len = strlen(*bufp); 437 if (len <= off) 438 *wrlen = 0; 439 else { 440 *bufp += off; 441 *wrlen = len - off; 442 } 443 return (0); 444 } 445 446 static int 447 kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len) 448 { 449 450 switch (kfs->kfs_type) { 451 case KFShostname: 452 if (bf[len-1] == '\n') 453 --len; 454 memcpy(hostname, bf, len); 455 hostname[len] = '\0'; 456 hostnamelen = (size_t) len; 457 return (0); 458 459 default: 460 return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO); 461 } 462 } 463 464 465 /* 466 * vp is the current namei directory 467 * ndp is the name to locate in that directory... 468 */ 469 int 470 kernfs_lookup(void *v) 471 { 472 struct vop_lookup_v2_args /* { 473 struct vnode * a_dvp; 474 struct vnode ** a_vpp; 475 struct componentname * a_cnp; 476 } */ *ap = v; 477 struct componentname *cnp = ap->a_cnp; 478 struct vnode **vpp = ap->a_vpp; 479 struct vnode *dvp = ap->a_dvp; 480 const char *pname = cnp->cn_nameptr; 481 const struct kernfs_node *kfs; 482 const struct kern_target *kt; 483 const struct dyn_kern_target *dkt; 484 const struct kernfs_subdir *ks; 485 int error, i; 486 487 *vpp = NULLVP; 488 489 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 490 return (EROFS); 491 492 if (cnp->cn_namelen == 1 && *pname == '.') { 493 *vpp = dvp; 494 vref(dvp); 495 return (0); 496 } 497 498 kfs = VTOKERN(dvp); 499 switch (kfs->kfs_type) { 500 case KFSkern: 501 /* 502 * Shouldn't get here with .. in the root node. 503 */ 504 if (cnp->cn_flags & ISDOTDOT) 505 return (EIO); 506 507 for (i = 0; i < static_nkern_targets; i++) { 508 kt = &kern_targets[i]; 509 if (cnp->cn_namelen == kt->kt_namlen && 510 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) 511 goto found; 512 } 513 SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) { 514 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && 515 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { 516 kt = &dkt->dkt_kt; 517 goto found; 518 } 519 } 520 break; 521 522 found: 523 error = kernfs_allocvp(dvp->v_mount, vpp, kt->kt_tag, kt, 0); 524 if (error) 525 return error; 526 VOP_UNLOCK(*vpp); 527 return 0; 528 529 case KFSsubdir: 530 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 531 if (cnp->cn_flags & ISDOTDOT) { 532 kt = ks->ks_parent; 533 goto found; 534 } 535 536 SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) { 537 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && 538 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { 539 kt = &dkt->dkt_kt; 540 goto found; 541 } 542 } 543 break; 544 545 default: 546 return (ENOTDIR); 547 } 548 549 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 550 } 551 552 int 553 kernfs_open(void *v) 554 { 555 struct vop_open_args /* { 556 struct vnode *a_vp; 557 int a_mode; 558 kauth_cred_t a_cred; 559 } */ *ap = v; 560 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 561 562 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN, v, 0); 563 } 564 565 int 566 kernfs_close(void *v) 567 { 568 struct vop_close_args /* { 569 struct vnode *a_vp; 570 int a_fflag; 571 kauth_cred_t a_cred; 572 } */ *ap = v; 573 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 574 575 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE, v, 0); 576 } 577 578 int 579 kernfs_access(void *v) 580 { 581 struct vop_access_args /* { 582 struct vnode *a_vp; 583 int a_mode; 584 kauth_cred_t a_cred; 585 } */ *ap = v; 586 struct vattr va; 587 int error; 588 589 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0) 590 return (error); 591 592 return kauth_authorize_vnode(ap->a_cred, 593 KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode), 594 ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, 595 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 596 } 597 598 static int 599 kernfs_default_fileop_getattr(void *v) 600 { 601 struct vop_getattr_args /* { 602 struct vnode *a_vp; 603 struct vattr *a_vap; 604 kauth_cred_t a_cred; 605 } */ *ap = v; 606 struct vattr *vap = ap->a_vap; 607 608 vap->va_nlink = 1; 609 vap->va_bytes = vap->va_size = 0; 610 611 return 0; 612 } 613 614 int 615 kernfs_getattr(void *v) 616 { 617 struct vop_getattr_args /* { 618 struct vnode *a_vp; 619 struct vattr *a_vap; 620 kauth_cred_t a_cred; 621 } */ *ap = v; 622 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 623 struct kernfs_subdir *ks; 624 struct vattr *vap = ap->a_vap; 625 int error = 0; 626 char strbuf[KSTRING], *bf; 627 size_t nread, total; 628 629 vattr_null(vap); 630 vap->va_type = ap->a_vp->v_type; 631 vap->va_uid = 0; 632 vap->va_gid = 0; 633 vap->va_mode = kfs->kfs_mode; 634 vap->va_fileid = kfs->kfs_fileno; 635 vap->va_flags = 0; 636 vap->va_size = 0; 637 vap->va_blocksize = DEV_BSIZE; 638 /* Make all times be current TOD, except for the "boottime" node. */ 639 if (kfs->kfs_kt->kt_namlen == 8 && 640 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) { 641 vap->va_ctime = boottime; 642 } else { 643 getnanotime(&vap->va_ctime); 644 } 645 vap->va_atime = vap->va_mtime = vap->va_ctime; 646 vap->va_gen = 0; 647 vap->va_flags = 0; 648 vap->va_rdev = 0; 649 vap->va_bytes = 0; 650 651 switch (kfs->kfs_type) { 652 case KFSkern: 653 vap->va_nlink = nkern_dirs; 654 vap->va_bytes = vap->va_size = DEV_BSIZE; 655 break; 656 657 case KFSdevice: 658 vap->va_nlink = 1; 659 vap->va_rdev = ap->a_vp->v_rdev; 660 break; 661 662 case KFSroot: 663 vap->va_nlink = 1; 664 vap->va_bytes = vap->va_size = DEV_BSIZE; 665 break; 666 667 case KFSsubdir: 668 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 669 vap->va_nlink = ks->ks_dirs; 670 vap->va_bytes = vap->va_size = DEV_BSIZE; 671 break; 672 673 case KFSnull: 674 case KFStime: 675 case KFSint: 676 case KFSstring: 677 case KFShostname: 678 case KFSavenrun: 679 case KFSmsgbuf: 680 vap->va_nlink = 1; 681 total = 0; 682 do { 683 bf = strbuf; 684 error = kernfs_xread(kfs, total, &bf, 685 sizeof(strbuf), &nread); 686 total += nread; 687 } while (error == 0 && nread != 0); 688 vap->va_bytes = vap->va_size = total; 689 break; 690 691 default: 692 error = kernfs_try_fileop(kfs->kfs_type, 693 KERNFS_FILEOP_GETATTR, v, EINVAL); 694 break; 695 } 696 697 return (error); 698 } 699 700 /*ARGSUSED*/ 701 int 702 kernfs_setattr(void *v) 703 { 704 705 /* 706 * Silently ignore attribute changes. 707 * This allows for open with truncate to have no 708 * effect until some data is written. I want to 709 * do it this way because all writes are atomic. 710 */ 711 return (0); 712 } 713 714 int 715 kernfs_default_xread(void *v) 716 { 717 struct vop_read_args /* { 718 struct vnode *a_vp; 719 struct uio *a_uio; 720 int a_ioflag; 721 kauth_cred_t a_cred; 722 } */ *ap = v; 723 struct uio *uio = ap->a_uio; 724 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 725 char strbuf[KSTRING], *bf; 726 int off; 727 size_t len; 728 int error; 729 730 if (ap->a_vp->v_type == VDIR) 731 return EISDIR; 732 733 off = (int)uio->uio_offset; 734 /* Don't allow negative offsets */ 735 if (off < 0) 736 return EINVAL; 737 738 bf = strbuf; 739 if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0) 740 error = uiomove(bf, len, uio); 741 return (error); 742 } 743 744 int 745 kernfs_read(void *v) 746 { 747 struct vop_read_args /* { 748 struct vnode *a_vp; 749 struct uio *a_uio; 750 int a_ioflag; 751 struct ucred *a_cred; 752 } */ *ap = v; 753 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 754 755 if (kfs->kfs_type < KFSlasttype) { 756 /* use default function */ 757 return kernfs_default_xread(v); 758 } 759 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v, 760 EOPNOTSUPP); 761 } 762 763 static int 764 kernfs_default_xwrite(void *v) 765 { 766 struct vop_write_args /* { 767 struct vnode *a_vp; 768 struct uio *a_uio; 769 int a_ioflag; 770 kauth_cred_t a_cred; 771 } */ *ap = v; 772 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 773 struct uio *uio = ap->a_uio; 774 int error; 775 size_t xlen; 776 char strbuf[KSTRING]; 777 778 if (uio->uio_offset != 0) 779 return (EINVAL); 780 781 xlen = min(uio->uio_resid, KSTRING-1); 782 if ((error = uiomove(strbuf, xlen, uio)) != 0) 783 return (error); 784 785 if (uio->uio_resid != 0) 786 return (EIO); 787 788 strbuf[xlen] = '\0'; 789 xlen = strlen(strbuf); 790 return (kernfs_xwrite(kfs, strbuf, xlen)); 791 } 792 793 int 794 kernfs_write(void *v) 795 { 796 struct vop_write_args /* { 797 struct vnode *a_vp; 798 struct uio *a_uio; 799 int a_ioflag; 800 kauth_cred_t a_cred; 801 } */ *ap = v; 802 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 803 804 if (kfs->kfs_type < KFSlasttype) { 805 /* use default function */ 806 return kernfs_default_xwrite(v); 807 } 808 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 809 EOPNOTSUPP); 810 } 811 812 int 813 kernfs_ioctl(void *v) 814 { 815 struct vop_ioctl_args /* { 816 const struct vnodeop_desc *a_desc; 817 struct vnode *a_vp; 818 u_long a_command; 819 void *a_data; 820 int a_fflag; 821 kauth_cred_t a_cred; 822 } */ *ap = v; 823 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 824 825 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v, 826 EPASSTHROUGH); 827 } 828 829 static int 830 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt, 831 u_int32_t value, struct vop_readdir_args *ap) 832 { 833 struct kernfs_node *kfs; 834 struct vnode *vp; 835 int error; 836 837 if ((error = kernfs_allocvp(ap->a_vp->v_mount, &vp, kt->kt_tag, kt, 838 value)) != 0) 839 return error; 840 kfs = VTOKERN(vp); 841 d->d_fileno = kfs->kfs_fileno; 842 vput(vp); 843 return 0; 844 } 845 846 static int 847 kernfs_setdirentfileno(struct dirent *d, off_t entry, 848 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt, 849 const struct kern_target *kt, struct vop_readdir_args *ap) 850 { 851 const struct kern_target *ikt; 852 int error; 853 854 switch (entry) { 855 case 0: 856 d->d_fileno = thisdir_kfs->kfs_fileno; 857 return 0; 858 case 1: 859 ikt = parent_kt; 860 break; 861 default: 862 ikt = kt; 863 break; 864 } 865 if (ikt != thisdir_kfs->kfs_kt) { 866 if ((error = kernfs_setdirentfileno_kt(d, ikt, 0, ap)) != 0) 867 return error; 868 } else 869 d->d_fileno = thisdir_kfs->kfs_fileno; 870 return 0; 871 } 872 873 int 874 kernfs_readdir(void *v) 875 { 876 struct vop_readdir_args /* { 877 struct vnode *a_vp; 878 struct uio *a_uio; 879 kauth_cred_t a_cred; 880 int *a_eofflag; 881 off_t **a_cookies; 882 int a_*ncookies; 883 } */ *ap = v; 884 struct uio *uio = ap->a_uio; 885 struct dirent d; 886 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 887 const struct kern_target *kt; 888 const struct dyn_kern_target *dkt = NULL; 889 const struct kernfs_subdir *ks; 890 off_t i, j; 891 int error; 892 off_t *cookies = NULL; 893 int ncookies = 0, n; 894 895 if (uio->uio_resid < UIO_MX) 896 return (EINVAL); 897 if (uio->uio_offset < 0) 898 return (EINVAL); 899 900 error = 0; 901 i = uio->uio_offset; 902 memset(&d, 0, sizeof(d)); 903 d.d_reclen = UIO_MX; 904 ncookies = uio->uio_resid / UIO_MX; 905 906 switch (kfs->kfs_type) { 907 case KFSkern: 908 if (i >= nkern_targets) 909 return (0); 910 911 if (ap->a_ncookies) { 912 ncookies = min(ncookies, (nkern_targets - i)); 913 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 914 M_WAITOK); 915 *ap->a_cookies = cookies; 916 } 917 918 n = 0; 919 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) { 920 if (i < static_nkern_targets) 921 kt = &kern_targets[i]; 922 else { 923 if (dkt == NULL) { 924 dkt = SIMPLEQ_FIRST(&dyn_kern_targets); 925 for (j = static_nkern_targets; j < i && 926 dkt != NULL; j++) 927 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 928 if (j != i) 929 break; 930 } else { 931 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 932 } 933 if (dkt == NULL) 934 break; 935 kt = &dkt->dkt_kt; 936 } 937 if (kt->kt_tag == KFSdevice) { 938 dev_t *dp = kt->kt_data; 939 struct vnode *fvp; 940 941 if (*dp == NODEV || 942 !vfinddev(*dp, kt->kt_vtype, &fvp)) 943 continue; 944 vrele(fvp); 945 } 946 if (kt->kt_tag == KFSmsgbuf) { 947 if (!msgbufenabled 948 || msgbufp->msg_magic != MSG_MAGIC) { 949 continue; 950 } 951 } 952 d.d_namlen = kt->kt_namlen; 953 if ((error = kernfs_setdirentfileno(&d, i, kfs, 954 &kern_targets[0], kt, ap)) != 0) 955 break; 956 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 957 d.d_type = kt->kt_type; 958 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 959 break; 960 if (cookies) 961 *cookies++ = i + 1; 962 n++; 963 } 964 ncookies = n; 965 break; 966 967 case KFSroot: 968 if (i >= 2) 969 return 0; 970 971 if (ap->a_ncookies) { 972 ncookies = min(ncookies, (2 - i)); 973 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 974 M_WAITOK); 975 *ap->a_cookies = cookies; 976 } 977 978 n = 0; 979 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { 980 kt = &kern_targets[i]; 981 d.d_namlen = kt->kt_namlen; 982 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0); 983 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 984 d.d_type = kt->kt_type; 985 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 986 break; 987 if (cookies) 988 *cookies++ = i + 1; 989 n++; 990 } 991 ncookies = n; 992 break; 993 994 case KFSsubdir: 995 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 996 if (i >= ks->ks_nentries) 997 return (0); 998 999 if (ap->a_ncookies) { 1000 ncookies = min(ncookies, (ks->ks_nentries - i)); 1001 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1002 M_WAITOK); 1003 *ap->a_cookies = cookies; 1004 } 1005 1006 dkt = SIMPLEQ_FIRST(&ks->ks_entries); 1007 for (j = 0; j < i && dkt != NULL; j++) 1008 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1009 n = 0; 1010 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) { 1011 if (i < 2) 1012 kt = &subdir_targets[i]; 1013 else { 1014 /* check if ks_nentries lied to us */ 1015 if (dkt == NULL) 1016 break; 1017 kt = &dkt->dkt_kt; 1018 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1019 } 1020 if (kt->kt_tag == KFSdevice) { 1021 dev_t *dp = kt->kt_data; 1022 struct vnode *fvp; 1023 1024 if (*dp == NODEV || 1025 !vfinddev(*dp, kt->kt_vtype, &fvp)) 1026 continue; 1027 vrele(fvp); 1028 } 1029 d.d_namlen = kt->kt_namlen; 1030 if ((error = kernfs_setdirentfileno(&d, i, kfs, 1031 ks->ks_parent, kt, ap)) != 0) 1032 break; 1033 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1034 d.d_type = kt->kt_type; 1035 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1036 break; 1037 if (cookies) 1038 *cookies++ = i + 1; 1039 n++; 1040 } 1041 ncookies = n; 1042 break; 1043 1044 default: 1045 error = ENOTDIR; 1046 break; 1047 } 1048 1049 if (ap->a_ncookies) { 1050 if (error) { 1051 if (cookies) 1052 free(*ap->a_cookies, M_TEMP); 1053 *ap->a_ncookies = 0; 1054 *ap->a_cookies = NULL; 1055 } else 1056 *ap->a_ncookies = ncookies; 1057 } 1058 1059 uio->uio_offset = i; 1060 return (error); 1061 } 1062 1063 int 1064 kernfs_inactive(void *v) 1065 { 1066 struct vop_inactive_args /* { 1067 struct vnode *a_vp; 1068 bool *a_recycle; 1069 } */ *ap = v; 1070 struct vnode *vp = ap->a_vp; 1071 1072 *ap->a_recycle = false; 1073 VOP_UNLOCK(vp); 1074 return (0); 1075 } 1076 1077 int 1078 kernfs_reclaim(void *v) 1079 { 1080 struct vop_reclaim_args /* { 1081 struct vnode *a_vp; 1082 } */ *ap = v; 1083 1084 return (kernfs_freevp(ap->a_vp)); 1085 } 1086 1087 /* 1088 * Return POSIX pathconf information applicable to special devices. 1089 */ 1090 int 1091 kernfs_pathconf(void *v) 1092 { 1093 struct vop_pathconf_args /* { 1094 struct vnode *a_vp; 1095 int a_name; 1096 register_t *a_retval; 1097 } */ *ap = v; 1098 1099 switch (ap->a_name) { 1100 case _PC_LINK_MAX: 1101 *ap->a_retval = LINK_MAX; 1102 return (0); 1103 case _PC_MAX_CANON: 1104 *ap->a_retval = MAX_CANON; 1105 return (0); 1106 case _PC_MAX_INPUT: 1107 *ap->a_retval = MAX_INPUT; 1108 return (0); 1109 case _PC_PIPE_BUF: 1110 *ap->a_retval = PIPE_BUF; 1111 return (0); 1112 case _PC_CHOWN_RESTRICTED: 1113 *ap->a_retval = 1; 1114 return (0); 1115 case _PC_VDISABLE: 1116 *ap->a_retval = _POSIX_VDISABLE; 1117 return (0); 1118 case _PC_SYNC_IO: 1119 *ap->a_retval = 1; 1120 return (0); 1121 default: 1122 return (EINVAL); 1123 } 1124 /* NOTREACHED */ 1125 } 1126 1127 /* 1128 * Print out the contents of a /dev/fd vnode. 1129 */ 1130 /* ARGSUSED */ 1131 int 1132 kernfs_print(void *v) 1133 { 1134 1135 printf("tag VT_KERNFS, kernfs vnode\n"); 1136 return (0); 1137 } 1138 1139 int 1140 kernfs_link(void *v) 1141 { 1142 struct vop_link_args /* { 1143 struct vnode *a_dvp; 1144 struct vnode *a_vp; 1145 struct componentname *a_cnp; 1146 } */ *ap = v; 1147 1148 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1149 vput(ap->a_dvp); 1150 return (EROFS); 1151 } 1152 1153 int 1154 kernfs_symlink(void *v) 1155 { 1156 struct vop_symlink_v3_args /* { 1157 struct vnode *a_dvp; 1158 struct vnode **a_vpp; 1159 struct componentname *a_cnp; 1160 struct vattr *a_vap; 1161 char *a_target; 1162 } */ *ap = v; 1163 1164 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1165 return (EROFS); 1166 } 1167