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