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