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