1 /* $NetBSD: kernfs_vnops.c,v 1.162 2020/01/02 15:42:27 thorpej 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.162 2020/01/02 15:42:27 thorpej 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"), 0, KFSboottime, 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 int kernfs_getpages(void *); 176 #define kernfs_putpages genfs_putpages 177 178 static int kernfs_xread(struct kernfs_node *, int, char **, 179 size_t, size_t *); 180 static int kernfs_xwrite(const struct kernfs_node *, char *, size_t); 181 182 int (**kernfs_vnodeop_p)(void *); 183 const struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { 184 { &vop_default_desc, vn_default_error }, 185 { &vop_lookup_desc, kernfs_lookup }, /* lookup */ 186 { &vop_create_desc, kernfs_create }, /* create */ 187 { &vop_mknod_desc, kernfs_mknod }, /* mknod */ 188 { &vop_open_desc, kernfs_open }, /* open */ 189 { &vop_close_desc, kernfs_close }, /* close */ 190 { &vop_access_desc, kernfs_access }, /* access */ 191 { &vop_getattr_desc, kernfs_getattr }, /* getattr */ 192 { &vop_setattr_desc, kernfs_setattr }, /* setattr */ 193 { &vop_read_desc, kernfs_read }, /* read */ 194 { &vop_write_desc, kernfs_write }, /* write */ 195 { &vop_fallocate_desc, genfs_eopnotsupp }, /* fallocate */ 196 { &vop_fdiscard_desc, genfs_eopnotsupp }, /* fdiscard */ 197 { &vop_fcntl_desc, kernfs_fcntl }, /* fcntl */ 198 { &vop_ioctl_desc, kernfs_ioctl }, /* ioctl */ 199 { &vop_poll_desc, kernfs_poll }, /* poll */ 200 { &vop_revoke_desc, kernfs_revoke }, /* revoke */ 201 { &vop_fsync_desc, kernfs_fsync }, /* fsync */ 202 { &vop_seek_desc, kernfs_seek }, /* seek */ 203 { &vop_remove_desc, kernfs_remove }, /* remove */ 204 { &vop_link_desc, kernfs_link }, /* link */ 205 { &vop_rename_desc, kernfs_rename }, /* rename */ 206 { &vop_mkdir_desc, kernfs_mkdir }, /* mkdir */ 207 { &vop_rmdir_desc, kernfs_rmdir }, /* rmdir */ 208 { &vop_symlink_desc, kernfs_symlink }, /* symlink */ 209 { &vop_readdir_desc, kernfs_readdir }, /* readdir */ 210 { &vop_readlink_desc, kernfs_readlink }, /* readlink */ 211 { &vop_abortop_desc, kernfs_abortop }, /* abortop */ 212 { &vop_inactive_desc, kernfs_inactive }, /* inactive */ 213 { &vop_reclaim_desc, kernfs_reclaim }, /* reclaim */ 214 { &vop_lock_desc, kernfs_lock }, /* lock */ 215 { &vop_unlock_desc, kernfs_unlock }, /* unlock */ 216 { &vop_bmap_desc, kernfs_bmap }, /* bmap */ 217 { &vop_strategy_desc, kernfs_strategy }, /* strategy */ 218 { &vop_print_desc, kernfs_print }, /* print */ 219 { &vop_islocked_desc, kernfs_islocked }, /* islocked */ 220 { &vop_pathconf_desc, kernfs_pathconf }, /* pathconf */ 221 { &vop_advlock_desc, kernfs_advlock }, /* advlock */ 222 { &vop_bwrite_desc, kernfs_bwrite }, /* bwrite */ 223 { &vop_getpages_desc, kernfs_getpages }, /* getpages */ 224 { &vop_putpages_desc, kernfs_putpages }, /* putpages */ 225 { NULL, NULL } 226 }; 227 const struct vnodeopv_desc kernfs_vnodeop_opv_desc = 228 { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; 229 230 static inline int 231 kernfs_fileop_compare(struct kernfs_fileop *a, struct kernfs_fileop *b) 232 { 233 if (a->kf_type < b->kf_type) 234 return -1; 235 if (a->kf_type > b->kf_type) 236 return 1; 237 if (a->kf_fileop < b->kf_fileop) 238 return -1; 239 if (a->kf_fileop > b->kf_fileop) 240 return 1; 241 return (0); 242 } 243 244 SPLAY_HEAD(kfsfileoptree, kernfs_fileop) kfsfileoptree = 245 SPLAY_INITIALIZER(kfsfileoptree); 246 SPLAY_PROTOTYPE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare); 247 SPLAY_GENERATE(kfsfileoptree, kernfs_fileop, kf_node, kernfs_fileop_compare); 248 249 kfstype 250 kernfs_alloctype(int nkf, const struct kernfs_fileop *kf) 251 { 252 static u_char nextfreetype = KFSlasttype; 253 struct kernfs_fileop *dkf, *fkf, skf; 254 int i; 255 256 /* XXX need to keep track of dkf's memory if we support 257 deallocating types */ 258 dkf = malloc(sizeof(kernfs_default_fileops), M_TEMP, M_WAITOK); 259 memcpy(dkf, kernfs_default_fileops, sizeof(kernfs_default_fileops)); 260 261 for (i = 0; i < sizeof(kernfs_default_fileops) / 262 sizeof(kernfs_default_fileops[0]); i++) { 263 dkf[i].kf_type = nextfreetype; 264 SPLAY_INSERT(kfsfileoptree, &kfsfileoptree, &dkf[i]); 265 } 266 267 for (i = 0; i < nkf; i++) { 268 skf.kf_type = nextfreetype; 269 skf.kf_fileop = kf[i].kf_fileop; 270 if ((fkf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 271 fkf->kf_vop = kf[i].kf_vop; 272 } 273 274 return nextfreetype++; 275 } 276 277 int 278 kernfs_try_fileop(kfstype type, kfsfileop fileop, void *v, int error) 279 { 280 struct kernfs_fileop *kf, skf; 281 282 skf.kf_type = type; 283 skf.kf_fileop = fileop; 284 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 285 if (kf->kf_vop) 286 return kf->kf_vop(v); 287 return error; 288 } 289 290 int 291 kernfs_try_xread(kfstype type, const struct kernfs_node *kfs, char **bfp, 292 size_t len, int error) 293 { 294 struct kernfs_fileop *kf, skf; 295 296 skf.kf_type = type; 297 skf.kf_fileop = KERNFS_XREAD; 298 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 299 if (kf->kf_xread) 300 return kf->kf_xread(kfs, bfp, len); 301 return error; 302 } 303 304 int 305 kernfs_try_xwrite(kfstype type, const struct kernfs_node *kfs, char *bf, 306 size_t len, int error) 307 { 308 struct kernfs_fileop *kf, skf; 309 310 skf.kf_type = type; 311 skf.kf_fileop = KERNFS_XWRITE; 312 if ((kf = SPLAY_FIND(kfsfileoptree, &kfsfileoptree, &skf))) 313 if (kf->kf_xwrite) 314 return kf->kf_xwrite(kfs, bf, len); 315 return error; 316 } 317 318 int 319 kernfs_addentry(kernfs_parentdir_t *pkt, kernfs_entry_t *dkt) 320 { 321 struct kernfs_subdir *ks, *parent; 322 323 if (pkt == NULL) { 324 SIMPLEQ_INSERT_TAIL(&dyn_kern_targets, dkt, dkt_queue); 325 nkern_targets++; 326 if (dkt->dkt_kt.kt_vtype == VDIR) 327 nkern_dirs++; 328 } else { 329 parent = (struct kernfs_subdir *)pkt->kt_data; 330 SIMPLEQ_INSERT_TAIL(&parent->ks_entries, dkt, dkt_queue); 331 parent->ks_nentries++; 332 if (dkt->dkt_kt.kt_vtype == VDIR) 333 parent->ks_dirs++; 334 } 335 if (dkt->dkt_kt.kt_vtype == VDIR && dkt->dkt_kt.kt_data == NULL) { 336 ks = malloc(sizeof(struct kernfs_subdir), 337 M_TEMP, M_WAITOK); 338 SIMPLEQ_INIT(&ks->ks_entries); 339 ks->ks_nentries = 2; /* . and .. */ 340 ks->ks_dirs = 2; 341 ks->ks_parent = pkt ? pkt : &kern_targets[0]; 342 dkt->dkt_kt.kt_data = ks; 343 } 344 return 0; 345 } 346 347 static int 348 kernfs_xread(struct kernfs_node *kfs, int off, char **bufp, size_t len, size_t *wrlen) 349 { 350 const struct kern_target *kt; 351 int err; 352 353 kt = kfs->kfs_kt; 354 355 switch (kfs->kfs_type) { 356 case KFStime: { 357 struct timeval tv; 358 359 microtime(&tv); 360 snprintf(*bufp, len, "%lld %ld\n", (long long)tv.tv_sec, 361 (long)tv.tv_usec); 362 break; 363 } 364 365 case KFSboottime: { 366 struct timeval tv; 367 368 /* 369 * Historically, /kern/boottime only contained seconds. 370 */ 371 getmicroboottime(&tv); 372 snprintf(*bufp, len, "%lld\n", (long long)tv.tv_sec); 373 break; 374 } 375 376 case KFSint: { 377 int *ip = kt->kt_data; 378 379 snprintf(*bufp, len, "%d\n", *ip); 380 break; 381 } 382 383 case KFSstring: { 384 char *cp = kt->kt_data; 385 386 *bufp = cp; 387 break; 388 } 389 390 case KFSmsgbuf: { 391 long n; 392 393 /* 394 * deal with cases where the message buffer has 395 * become corrupted. 396 */ 397 if (!logenabled(msgbufp)) { 398 msgbufenabled = 0; 399 return (ENXIO); 400 } 401 402 /* 403 * Note that reads of /kern/msgbuf won't necessarily yield 404 * consistent results, if the message buffer is modified 405 * while the read is in progress. The worst that can happen 406 * is that incorrect data will be read. There's no way 407 * that this can crash the system unless the values in the 408 * message buffer header are corrupted, but that'll cause 409 * the system to die anyway. 410 */ 411 if (off >= msgbufp->msg_bufs) { 412 *wrlen = 0; 413 return (0); 414 } 415 n = msgbufp->msg_bufx + off; 416 if (n >= msgbufp->msg_bufs) 417 n -= msgbufp->msg_bufs; 418 len = uimin(msgbufp->msg_bufs - n, msgbufp->msg_bufs - off); 419 *bufp = msgbufp->msg_bufc + n; 420 *wrlen = len; 421 return (0); 422 } 423 424 case KFShostname: { 425 char *cp = hostname; 426 size_t xlen = hostnamelen; 427 428 if (xlen >= (len - 2)) 429 return (EINVAL); 430 431 memcpy(*bufp, cp, xlen); 432 (*bufp)[xlen] = '\n'; 433 (*bufp)[xlen+1] = '\0'; 434 break; 435 } 436 437 case KFSavenrun: 438 averunnable.fscale = FSCALE; 439 snprintf(*bufp, len, "%d %d %d %ld\n", 440 averunnable.ldavg[0], averunnable.ldavg[1], 441 averunnable.ldavg[2], averunnable.fscale); 442 break; 443 444 default: 445 err = kernfs_try_xread(kfs->kfs_type, kfs, bufp, len, 446 EOPNOTSUPP); 447 if (err) 448 return err; 449 } 450 451 len = strlen(*bufp); 452 if (len <= off) 453 *wrlen = 0; 454 else { 455 *bufp += off; 456 *wrlen = len - off; 457 } 458 return (0); 459 } 460 461 static int 462 kernfs_xwrite(const struct kernfs_node *kfs, char *bf, size_t len) 463 { 464 465 switch (kfs->kfs_type) { 466 case KFShostname: 467 if (bf[len-1] == '\n') 468 --len; 469 memcpy(hostname, bf, len); 470 hostname[len] = '\0'; 471 hostnamelen = (size_t) len; 472 return (0); 473 474 default: 475 return kernfs_try_xwrite(kfs->kfs_type, kfs, bf, len, EIO); 476 } 477 } 478 479 480 /* 481 * vp is the current namei directory 482 * ndp is the name to locate in that directory... 483 */ 484 int 485 kernfs_lookup(void *v) 486 { 487 struct vop_lookup_v2_args /* { 488 struct vnode * a_dvp; 489 struct vnode ** a_vpp; 490 struct componentname * a_cnp; 491 } */ *ap = v; 492 struct componentname *cnp = ap->a_cnp; 493 struct vnode **vpp = ap->a_vpp; 494 struct vnode *dvp = ap->a_dvp; 495 const char *pname = cnp->cn_nameptr; 496 const struct kernfs_node *kfs; 497 const struct kern_target *kt; 498 const struct dyn_kern_target *dkt; 499 const struct kernfs_subdir *ks; 500 int error, i; 501 502 *vpp = NULLVP; 503 504 if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) 505 return (EROFS); 506 507 if (cnp->cn_namelen == 1 && *pname == '.') { 508 *vpp = dvp; 509 vref(dvp); 510 return (0); 511 } 512 513 kfs = VTOKERN(dvp); 514 switch (kfs->kfs_type) { 515 case KFSkern: 516 /* 517 * Shouldn't get here with .. in the root node. 518 */ 519 if (cnp->cn_flags & ISDOTDOT) 520 return (EIO); 521 522 for (i = 0; i < static_nkern_targets; i++) { 523 kt = &kern_targets[i]; 524 if (cnp->cn_namelen == kt->kt_namlen && 525 memcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) 526 goto found; 527 } 528 SIMPLEQ_FOREACH(dkt, &dyn_kern_targets, dkt_queue) { 529 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && 530 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { 531 kt = &dkt->dkt_kt; 532 goto found; 533 } 534 } 535 break; 536 537 found: 538 error = vcache_get(dvp->v_mount, &kt, sizeof(kt), vpp); 539 return error; 540 541 case KFSsubdir: 542 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 543 if (cnp->cn_flags & ISDOTDOT) { 544 kt = ks->ks_parent; 545 goto found; 546 } 547 548 SIMPLEQ_FOREACH(dkt, &ks->ks_entries, dkt_queue) { 549 if (cnp->cn_namelen == dkt->dkt_kt.kt_namlen && 550 memcmp(dkt->dkt_kt.kt_name, pname, cnp->cn_namelen) == 0) { 551 kt = &dkt->dkt_kt; 552 goto found; 553 } 554 } 555 break; 556 557 default: 558 return (ENOTDIR); 559 } 560 561 return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); 562 } 563 564 int 565 kernfs_open(void *v) 566 { 567 struct vop_open_args /* { 568 struct vnode *a_vp; 569 int a_mode; 570 kauth_cred_t a_cred; 571 } */ *ap = v; 572 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 573 574 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_OPEN, v, 0); 575 } 576 577 int 578 kernfs_close(void *v) 579 { 580 struct vop_close_args /* { 581 struct vnode *a_vp; 582 int a_fflag; 583 kauth_cred_t a_cred; 584 } */ *ap = v; 585 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 586 587 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_CLOSE, v, 0); 588 } 589 590 int 591 kernfs_access(void *v) 592 { 593 struct vop_access_args /* { 594 struct vnode *a_vp; 595 int a_mode; 596 kauth_cred_t a_cred; 597 } */ *ap = v; 598 struct vattr va; 599 int error; 600 601 if ((error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred)) != 0) 602 return (error); 603 604 return kauth_authorize_vnode(ap->a_cred, 605 KAUTH_ACCESS_ACTION(ap->a_mode, ap->a_vp->v_type, va.va_mode), 606 ap->a_vp, NULL, genfs_can_access(va.va_type, va.va_mode, 607 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 608 } 609 610 static int 611 kernfs_default_fileop_getattr(void *v) 612 { 613 struct vop_getattr_args /* { 614 struct vnode *a_vp; 615 struct vattr *a_vap; 616 kauth_cred_t a_cred; 617 } */ *ap = v; 618 struct vattr *vap = ap->a_vap; 619 620 vap->va_nlink = 1; 621 vap->va_bytes = vap->va_size = 0; 622 623 return 0; 624 } 625 626 int 627 kernfs_getattr(void *v) 628 { 629 struct vop_getattr_args /* { 630 struct vnode *a_vp; 631 struct vattr *a_vap; 632 kauth_cred_t a_cred; 633 } */ *ap = v; 634 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 635 struct kernfs_subdir *ks; 636 struct vattr *vap = ap->a_vap; 637 int error = 0; 638 char strbuf[KSTRING], *bf; 639 size_t nread, total; 640 641 vattr_null(vap); 642 vap->va_type = ap->a_vp->v_type; 643 vap->va_uid = 0; 644 vap->va_gid = 0; 645 vap->va_mode = kfs->kfs_mode; 646 vap->va_fileid = kfs->kfs_fileno; 647 vap->va_flags = 0; 648 vap->va_size = 0; 649 vap->va_blocksize = DEV_BSIZE; 650 /* Make all times be current TOD, except for the "boottime" node. */ 651 if (kfs->kfs_kt->kt_namlen == 8 && 652 !memcmp(kfs->kfs_kt->kt_name, "boottime", 8)) { 653 getnanoboottime(&vap->va_ctime); 654 } else { 655 getnanotime(&vap->va_ctime); 656 } 657 vap->va_atime = vap->va_mtime = vap->va_ctime; 658 vap->va_gen = 0; 659 vap->va_flags = 0; 660 vap->va_rdev = 0; 661 vap->va_bytes = 0; 662 663 switch (kfs->kfs_type) { 664 case KFSkern: 665 vap->va_nlink = nkern_dirs; 666 vap->va_bytes = vap->va_size = DEV_BSIZE; 667 break; 668 669 case KFSdevice: 670 vap->va_nlink = 1; 671 vap->va_rdev = ap->a_vp->v_rdev; 672 break; 673 674 case KFSroot: 675 vap->va_nlink = 1; 676 vap->va_bytes = vap->va_size = DEV_BSIZE; 677 break; 678 679 case KFSsubdir: 680 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 681 vap->va_nlink = ks->ks_dirs; 682 vap->va_bytes = vap->va_size = DEV_BSIZE; 683 break; 684 685 case KFSnull: 686 case KFStime: 687 case KFSboottime: 688 case KFSint: 689 case KFSstring: 690 case KFShostname: 691 case KFSavenrun: 692 case KFSmsgbuf: 693 vap->va_nlink = 1; 694 total = 0; 695 do { 696 bf = strbuf; 697 error = kernfs_xread(kfs, total, &bf, 698 sizeof(strbuf), &nread); 699 total += nread; 700 } while (error == 0 && nread != 0); 701 vap->va_bytes = vap->va_size = total; 702 break; 703 704 default: 705 error = kernfs_try_fileop(kfs->kfs_type, 706 KERNFS_FILEOP_GETATTR, v, EINVAL); 707 break; 708 } 709 710 return (error); 711 } 712 713 /*ARGSUSED*/ 714 int 715 kernfs_setattr(void *v) 716 { 717 718 /* 719 * Silently ignore attribute changes. 720 * This allows for open with truncate to have no 721 * effect until some data is written. I want to 722 * do it this way because all writes are atomic. 723 */ 724 return (0); 725 } 726 727 int 728 kernfs_default_xread(void *v) 729 { 730 struct vop_read_args /* { 731 struct vnode *a_vp; 732 struct uio *a_uio; 733 int a_ioflag; 734 kauth_cred_t a_cred; 735 } */ *ap = v; 736 struct uio *uio = ap->a_uio; 737 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 738 char strbuf[KSTRING], *bf; 739 int off; 740 size_t len; 741 int error; 742 743 if (ap->a_vp->v_type == VDIR) 744 return EISDIR; 745 746 off = (int)uio->uio_offset; 747 /* Don't allow negative offsets */ 748 if (off < 0) 749 return EINVAL; 750 751 bf = strbuf; 752 if ((error = kernfs_xread(kfs, off, &bf, sizeof(strbuf), &len)) == 0) 753 error = uiomove(bf, len, uio); 754 return (error); 755 } 756 757 int 758 kernfs_read(void *v) 759 { 760 struct vop_read_args /* { 761 struct vnode *a_vp; 762 struct uio *a_uio; 763 int a_ioflag; 764 struct ucred *a_cred; 765 } */ *ap = v; 766 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 767 768 if (kfs->kfs_type < KFSlasttype) { 769 /* use default function */ 770 return kernfs_default_xread(v); 771 } 772 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_READ, v, 773 EOPNOTSUPP); 774 } 775 776 static int 777 kernfs_default_xwrite(void *v) 778 { 779 struct vop_write_args /* { 780 struct vnode *a_vp; 781 struct uio *a_uio; 782 int a_ioflag; 783 kauth_cred_t a_cred; 784 } */ *ap = v; 785 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 786 struct uio *uio = ap->a_uio; 787 int error; 788 size_t xlen; 789 char strbuf[KSTRING]; 790 791 if (uio->uio_offset != 0) 792 return (EINVAL); 793 794 xlen = uimin(uio->uio_resid, KSTRING-1); 795 if ((error = uiomove(strbuf, xlen, uio)) != 0) 796 return (error); 797 798 if (uio->uio_resid != 0) 799 return (EIO); 800 801 strbuf[xlen] = '\0'; 802 xlen = strlen(strbuf); 803 return (kernfs_xwrite(kfs, strbuf, xlen)); 804 } 805 806 int 807 kernfs_write(void *v) 808 { 809 struct vop_write_args /* { 810 struct vnode *a_vp; 811 struct uio *a_uio; 812 int a_ioflag; 813 kauth_cred_t a_cred; 814 } */ *ap = v; 815 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 816 817 if (kfs->kfs_type < KFSlasttype) { 818 /* use default function */ 819 return kernfs_default_xwrite(v); 820 } 821 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_WRITE, v, 822 EOPNOTSUPP); 823 } 824 825 int 826 kernfs_ioctl(void *v) 827 { 828 struct vop_ioctl_args /* { 829 const struct vnodeop_desc *a_desc; 830 struct vnode *a_vp; 831 u_long a_command; 832 void *a_data; 833 int a_fflag; 834 kauth_cred_t a_cred; 835 } */ *ap = v; 836 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 837 838 return kernfs_try_fileop(kfs->kfs_type, KERNFS_FILEOP_IOCTL, v, 839 EPASSTHROUGH); 840 } 841 842 static int 843 kernfs_setdirentfileno_kt(struct dirent *d, const struct kern_target *kt, 844 struct vop_readdir_args *ap) 845 { 846 struct kernfs_node *kfs; 847 struct vnode *vp; 848 int error; 849 850 if ((error = vcache_get(ap->a_vp->v_mount, &kt, sizeof(kt), &vp)) != 0) 851 return error; 852 kfs = VTOKERN(vp); 853 d->d_fileno = kfs->kfs_fileno; 854 vrele(vp); 855 return 0; 856 } 857 858 static int 859 kernfs_setdirentfileno(struct dirent *d, off_t entry, 860 struct kernfs_node *thisdir_kfs, const struct kern_target *parent_kt, 861 const struct kern_target *kt, struct vop_readdir_args *ap) 862 { 863 const struct kern_target *ikt; 864 int error; 865 866 switch (entry) { 867 case 0: 868 d->d_fileno = thisdir_kfs->kfs_fileno; 869 return 0; 870 case 1: 871 ikt = parent_kt; 872 break; 873 default: 874 ikt = kt; 875 break; 876 } 877 if (ikt != thisdir_kfs->kfs_kt) { 878 if ((error = kernfs_setdirentfileno_kt(d, ikt, ap)) != 0) 879 return error; 880 } else 881 d->d_fileno = thisdir_kfs->kfs_fileno; 882 return 0; 883 } 884 885 int 886 kernfs_readdir(void *v) 887 { 888 struct vop_readdir_args /* { 889 struct vnode *a_vp; 890 struct uio *a_uio; 891 kauth_cred_t a_cred; 892 int *a_eofflag; 893 off_t **a_cookies; 894 int a_*ncookies; 895 } */ *ap = v; 896 struct uio *uio = ap->a_uio; 897 struct dirent d; 898 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 899 const struct kern_target *kt; 900 const struct dyn_kern_target *dkt = NULL; 901 const struct kernfs_subdir *ks; 902 off_t i, j; 903 int error; 904 off_t *cookies = NULL; 905 int ncookies = 0, n; 906 907 if (uio->uio_resid < UIO_MX) 908 return (EINVAL); 909 if (uio->uio_offset < 0) 910 return (EINVAL); 911 912 error = 0; 913 i = uio->uio_offset; 914 memset(&d, 0, sizeof(d)); 915 d.d_reclen = UIO_MX; 916 ncookies = uio->uio_resid / UIO_MX; 917 918 switch (kfs->kfs_type) { 919 case KFSkern: 920 if (i >= nkern_targets) 921 return (0); 922 923 if (ap->a_ncookies) { 924 ncookies = uimin(ncookies, (nkern_targets - i)); 925 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 926 M_WAITOK); 927 *ap->a_cookies = cookies; 928 } 929 930 n = 0; 931 for (; i < nkern_targets && uio->uio_resid >= UIO_MX; i++) { 932 if (i < static_nkern_targets) 933 kt = &kern_targets[i]; 934 else { 935 if (dkt == NULL) { 936 dkt = SIMPLEQ_FIRST(&dyn_kern_targets); 937 for (j = static_nkern_targets; j < i && 938 dkt != NULL; j++) 939 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 940 if (j != i) 941 break; 942 } else { 943 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 944 } 945 if (dkt == NULL) 946 break; 947 kt = &dkt->dkt_kt; 948 } 949 if (kt->kt_tag == KFSdevice) { 950 dev_t *dp = kt->kt_data; 951 struct vnode *fvp; 952 953 if (*dp == NODEV || 954 !vfinddev(*dp, kt->kt_vtype, &fvp)) 955 continue; 956 vrele(fvp); 957 } 958 if (kt->kt_tag == KFSmsgbuf) { 959 if (!logenabled(msgbufp)) { 960 continue; 961 } 962 } 963 d.d_namlen = kt->kt_namlen; 964 if ((error = kernfs_setdirentfileno(&d, i, kfs, 965 &kern_targets[0], kt, ap)) != 0) 966 break; 967 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 968 d.d_type = kt->kt_type; 969 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 970 break; 971 if (cookies) 972 *cookies++ = i + 1; 973 n++; 974 } 975 ncookies = n; 976 break; 977 978 case KFSroot: 979 if (i >= 2) 980 return 0; 981 982 if (ap->a_ncookies) { 983 ncookies = uimin(ncookies, (2 - i)); 984 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 985 M_WAITOK); 986 *ap->a_cookies = cookies; 987 } 988 989 n = 0; 990 for (; i < 2 && uio->uio_resid >= UIO_MX; i++) { 991 kt = &kern_targets[i]; 992 d.d_namlen = kt->kt_namlen; 993 d.d_fileno = KERNFS_FILENO(kt, kt->kt_tag, 0); 994 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 995 d.d_type = kt->kt_type; 996 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 997 break; 998 if (cookies) 999 *cookies++ = i + 1; 1000 n++; 1001 } 1002 ncookies = n; 1003 break; 1004 1005 case KFSsubdir: 1006 ks = (struct kernfs_subdir *)kfs->kfs_kt->kt_data; 1007 if (i >= ks->ks_nentries) 1008 return (0); 1009 1010 if (ap->a_ncookies) { 1011 ncookies = uimin(ncookies, (ks->ks_nentries - i)); 1012 cookies = malloc(ncookies * sizeof(off_t), M_TEMP, 1013 M_WAITOK); 1014 *ap->a_cookies = cookies; 1015 } 1016 1017 dkt = SIMPLEQ_FIRST(&ks->ks_entries); 1018 for (j = 0; j < i && dkt != NULL; j++) 1019 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1020 n = 0; 1021 for (; i < ks->ks_nentries && uio->uio_resid >= UIO_MX; i++) { 1022 if (i < 2) 1023 kt = &subdir_targets[i]; 1024 else { 1025 /* check if ks_nentries lied to us */ 1026 if (dkt == NULL) 1027 break; 1028 kt = &dkt->dkt_kt; 1029 dkt = SIMPLEQ_NEXT(dkt, dkt_queue); 1030 } 1031 if (kt->kt_tag == KFSdevice) { 1032 dev_t *dp = kt->kt_data; 1033 struct vnode *fvp; 1034 1035 if (*dp == NODEV || 1036 !vfinddev(*dp, kt->kt_vtype, &fvp)) 1037 continue; 1038 vrele(fvp); 1039 } 1040 d.d_namlen = kt->kt_namlen; 1041 if ((error = kernfs_setdirentfileno(&d, i, kfs, 1042 ks->ks_parent, kt, ap)) != 0) 1043 break; 1044 memcpy(d.d_name, kt->kt_name, kt->kt_namlen + 1); 1045 d.d_type = kt->kt_type; 1046 if ((error = uiomove(&d, UIO_MX, uio)) != 0) 1047 break; 1048 if (cookies) 1049 *cookies++ = i + 1; 1050 n++; 1051 } 1052 ncookies = n; 1053 break; 1054 1055 default: 1056 error = ENOTDIR; 1057 break; 1058 } 1059 1060 if (ap->a_ncookies) { 1061 if (error) { 1062 if (cookies) 1063 free(*ap->a_cookies, M_TEMP); 1064 *ap->a_ncookies = 0; 1065 *ap->a_cookies = NULL; 1066 } else 1067 *ap->a_ncookies = ncookies; 1068 } 1069 1070 uio->uio_offset = i; 1071 return (error); 1072 } 1073 1074 int 1075 kernfs_inactive(void *v) 1076 { 1077 struct vop_inactive_v2_args /* { 1078 struct vnode *a_vp; 1079 bool *a_recycle; 1080 } */ *ap = v; 1081 1082 *ap->a_recycle = false; 1083 1084 return (0); 1085 } 1086 1087 int 1088 kernfs_reclaim(void *v) 1089 { 1090 struct vop_reclaim_v2_args /* { 1091 struct vnode *a_vp; 1092 } */ *ap = v; 1093 struct vnode *vp = ap->a_vp; 1094 struct kernfs_node *kfs = VTOKERN(vp); 1095 1096 VOP_UNLOCK(vp); 1097 1098 vp->v_data = NULL; 1099 mutex_enter(&kfs_lock); 1100 TAILQ_REMOVE(&VFSTOKERNFS(vp->v_mount)->nodelist, kfs, kfs_list); 1101 mutex_exit(&kfs_lock); 1102 kmem_free(kfs, sizeof(struct kernfs_node)); 1103 1104 return 0; 1105 } 1106 1107 /* 1108 * Return POSIX pathconf information applicable to special devices. 1109 */ 1110 int 1111 kernfs_pathconf(void *v) 1112 { 1113 struct vop_pathconf_args /* { 1114 struct vnode *a_vp; 1115 int a_name; 1116 register_t *a_retval; 1117 } */ *ap = v; 1118 1119 switch (ap->a_name) { 1120 case _PC_LINK_MAX: 1121 *ap->a_retval = LINK_MAX; 1122 return (0); 1123 case _PC_MAX_CANON: 1124 *ap->a_retval = MAX_CANON; 1125 return (0); 1126 case _PC_MAX_INPUT: 1127 *ap->a_retval = MAX_INPUT; 1128 return (0); 1129 case _PC_PIPE_BUF: 1130 *ap->a_retval = PIPE_BUF; 1131 return (0); 1132 case _PC_CHOWN_RESTRICTED: 1133 *ap->a_retval = 1; 1134 return (0); 1135 case _PC_VDISABLE: 1136 *ap->a_retval = _POSIX_VDISABLE; 1137 return (0); 1138 case _PC_SYNC_IO: 1139 *ap->a_retval = 1; 1140 return (0); 1141 default: 1142 return (EINVAL); 1143 } 1144 /* NOTREACHED */ 1145 } 1146 1147 /* 1148 * Print out the contents of a /dev/fd vnode. 1149 */ 1150 /* ARGSUSED */ 1151 int 1152 kernfs_print(void *v) 1153 { 1154 1155 printf("tag VT_KERNFS, kernfs vnode\n"); 1156 return (0); 1157 } 1158 1159 int 1160 kernfs_link(void *v) 1161 { 1162 struct vop_link_v2_args /* { 1163 struct vnode *a_dvp; 1164 struct vnode *a_vp; 1165 struct componentname *a_cnp; 1166 } */ *ap = v; 1167 1168 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1169 return (EROFS); 1170 } 1171 1172 int 1173 kernfs_symlink(void *v) 1174 { 1175 struct vop_symlink_v3_args /* { 1176 struct vnode *a_dvp; 1177 struct vnode **a_vpp; 1178 struct componentname *a_cnp; 1179 struct vattr *a_vap; 1180 char *a_target; 1181 } */ *ap = v; 1182 1183 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 1184 return (EROFS); 1185 } 1186 1187 int 1188 kernfs_getpages(void *v) 1189 { 1190 struct vop_getpages_args /* { 1191 struct vnode *a_vp; 1192 voff_t a_offset; 1193 struct vm_page **a_m; 1194 int *a_count; 1195 int a_centeridx; 1196 vm_prot_t a_access_type; 1197 int a_advice; 1198 int a_flags; 1199 } */ *ap = v; 1200 1201 if ((ap->a_flags & PGO_LOCKED) == 0) 1202 mutex_exit(ap->a_vp->v_interlock); 1203 1204 return (EFAULT); 1205 } 1206