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