1 1.97 ad /* $NetBSD: rump_vfs.c,v 1.97 2023/09/23 18:21:12 ad Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.1 pooka * Copyright (c) 2008 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.1 pooka * Development of this software was supported by the 7 1.1 pooka * Finnish Cultural Foundation. 8 1.1 pooka * 9 1.1 pooka * Redistribution and use in source and binary forms, with or without 10 1.1 pooka * modification, are permitted provided that the following conditions 11 1.1 pooka * are met: 12 1.1 pooka * 1. Redistributions of source code must retain the above copyright 13 1.1 pooka * notice, this list of conditions and the following disclaimer. 14 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 pooka * notice, this list of conditions and the following disclaimer in the 16 1.1 pooka * documentation and/or other materials provided with the distribution. 17 1.1 pooka * 18 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 1.1 pooka * SUCH DAMAGE. 29 1.1 pooka */ 30 1.1 pooka 31 1.5 pooka #include <sys/cdefs.h> 32 1.97 ad __KERNEL_RCSID(0, "$NetBSD: rump_vfs.c,v 1.97 2023/09/23 18:21:12 ad Exp $"); 33 1.5 pooka 34 1.1 pooka #include <sys/param.h> 35 1.1 pooka #include <sys/buf.h> 36 1.6 pooka #include <sys/conf.h> 37 1.16 pooka #include <sys/evcnt.h> 38 1.80 pooka #include <sys/fcntl.h> 39 1.1 pooka #include <sys/filedesc.h> 40 1.45 pooka #include <sys/fstrans.h> 41 1.11 pooka #include <sys/lockf.h> 42 1.15 pooka #include <sys/kthread.h> 43 1.1 pooka #include <sys/module.h> 44 1.1 pooka #include <sys/namei.h> 45 1.1 pooka #include <sys/queue.h> 46 1.48 pooka #include <sys/stat.h> 47 1.1 pooka #include <sys/vfs_syscalls.h> 48 1.1 pooka #include <sys/vnode.h> 49 1.1 pooka #include <sys/wapbl.h> 50 1.85 pgoyette #include <sys/bufq.h> 51 1.1 pooka 52 1.1 pooka #include <miscfs/specfs/specdev.h> 53 1.1 pooka 54 1.84 pooka #include <rump-sys/kern.h> 55 1.84 pooka #include <rump-sys/vfs.h> 56 1.84 pooka 57 1.1 pooka #include <rump/rump.h> 58 1.1 pooka #include <rump/rumpuser.h> 59 1.1 pooka 60 1.44 pooka const char *rootfstype = ROOT_FSTYPE_ANY; 61 1.1 pooka 62 1.1 pooka static void 63 1.1 pooka pvfs_init(struct proc *p) 64 1.1 pooka { 65 1.1 pooka 66 1.1 pooka p->p_cwdi = cwdinit(); 67 1.1 pooka } 68 1.1 pooka 69 1.1 pooka static void 70 1.1 pooka pvfs_rele(struct proc *p) 71 1.1 pooka { 72 1.1 pooka 73 1.1 pooka cwdfree(p->p_cwdi); 74 1.1 pooka } 75 1.1 pooka 76 1.71 pooka static void 77 1.71 pooka fini(void) 78 1.71 pooka { 79 1.71 pooka 80 1.71 pooka vfs_shutdown(); 81 1.81 pooka rumpblk_fini(); 82 1.71 pooka } 83 1.71 pooka 84 1.71 pooka static void 85 1.71 pooka drainbufs(int npages) 86 1.71 pooka { 87 1.71 pooka 88 1.71 pooka mutex_enter(&bufcache_lock); 89 1.71 pooka buf_drain(npages); 90 1.71 pooka mutex_exit(&bufcache_lock); 91 1.71 pooka } 92 1.71 pooka 93 1.71 pooka RUMP_COMPONENT(RUMP__FACTION_VFS) 94 1.1 pooka { 95 1.39 pooka extern struct vfsops rumpfs_vfsops; 96 1.10 pooka char buf[64]; 97 1.78 pooka char *mbase; 98 1.38 pooka int rv, i; 99 1.1 pooka 100 1.71 pooka /* initialize indirect interfaces */ 101 1.71 pooka rump_vfs_fini = fini; 102 1.71 pooka rump_vfs_drainbufs = drainbufs; 103 1.71 pooka 104 1.75 pooka if (rumpuser_getparam("RUMP_NVNODES", buf, sizeof(buf)) == 0) { 105 1.10 pooka desiredvnodes = strtoul(buf, NULL, 10); 106 1.10 pooka } else { 107 1.50 pooka desiredvnodes = 1<<10; 108 1.10 pooka } 109 1.10 pooka 110 1.16 pooka rumpblk_init(); 111 1.16 pooka 112 1.38 pooka for (i = 0; i < ncpu; i++) { 113 1.38 pooka struct cpu_info *ci = cpu_lookup(i); 114 1.38 pooka cache_cpu_init(ci); 115 1.38 pooka } 116 1.58 pooka 117 1.58 pooka /* make number of bufpages 5% of total memory limit */ 118 1.58 pooka if (rump_physmemlimit != RUMPMEM_UNLIMITED) { 119 1.58 pooka extern u_int bufpages; 120 1.58 pooka bufpages = rump_physmemlimit / (20 * PAGE_SIZE); 121 1.58 pooka } 122 1.58 pooka 123 1.85 pgoyette bufq_init(); 124 1.88 hannken fstrans_init(); 125 1.1 pooka vfsinit(); 126 1.1 pooka bufinit(); 127 1.96 ad lf_init(); 128 1.40 pooka spec_init(); 129 1.11 pooka 130 1.39 pooka root_device = &rump_rootdev; 131 1.36 pooka 132 1.37 pooka /* bootstrap cwdi (rest done in vfs_mountroot() */ 133 1.37 pooka proc0.p_cwdi = &cwdi0; 134 1.37 pooka proc0.p_cwdi = cwdinit(); 135 1.37 pooka 136 1.39 pooka vfs_attach(&rumpfs_vfsops); 137 1.35 pooka vfs_mountroot(); 138 1.1 pooka 139 1.79 pooka /* "mtree": create /dev and /tmp */ 140 1.77 pooka do_sys_mkdir("/dev", 0755, UIO_SYSSPACE); 141 1.80 pooka do_sys_mkdir("/tmp", 01777, UIO_SYSSPACE); 142 1.80 pooka do_sys_chmodat(curlwp, AT_FDCWD, "/tmp", 01777, 0); 143 1.41 pooka 144 1.1 pooka rump_proc_vfs_init = pvfs_init; 145 1.1 pooka rump_proc_vfs_release = pvfs_rele; 146 1.1 pooka 147 1.15 pooka if (rump_threads) { 148 1.15 pooka if ((rv = kthread_create(PRI_IOFLUSH, KTHREAD_MPSAFE, NULL, 149 1.15 pooka sched_sync, NULL, NULL, "ioflush")) != 0) 150 1.15 pooka panic("syncer thread create failed: %d", rv); 151 1.16 pooka } else { 152 1.16 pooka syncdelay = 0; 153 1.15 pooka } 154 1.43 pooka 155 1.47 pooka /* 156 1.47 pooka * On archs where the native kernel ABI is supported, map 157 1.47 pooka * host module directory to rump. This means that kernel 158 1.47 pooka * modules from the host will be autoloaded to rump kernels. 159 1.47 pooka */ 160 1.78 pooka if (rump_nativeabi_p()) { 161 1.78 pooka if (rumpuser_getparam("RUMP_MODULEBASE", buf, sizeof(buf)) == 0) 162 1.78 pooka mbase = buf; 163 1.78 pooka else 164 1.78 pooka mbase = module_base; 165 1.78 pooka 166 1.78 pooka if (strlen(mbase) != 0 && *mbase != '0') { 167 1.78 pooka rump_etfs_register(module_base, mbase, 168 1.78 pooka RUMP_ETFS_DIR_SUBDIRS); 169 1.78 pooka } 170 1.53 pooka } 171 1.47 pooka 172 1.86 pgoyette module_init_class(MODULE_CLASS_BUFQ); 173 1.43 pooka module_init_class(MODULE_CLASS_VFS); 174 1.48 pooka 175 1.72 pooka /* 176 1.72 pooka * Don't build device names for a large set of devices by 177 1.72 pooka * default. While the pseudo-devfs is a fun experiment, 178 1.72 pooka * creating many many device nodes may increase rump kernel 179 1.72 pooka * bootstrap time by ~40%. Device nodes should be created 180 1.72 pooka * per-demand in the component constructors. 181 1.72 pooka */ 182 1.72 pooka #if 0 183 1.72 pooka { 184 1.72 pooka extern struct devsw_conv devsw_conv0[]; 185 1.72 pooka extern int max_devsw_convs; 186 1.48 pooka rump_vfs_builddevs(devsw_conv0, max_devsw_convs); 187 1.72 pooka } 188 1.72 pooka #else 189 1.72 pooka rump_vfs_builddevs(NULL, 0); 190 1.72 pooka #endif 191 1.56 pooka 192 1.73 pooka /* attach null device and create /dev/{null,zero} */ 193 1.73 pooka rump_devnull_init(); 194 1.73 pooka 195 1.56 pooka rump_component_init(RUMP_COMPONENT_VFS); 196 1.1 pooka } 197 1.1 pooka 198 1.62 pooka struct rumpcn { 199 1.62 pooka struct componentname rcn_cn; 200 1.62 pooka char *rcn_path; 201 1.62 pooka }; 202 1.62 pooka 203 1.1 pooka struct componentname * 204 1.32 pooka rump_makecn(u_long nameiop, u_long flags, const char *name, size_t namelen, 205 1.1 pooka kauth_cred_t creds, struct lwp *l) 206 1.1 pooka { 207 1.62 pooka struct rumpcn *rcn; 208 1.1 pooka struct componentname *cnp; 209 1.1 pooka 210 1.62 pooka rcn = kmem_zalloc(sizeof(*rcn), KM_SLEEP); 211 1.62 pooka cnp = &rcn->rcn_cn; 212 1.62 pooka 213 1.62 pooka rcn->rcn_path = PNBUF_GET(); 214 1.62 pooka strlcpy(rcn->rcn_path, name, MAXPATHLEN); 215 1.62 pooka cnp->cn_nameptr = rcn->rcn_path; 216 1.1 pooka 217 1.1 pooka cnp->cn_nameiop = nameiop; 218 1.65 pooka cnp->cn_flags = flags & (MODMASK | PARAMASK); 219 1.1 pooka 220 1.1 pooka cnp->cn_namelen = namelen; 221 1.1 pooka 222 1.1 pooka cnp->cn_cred = creds; 223 1.1 pooka 224 1.1 pooka return cnp; 225 1.1 pooka } 226 1.1 pooka 227 1.1 pooka void 228 1.32 pooka rump_freecn(struct componentname *cnp, int flags) 229 1.1 pooka { 230 1.62 pooka struct rumpcn *rcn = (void *)cnp; 231 1.1 pooka 232 1.1 pooka if (flags & RUMPCN_FREECRED) 233 1.32 pooka rump_cred_put(cnp->cn_cred); 234 1.1 pooka 235 1.62 pooka PNBUF_PUT(rcn->rcn_path); 236 1.63 pooka kmem_free(rcn, sizeof(*rcn)); 237 1.1 pooka } 238 1.1 pooka 239 1.1 pooka /* hey baby, what's your namei? */ 240 1.1 pooka int 241 1.32 pooka rump_namei(uint32_t op, uint32_t flags, const char *namep, 242 1.1 pooka struct vnode **dvpp, struct vnode **vpp, struct componentname **cnpp) 243 1.1 pooka { 244 1.59 dholland struct pathbuf *pb; 245 1.1 pooka struct nameidata nd; 246 1.1 pooka int rv; 247 1.1 pooka 248 1.59 dholland pb = pathbuf_create(namep); 249 1.59 dholland if (pb == NULL) { 250 1.59 dholland return ENOMEM; 251 1.59 dholland } 252 1.59 dholland NDINIT(&nd, op, flags, pb); 253 1.1 pooka rv = namei(&nd); 254 1.59 dholland if (rv) { 255 1.59 dholland pathbuf_destroy(pb); 256 1.1 pooka return rv; 257 1.59 dholland } 258 1.1 pooka 259 1.1 pooka if (dvpp) { 260 1.1 pooka KASSERT(flags & LOCKPARENT); 261 1.1 pooka *dvpp = nd.ni_dvp; 262 1.1 pooka } else { 263 1.1 pooka KASSERT((flags & LOCKPARENT) == 0); 264 1.1 pooka } 265 1.1 pooka 266 1.1 pooka if (vpp) { 267 1.1 pooka *vpp = nd.ni_vp; 268 1.1 pooka } else { 269 1.1 pooka if (nd.ni_vp) { 270 1.1 pooka if (flags & LOCKLEAF) 271 1.1 pooka vput(nd.ni_vp); 272 1.1 pooka else 273 1.1 pooka vrele(nd.ni_vp); 274 1.1 pooka } 275 1.1 pooka } 276 1.1 pooka 277 1.1 pooka if (cnpp) { 278 1.1 pooka struct componentname *cnp; 279 1.1 pooka 280 1.1 pooka cnp = kmem_alloc(sizeof(*cnp), KM_SLEEP); 281 1.1 pooka memcpy(cnp, &nd.ni_cnd, sizeof(*cnp)); 282 1.1 pooka *cnpp = cnp; 283 1.1 pooka } 284 1.59 dholland pathbuf_destroy(pb); 285 1.1 pooka 286 1.1 pooka return rv; 287 1.1 pooka } 288 1.1 pooka 289 1.1 pooka void 290 1.69 pooka rump_getvninfo(struct vnode *vp, enum rump_vtype *vtype, 291 1.31 pooka voff_t *vsize, dev_t *vdev) 292 1.1 pooka { 293 1.1 pooka 294 1.70 pooka *vtype = (enum rump_vtype)vp->v_type; 295 1.1 pooka *vsize = vp->v_size; 296 1.1 pooka if (vp->v_specnode) 297 1.1 pooka *vdev = vp->v_rdev; 298 1.1 pooka else 299 1.1 pooka *vdev = 0; 300 1.1 pooka } 301 1.1 pooka 302 1.1 pooka struct vfsops * 303 1.32 pooka rump_vfslist_iterate(struct vfsops *ops) 304 1.1 pooka { 305 1.1 pooka 306 1.1 pooka if (ops == NULL) 307 1.1 pooka return LIST_FIRST(&vfs_list); 308 1.1 pooka else 309 1.1 pooka return LIST_NEXT(ops, vfs_list); 310 1.1 pooka } 311 1.1 pooka 312 1.1 pooka struct vfsops * 313 1.32 pooka rump_vfs_getopsbyname(const char *name) 314 1.1 pooka { 315 1.1 pooka 316 1.1 pooka return vfs_getopsbyname(name); 317 1.1 pooka } 318 1.1 pooka 319 1.19 pooka int 320 1.32 pooka rump_vfs_getmp(const char *path, struct mount **mpp) 321 1.19 pooka { 322 1.19 pooka struct vnode *vp; 323 1.19 pooka int rv; 324 1.19 pooka 325 1.23 dholland if ((rv = namei_simple_user(path, NSM_FOLLOW_TRYEMULROOT, &vp)) != 0) 326 1.19 pooka return rv; 327 1.19 pooka 328 1.19 pooka *mpp = vp->v_mount; 329 1.19 pooka vrele(vp); 330 1.19 pooka return 0; 331 1.19 pooka } 332 1.19 pooka 333 1.1 pooka struct vattr* 334 1.32 pooka rump_vattr_init(void) 335 1.1 pooka { 336 1.1 pooka struct vattr *vap; 337 1.1 pooka 338 1.1 pooka vap = kmem_alloc(sizeof(struct vattr), KM_SLEEP); 339 1.1 pooka vattr_null(vap); 340 1.1 pooka 341 1.1 pooka return vap; 342 1.1 pooka } 343 1.1 pooka 344 1.1 pooka void 345 1.69 pooka rump_vattr_settype(struct vattr *vap, enum rump_vtype vt) 346 1.1 pooka { 347 1.1 pooka 348 1.70 pooka vap->va_type = (enum vtype)vt; 349 1.1 pooka } 350 1.1 pooka 351 1.1 pooka void 352 1.32 pooka rump_vattr_setmode(struct vattr *vap, mode_t mode) 353 1.1 pooka { 354 1.1 pooka 355 1.1 pooka vap->va_mode = mode; 356 1.1 pooka } 357 1.1 pooka 358 1.1 pooka void 359 1.32 pooka rump_vattr_setrdev(struct vattr *vap, dev_t dev) 360 1.1 pooka { 361 1.1 pooka 362 1.1 pooka vap->va_rdev = dev; 363 1.1 pooka } 364 1.1 pooka 365 1.1 pooka void 366 1.32 pooka rump_vattr_free(struct vattr *vap) 367 1.1 pooka { 368 1.1 pooka 369 1.1 pooka kmem_free(vap, sizeof(*vap)); 370 1.1 pooka } 371 1.1 pooka 372 1.1 pooka void 373 1.32 pooka rump_vp_incref(struct vnode *vp) 374 1.1 pooka { 375 1.1 pooka 376 1.29 pooka vref(vp); 377 1.1 pooka } 378 1.1 pooka 379 1.1 pooka int 380 1.32 pooka rump_vp_getref(struct vnode *vp) 381 1.1 pooka { 382 1.1 pooka 383 1.91 ad return vrefcnt(vp); 384 1.1 pooka } 385 1.1 pooka 386 1.1 pooka void 387 1.32 pooka rump_vp_rele(struct vnode *vp) 388 1.1 pooka { 389 1.1 pooka 390 1.1 pooka vrele(vp); 391 1.1 pooka } 392 1.1 pooka 393 1.1 pooka void 394 1.32 pooka rump_vp_interlock(struct vnode *vp) 395 1.1 pooka { 396 1.1 pooka 397 1.66 rmind mutex_enter(vp->v_interlock); 398 1.1 pooka } 399 1.1 pooka 400 1.90 ad void 401 1.90 ad rump_vp_vmobjlock(struct vnode *vp, int write) 402 1.90 ad { 403 1.90 ad 404 1.90 ad rw_enter(vp->v_uobj.vmobjlock, write ? RW_WRITER : RW_READER); 405 1.90 ad } 406 1.90 ad 407 1.1 pooka int 408 1.32 pooka rump_vfs_unmount(struct mount *mp, int mntflags) 409 1.1 pooka { 410 1.1 pooka 411 1.1 pooka return VFS_UNMOUNT(mp, mntflags); 412 1.1 pooka } 413 1.1 pooka 414 1.1 pooka int 415 1.32 pooka rump_vfs_root(struct mount *mp, struct vnode **vpp, int lock) 416 1.1 pooka { 417 1.1 pooka int rv; 418 1.1 pooka 419 1.89 ad rv = VFS_ROOT(mp, LK_EXCLUSIVE, vpp); 420 1.1 pooka if (rv) 421 1.1 pooka return rv; 422 1.1 pooka 423 1.1 pooka if (!lock) 424 1.55 hannken VOP_UNLOCK(*vpp); 425 1.1 pooka 426 1.1 pooka return 0; 427 1.1 pooka } 428 1.1 pooka 429 1.1 pooka int 430 1.32 pooka rump_vfs_statvfs(struct mount *mp, struct statvfs *sbp) 431 1.1 pooka { 432 1.1 pooka 433 1.1 pooka return VFS_STATVFS(mp, sbp); 434 1.1 pooka } 435 1.1 pooka 436 1.1 pooka int 437 1.32 pooka rump_vfs_sync(struct mount *mp, int wait, kauth_cred_t cred) 438 1.1 pooka { 439 1.1 pooka 440 1.1 pooka return VFS_SYNC(mp, wait ? MNT_WAIT : MNT_NOWAIT, cred); 441 1.1 pooka } 442 1.1 pooka 443 1.1 pooka int 444 1.32 pooka rump_vfs_fhtovp(struct mount *mp, struct fid *fid, struct vnode **vpp) 445 1.1 pooka { 446 1.1 pooka 447 1.89 ad return VFS_FHTOVP(mp, fid, LK_EXCLUSIVE, vpp); 448 1.1 pooka } 449 1.1 pooka 450 1.1 pooka int 451 1.32 pooka rump_vfs_vptofh(struct vnode *vp, struct fid *fid, size_t *fidsize) 452 1.1 pooka { 453 1.1 pooka 454 1.1 pooka return VFS_VPTOFH(vp, fid, fidsize); 455 1.1 pooka } 456 1.1 pooka 457 1.51 pooka int 458 1.51 pooka rump_vfs_extattrctl(struct mount *mp, int cmd, struct vnode *vp, 459 1.51 pooka int attrnamespace, const char *attrname) 460 1.51 pooka { 461 1.51 pooka 462 1.51 pooka return VFS_EXTATTRCTL(mp, cmd, vp, attrnamespace, attrname); 463 1.51 pooka } 464 1.51 pooka 465 1.1 pooka /*ARGSUSED*/ 466 1.1 pooka void 467 1.32 pooka rump_vfs_syncwait(struct mount *mp) 468 1.1 pooka { 469 1.1 pooka int n; 470 1.1 pooka 471 1.92 ad n = vfs_syncwait(); 472 1.1 pooka if (n) 473 1.1 pooka printf("syncwait: unsynced buffers: %d\n", n); 474 1.1 pooka } 475 1.1 pooka 476 1.52 pooka /* 477 1.52 pooka * Dump info about mount point. No locking. 478 1.52 pooka */ 479 1.83 hannken static bool 480 1.83 hannken rump_print_selector(void *cl, struct vnode *vp) 481 1.83 hannken { 482 1.83 hannken int *full = cl; 483 1.83 hannken 484 1.87 riastrad KASSERT(mutex_owned(vp->v_interlock)); 485 1.87 riastrad 486 1.83 hannken vfs_vnode_print(vp, *full, (void *)rumpuser_dprintf); 487 1.83 hannken return false; 488 1.83 hannken } 489 1.83 hannken 490 1.52 pooka void 491 1.52 pooka rump_vfs_mount_print(const char *path, int full) 492 1.52 pooka { 493 1.52 pooka #ifdef DEBUGPRINT 494 1.52 pooka struct vnode *mvp; 495 1.83 hannken struct vnode_iterator *marker; 496 1.52 pooka int error; 497 1.52 pooka 498 1.52 pooka rumpuser_dprintf("\n==== dumping mountpoint at ``%s'' ====\n\n", path); 499 1.52 pooka if ((error = namei_simple_user(path, NSM_FOLLOW_NOEMULROOT, &mvp))!=0) { 500 1.52 pooka rumpuser_dprintf("==== lookup error %d ====\n\n", error); 501 1.52 pooka return; 502 1.52 pooka } 503 1.52 pooka vfs_mount_print(mvp->v_mount, full, (void *)rumpuser_dprintf); 504 1.52 pooka if (full) { 505 1.52 pooka rumpuser_dprintf("\n== dumping vnodes ==\n\n"); 506 1.83 hannken vfs_vnode_iterator_init(mvp->v_mount, &marker); 507 1.83 hannken vfs_vnode_iterator_next(marker, rump_print_selector, &full); 508 1.83 hannken vfs_vnode_iterator_destroy(marker); 509 1.52 pooka } 510 1.52 pooka vrele(mvp); 511 1.52 pooka rumpuser_dprintf("\n==== done ====\n\n"); 512 1.52 pooka #else 513 1.52 pooka rumpuser_dprintf("mount dump not supported without DEBUGPRINT\n"); 514 1.52 pooka #endif 515 1.52 pooka } 516 1.52 pooka 517 1.1 pooka void 518 1.1 pooka rump_biodone(void *arg, size_t count, int error) 519 1.1 pooka { 520 1.1 pooka struct buf *bp = arg; 521 1.1 pooka 522 1.1 pooka bp->b_resid = bp->b_bcount - count; 523 1.1 pooka KASSERT(bp->b_resid >= 0); 524 1.1 pooka bp->b_error = error; 525 1.1 pooka 526 1.1 pooka biodone(bp); 527 1.1 pooka } 528