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