1 1.75 andvar /* $NetBSD: p2k.c,v 1.75 2022/05/24 20:50:17 andvar Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.19 pooka * Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.19 pooka * Development of this software was supported by the 7 1.19 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.1 pooka /* 32 1.1 pooka * puffs 2k, i.e. puffs 2 kernel. Converts the puffs protocol to 33 1.1 pooka * the kernel vfs protocol and vice versa. 34 1.1 pooka * 35 1.1 pooka * A word about reference counting: puffs in the kernel is the king of 36 1.1 pooka * reference counting. We must maintain a vnode alive and kicking 37 1.1 pooka * until the kernel tells us to reclaim it. Therefore we make sure 38 1.1 pooka * we never accidentally lose a vnode. Before calling operations which 39 1.1 pooka * decrease the refcount we always bump the refcount up to compensate. 40 1.1 pooka * Come inactive, if the file system thinks that the vnode should be 41 1.1 pooka * put out of its misery, it will set the recycle flag. We use this 42 1.1 pooka * to tell the kernel to reclaim the vnode. Only in reclaim do we 43 1.1 pooka * really nuke the last reference. 44 1.1 pooka */ 45 1.1 pooka 46 1.4 pooka #include <sys/cdefs.h> 47 1.1 pooka #include <sys/mount.h> 48 1.1 pooka #include <sys/param.h> 49 1.1 pooka #include <sys/lock.h> 50 1.1 pooka #include <sys/namei.h> 51 1.1 pooka #include <sys/dirent.h> 52 1.17 pooka #include <sys/hash.h> 53 1.1 pooka 54 1.1 pooka #include <assert.h> 55 1.1 pooka #include <errno.h> 56 1.1 pooka #include <puffs.h> 57 1.1 pooka #include <stdlib.h> 58 1.10 pooka #include <stdio.h> 59 1.1 pooka 60 1.1 pooka #include <rump/rump.h> 61 1.68 pooka #include <rump/rumpvnode_if.h> 62 1.1 pooka #include <rump/p2k.h> 63 1.1 pooka #include <rump/ukfs.h> 64 1.1 pooka 65 1.67 christos #include <uvm/uvm_pager.h> 66 1.67 christos 67 1.35 pooka /* NetBSD-5 compat */ 68 1.35 pooka #ifndef MOUNT_RUMPFS 69 1.35 pooka #define MOUNT_RUMPFS "rumpfs" 70 1.35 pooka #endif 71 1.35 pooka 72 1.1 pooka PUFFSOP_PROTOS(p2k) 73 1.1 pooka 74 1.17 pooka LIST_HEAD(p2k_vp_hash, p2k_node); 75 1.17 pooka #define NHASHBUCK (1<<16) 76 1.17 pooka struct p2k_mount { 77 1.17 pooka struct vnode *p2m_rvp; 78 1.21 pooka struct puffs_usermount *p2m_pu; 79 1.21 pooka struct ukfs *p2m_ukfs; 80 1.17 pooka struct p2k_vp_hash p2m_vphash[NHASHBUCK]; 81 1.35 pooka struct mount *p2m_mp; 82 1.17 pooka int p2m_nvnodes; 83 1.31 pooka int p2m_imtmpfsman; 84 1.36 pooka bool p2m_hasdebug; 85 1.17 pooka }; 86 1.17 pooka 87 1.17 pooka struct p2k_node { 88 1.56 manu struct puffs_node p2n_pn; 89 1.17 pooka struct vnode *p2n_vp; 90 1.17 pooka 91 1.17 pooka LIST_ENTRY(p2k_node) p2n_entries; 92 1.17 pooka }; 93 1.17 pooka 94 1.17 pooka #define OPC2VP(opc) (((struct p2k_node *)opc)->p2n_vp) 95 1.17 pooka 96 1.28 pooka static int haswizard; 97 1.28 pooka static uid_t wizarduid; 98 1.28 pooka 99 1.34 pooka static struct kauth_cred * 100 1.1 pooka cred_create(const struct puffs_cred *pcr) 101 1.1 pooka { 102 1.1 pooka gid_t groups[NGROUPS]; 103 1.1 pooka uid_t uid; 104 1.1 pooka gid_t gid; 105 1.29 pooka short ngroups = __arraycount(groups); 106 1.1 pooka 107 1.28 pooka if (haswizard) { 108 1.28 pooka uid = wizarduid; 109 1.28 pooka } else { 110 1.28 pooka if (puffs_cred_getuid(pcr, &uid) == -1) 111 1.28 pooka uid = 0; 112 1.28 pooka } 113 1.1 pooka if (puffs_cred_getgid(pcr, &gid) == -1) 114 1.1 pooka gid = 0; 115 1.1 pooka puffs_cred_getgroups(pcr, groups, &ngroups); 116 1.1 pooka 117 1.1 pooka /* LINTED: ngroups is ok */ 118 1.23 pooka return rump_pub_cred_create(uid, gid, ngroups, groups); 119 1.1 pooka } 120 1.1 pooka 121 1.1 pooka static __inline void 122 1.34 pooka cred_destroy(struct kauth_cred *cred) 123 1.1 pooka { 124 1.1 pooka 125 1.23 pooka rump_pub_cred_put(cred); 126 1.1 pooka } 127 1.1 pooka 128 1.1 pooka static struct componentname * 129 1.47 pooka makecn(const struct puffs_cn *pcn) 130 1.1 pooka { 131 1.34 pooka struct kauth_cred *cred; 132 1.1 pooka 133 1.1 pooka cred = cred_create(pcn->pcn_cred); 134 1.1 pooka /* LINTED: prehistoric types in first two args */ 135 1.47 pooka return rump_pub_makecn(pcn->pcn_nameiop, pcn->pcn_flags, 136 1.42 pooka pcn->pcn_name, pcn->pcn_namelen, cred, rump_pub_lwproc_curlwp()); 137 1.1 pooka } 138 1.1 pooka 139 1.1 pooka static __inline void 140 1.47 pooka freecn(struct componentname *cnp) 141 1.1 pooka { 142 1.1 pooka 143 1.47 pooka rump_pub_freecn(cnp, RUMPCN_FREECRED); 144 1.1 pooka } 145 1.1 pooka 146 1.1 pooka static void 147 1.1 pooka makelwp(struct puffs_usermount *pu) 148 1.1 pooka { 149 1.1 pooka pid_t pid; 150 1.1 pooka lwpid_t lid; 151 1.1 pooka 152 1.1 pooka puffs_cc_getcaller(puffs_cc_getcc(pu), &pid, &lid); 153 1.42 pooka rump_pub_allbetsareoff_setid(pid, lid); 154 1.17 pooka } 155 1.17 pooka 156 1.53 pooka static volatile sig_atomic_t dodump; 157 1.53 pooka static void 158 1.53 pooka dumpmp(struct puffs_usermount *pu) 159 1.53 pooka { 160 1.71 christos struct puffs_statvfs svfsb; 161 1.53 pooka 162 1.53 pooka if (dodump && p2k_fs_statvfs(pu, &svfsb) == 0) { 163 1.53 pooka rump_pub_vfs_mount_print(svfsb.f_mntonname, dodump-1); 164 1.53 pooka } 165 1.53 pooka 166 1.53 pooka dodump = 0; 167 1.53 pooka } 168 1.53 pooka 169 1.53 pooka static void 170 1.53 pooka sighand(int sig) 171 1.53 pooka { 172 1.53 pooka 173 1.53 pooka if (sig == SIGINFO) 174 1.53 pooka dodump = 1; 175 1.53 pooka else if (sig == SIGUSR1) 176 1.53 pooka dodump = 2; 177 1.53 pooka } 178 1.53 pooka 179 1.17 pooka static __inline struct p2k_vp_hash * 180 1.17 pooka gethash(struct p2k_mount *p2m, struct vnode *vp) 181 1.17 pooka { 182 1.17 pooka uint32_t hash; 183 1.17 pooka 184 1.17 pooka hash = hash32_buf(&vp, sizeof(vp), HASH32_BUF_INIT); 185 1.17 pooka return &p2m->p2m_vphash[hash % NHASHBUCK]; 186 1.17 pooka } 187 1.17 pooka 188 1.17 pooka /* 189 1.17 pooka * Find node based on hash of vnode pointer. If vnode is found, 190 1.17 pooka * releases one reference to vnode based on the fact that we just 191 1.17 pooka * performed a lookup for it. 192 1.17 pooka * 193 1.17 pooka * If the optinal p2n_storage parameter is passed, it is used instead 194 1.17 pooka * of allocating more memory. This allows for easier error recovery. 195 1.17 pooka */ 196 1.17 pooka static struct p2k_node * 197 1.17 pooka getp2n(struct p2k_mount *p2m, struct vnode *vp, bool initial, 198 1.17 pooka struct p2k_node *p2n_storage) 199 1.17 pooka { 200 1.17 pooka struct p2k_vp_hash *hl; 201 1.17 pooka struct p2k_node *p2n = NULL; 202 1.17 pooka 203 1.17 pooka /* p2n_storage => initial */ 204 1.17 pooka assert(!p2n_storage || initial); 205 1.17 pooka 206 1.17 pooka hl = gethash(p2m, vp); 207 1.17 pooka if (!initial) 208 1.17 pooka LIST_FOREACH(p2n, hl, p2n_entries) 209 1.17 pooka if (p2n->p2n_vp == vp) 210 1.17 pooka break; 211 1.17 pooka 212 1.17 pooka hl = gethash(p2m, vp); 213 1.17 pooka if (p2n) { 214 1.23 pooka rump_pub_vp_rele(vp); 215 1.17 pooka } else { 216 1.17 pooka if (p2n_storage) 217 1.17 pooka p2n = p2n_storage; 218 1.17 pooka else 219 1.17 pooka p2n = malloc(sizeof(*p2n)); 220 1.17 pooka if (!p2n) { 221 1.23 pooka rump_pub_vp_rele(vp); 222 1.17 pooka return NULL; 223 1.17 pooka } 224 1.17 pooka memset(p2n, 0, sizeof(*p2n)); 225 1.17 pooka LIST_INSERT_HEAD(hl, p2n, p2n_entries); 226 1.17 pooka p2n->p2n_vp = vp; 227 1.17 pooka } 228 1.17 pooka return p2n; 229 1.17 pooka } 230 1.17 pooka 231 1.17 pooka static void 232 1.17 pooka freep2n(struct p2k_node *p2n) 233 1.17 pooka { 234 1.17 pooka 235 1.17 pooka assert(p2n->p2n_vp == NULL); 236 1.17 pooka LIST_REMOVE(p2n, p2n_entries); 237 1.17 pooka free(p2n); 238 1.1 pooka } 239 1.1 pooka 240 1.11 pooka /*ARGSUSED*/ 241 1.10 pooka static void 242 1.10 pooka p2k_errcatcher(struct puffs_usermount *pu, uint8_t type, int error, 243 1.10 pooka const char *str, puffs_cookie_t cook) 244 1.10 pooka { 245 1.10 pooka 246 1.10 pooka fprintf(stderr, "type %d, error %d, cookie %p (%s)\n", 247 1.10 pooka type, error, cook, str); 248 1.10 pooka 249 1.10 pooka /* 250 1.10 pooka * Trap all EINVAL responses to lookup. It most likely means 251 1.10 pooka * that we supplied VNON/VBAD as the type. The real kernel 252 1.10 pooka * doesn't panic from this either, but just handles it. 253 1.10 pooka */ 254 1.10 pooka if (type != PUFFS_VN_LOOKUP && error == EINVAL) 255 1.10 pooka abort(); 256 1.10 pooka } 257 1.10 pooka 258 1.17 pooka /* just to avoid annoying loop when singlestepping */ 259 1.26 pooka static struct p2k_mount * 260 1.26 pooka allocp2m(void) 261 1.17 pooka { 262 1.17 pooka struct p2k_mount *p2m; 263 1.17 pooka int i; 264 1.17 pooka 265 1.17 pooka p2m = malloc(sizeof(*p2m)); 266 1.26 pooka if (p2m == NULL) 267 1.26 pooka return NULL; 268 1.21 pooka memset(p2m, 0, sizeof(*p2m)); 269 1.21 pooka 270 1.17 pooka for (i = 0; i < NHASHBUCK; i++) 271 1.17 pooka LIST_INIT(&p2m->p2m_vphash[i]); 272 1.26 pooka 273 1.26 pooka return p2m; 274 1.17 pooka } 275 1.17 pooka 276 1.26 pooka struct p2k_mount * 277 1.26 pooka p2k_init(uint32_t puffs_flags) 278 1.1 pooka { 279 1.1 pooka struct puffs_ops *pops; 280 1.26 pooka struct p2k_mount *p2m; 281 1.28 pooka char *envbuf; 282 1.6 pooka bool dodaemon; 283 1.36 pooka bool hasdebug; 284 1.1 pooka 285 1.1 pooka PUFFSOP_INIT(pops); 286 1.1 pooka 287 1.1 pooka PUFFSOP_SET(pops, p2k, fs, statvfs); 288 1.1 pooka PUFFSOP_SET(pops, p2k, fs, unmount); 289 1.1 pooka PUFFSOP_SET(pops, p2k, fs, sync); 290 1.1 pooka PUFFSOP_SET(pops, p2k, fs, fhtonode); 291 1.1 pooka PUFFSOP_SET(pops, p2k, fs, nodetofh); 292 1.38 pooka PUFFSOP_SET(pops, p2k, fs, extattrctl); 293 1.1 pooka 294 1.1 pooka PUFFSOP_SET(pops, p2k, node, lookup); 295 1.1 pooka PUFFSOP_SET(pops, p2k, node, create); 296 1.1 pooka PUFFSOP_SET(pops, p2k, node, mknod); 297 1.1 pooka PUFFSOP_SET(pops, p2k, node, open); 298 1.1 pooka PUFFSOP_SET(pops, p2k, node, close); 299 1.1 pooka PUFFSOP_SET(pops, p2k, node, access); 300 1.1 pooka PUFFSOP_SET(pops, p2k, node, getattr); 301 1.1 pooka PUFFSOP_SET(pops, p2k, node, setattr); 302 1.1 pooka #if 0 303 1.1 pooka PUFFSOP_SET(pops, p2k, node, poll); 304 1.1 pooka #endif 305 1.1 pooka PUFFSOP_SET(pops, p2k, node, mmap); 306 1.1 pooka PUFFSOP_SET(pops, p2k, node, fsync); 307 1.1 pooka PUFFSOP_SET(pops, p2k, node, seek); 308 1.1 pooka PUFFSOP_SET(pops, p2k, node, remove); 309 1.1 pooka PUFFSOP_SET(pops, p2k, node, link); 310 1.1 pooka PUFFSOP_SET(pops, p2k, node, rename); 311 1.1 pooka PUFFSOP_SET(pops, p2k, node, mkdir); 312 1.1 pooka PUFFSOP_SET(pops, p2k, node, rmdir); 313 1.1 pooka PUFFSOP_SET(pops, p2k, node, symlink); 314 1.1 pooka PUFFSOP_SET(pops, p2k, node, readdir); 315 1.1 pooka PUFFSOP_SET(pops, p2k, node, readlink); 316 1.1 pooka PUFFSOP_SET(pops, p2k, node, read); 317 1.1 pooka PUFFSOP_SET(pops, p2k, node, write); 318 1.1 pooka 319 1.39 pooka PUFFSOP_SET(pops, p2k, node, pathconf); 320 1.39 pooka 321 1.1 pooka PUFFSOP_SET(pops, p2k, node, inactive); 322 1.1 pooka PUFFSOP_SET(pops, p2k, node, reclaim); 323 1.1 pooka 324 1.38 pooka PUFFSOP_SET(pops, p2k, node, getextattr); 325 1.38 pooka PUFFSOP_SET(pops, p2k, node, setextattr); 326 1.38 pooka PUFFSOP_SET(pops, p2k, node, listextattr); 327 1.38 pooka PUFFSOP_SET(pops, p2k, node, deleteextattr); 328 1.38 pooka 329 1.6 pooka dodaemon = true; 330 1.37 pooka hasdebug = false; 331 1.37 pooka 332 1.6 pooka if (getenv("P2K_DEBUG") != NULL) { 333 1.6 pooka puffs_flags |= PUFFS_FLAG_OPDUMP; 334 1.6 pooka dodaemon = false; 335 1.36 pooka hasdebug = true; 336 1.6 pooka } 337 1.8 pooka if (getenv("P2K_NODETACH") != NULL) { 338 1.8 pooka dodaemon = false; 339 1.8 pooka } 340 1.13 pooka if (getenv("P2K_NOCACHE_PAGE") != NULL) { 341 1.13 pooka puffs_flags |= PUFFS_KFLAG_NOCACHE_PAGE; 342 1.13 pooka } 343 1.13 pooka if (getenv("P2K_NOCACHE_NAME") != NULL) { 344 1.13 pooka puffs_flags |= PUFFS_KFLAG_NOCACHE_NAME; 345 1.13 pooka } 346 1.13 pooka if (getenv("P2K_NOCACHE") != NULL) { 347 1.13 pooka puffs_flags |= PUFFS_KFLAG_NOCACHE; 348 1.13 pooka } 349 1.28 pooka if ((envbuf = getenv("P2K_WIZARDUID")) != NULL) { 350 1.54 pooka char *ep; 351 1.54 pooka 352 1.54 pooka wizarduid = strtoul(envbuf, &ep, 10); 353 1.54 pooka if (envbuf[0] == '\0' || *ep != '\0') { 354 1.54 pooka printf("P2K_WIZARDUID: invalid uid %s\n", envbuf); 355 1.54 pooka } else if (wizarduid > UID_MAX) { 356 1.54 pooka printf("P2K_WIZARDUID: uid %s out-of-range\n", envbuf); 357 1.54 pooka } else { 358 1.54 pooka haswizard = 1; 359 1.54 pooka printf("P2K WIZARD MODE: using uid %d\n", wizarduid); 360 1.54 pooka } 361 1.28 pooka } 362 1.6 pooka 363 1.57 manu /* 364 1.75 andvar * Explicitly tell that our cookies can be treated as 365 1.57 manu * puffs_node, since we never let libpuffs know by 366 1.57 manu * calling call puffs_pn_new() 367 1.57 manu */ 368 1.57 manu puffs_flags |= PUFFS_FLAG_PNCOOKIE; 369 1.57 manu 370 1.26 pooka p2m = allocp2m(); 371 1.26 pooka if (p2m == NULL) 372 1.26 pooka return NULL; 373 1.26 pooka p2m->p2m_pu = puffs_init(pops, PUFFS_DEFER, PUFFS_DEFER, 374 1.26 pooka PUFFS_DEFER, puffs_flags); 375 1.26 pooka if (p2m->p2m_pu == NULL) { 376 1.26 pooka int sverrno = errno; 377 1.26 pooka free(p2m); 378 1.26 pooka errno = sverrno; 379 1.26 pooka return NULL; 380 1.26 pooka } 381 1.36 pooka p2m->p2m_hasdebug = hasdebug; 382 1.26 pooka 383 1.26 pooka if (dodaemon) { 384 1.26 pooka if (puffs_daemon(p2m->p2m_pu, 1, 1) == -1) { 385 1.26 pooka int sverrno = errno; 386 1.26 pooka p2k_cancel(p2m, sverrno); 387 1.26 pooka errno = sverrno; 388 1.26 pooka p2m = NULL; 389 1.26 pooka } 390 1.26 pooka } 391 1.26 pooka if (p2m) 392 1.26 pooka rump_init(); 393 1.26 pooka 394 1.49 pooka rump_pub_lwproc_rfork(RUMP_RFCFDG); 395 1.42 pooka 396 1.26 pooka return p2m; 397 1.26 pooka } 398 1.26 pooka 399 1.26 pooka void 400 1.26 pooka p2k_cancel(struct p2k_mount *p2m, int error) 401 1.26 pooka { 402 1.26 pooka 403 1.26 pooka puffs_cancel(p2m->p2m_pu, error); 404 1.26 pooka free(p2m); 405 1.26 pooka } 406 1.26 pooka 407 1.26 pooka static int 408 1.26 pooka setupfs(struct p2k_mount *p2m, const char *vfsname, const char *devpath, 409 1.30 pooka struct ukfs_part *part, const char *mountpath, int mntflags, 410 1.26 pooka void *arg, size_t alen) 411 1.26 pooka { 412 1.30 pooka char partpath[UKFS_DEVICE_MAXPATHLEN]; 413 1.30 pooka char partbuf[UKFS_DEVICE_MAXSTR]; 414 1.26 pooka char typebuf[PUFFS_TYPELEN]; 415 1.26 pooka struct puffs_usermount *pu = p2m->p2m_pu; 416 1.26 pooka struct p2k_node *p2n_root; 417 1.26 pooka struct ukfs *ukfs = NULL; 418 1.26 pooka extern int puffs_fakecc; 419 1.26 pooka int rv = -1, sverrno; 420 1.26 pooka 421 1.1 pooka strcpy(typebuf, "p2k|"); 422 1.1 pooka if (strcmp(vfsname, "puffs") == 0) { /* XXX */ 423 1.1 pooka struct puffs_kargs *args = arg; 424 1.1 pooka strlcat(typebuf, args->pa_typename, sizeof(typebuf)); 425 1.1 pooka } else { 426 1.1 pooka strlcat(typebuf, vfsname, sizeof(typebuf)); 427 1.1 pooka } 428 1.1 pooka 429 1.30 pooka strlcpy(partpath, devpath, sizeof(partpath)); 430 1.30 pooka if (ukfs_part_tostring(part, partbuf, sizeof(partbuf))) { 431 1.19 pooka strlcat(partpath, partbuf, sizeof(partpath)); 432 1.19 pooka } 433 1.26 pooka puffs_setmntinfo(pu, partpath, typebuf); 434 1.7 pooka 435 1.7 pooka if (ukfs_init() == -1) 436 1.21 pooka goto out; 437 1.35 pooka 438 1.35 pooka /* 439 1.35 pooka * If we're mounting rumpfs, actually do no mount and redirect 440 1.35 pooka * requests to rump fs namespace root. Strictly speaking, this 441 1.45 pooka * is not correct, but I don't think anyone will notice. 442 1.45 pooka * After all, we're mostly interested in things which reside 443 1.45 pooka * specifically on the rootfs, namely the contents of /dev 444 1.35 pooka */ 445 1.35 pooka if (strcmp(vfsname, MOUNT_RUMPFS) == 0) { 446 1.35 pooka if ((rv = rump_pub_vfs_getmp("/", &p2m->p2m_mp)) != 0) { 447 1.35 pooka errno = rv; 448 1.35 pooka rv = -1; 449 1.35 pooka goto out; 450 1.35 pooka } 451 1.35 pooka } else { 452 1.35 pooka if (part != ukfs_part_na) 453 1.35 pooka ukfs = ukfs_mount_disk(vfsname, devpath, part, 454 1.35 pooka mountpath, mntflags, arg, alen); 455 1.35 pooka else 456 1.35 pooka ukfs = ukfs_mount(vfsname, devpath, mountpath, mntflags, 457 1.35 pooka arg, alen); 458 1.35 pooka if (ukfs == NULL) 459 1.35 pooka goto out; 460 1.35 pooka ukfs_setspecific(ukfs, p2m); 461 1.35 pooka p2m->p2m_ukfs = ukfs; 462 1.35 pooka p2m->p2m_mp = ukfs_getmp(ukfs); 463 1.43 pooka } 464 1.43 pooka if ((rv = rump_pub_vfs_root(p2m->p2m_mp, &p2m->p2m_rvp, 0)) != 0) { 465 1.43 pooka errno = rv; 466 1.43 pooka rv = -1; 467 1.43 pooka goto out; 468 1.35 pooka } 469 1.35 pooka 470 1.21 pooka p2m->p2m_pu = pu; 471 1.7 pooka 472 1.31 pooka /* 473 1.31 pooka * Detect tmpfs. XXX: this is a kludge. See inactive(). 474 1.31 pooka * 475 1.31 pooka * In reality we'd want "does file system use anon objects 476 1.31 pooka * for storage?". But since tmpfs hides the anon object from 477 1.31 pooka * the public interface, we can't actually detect it sanely. 478 1.31 pooka * Therefore, use this kludge. 479 1.31 pooka */ 480 1.31 pooka p2m->p2m_imtmpfsman = strcmp(vfsname, MOUNT_TMPFS) == 0; 481 1.31 pooka 482 1.17 pooka p2n_root = getp2n(p2m, p2m->p2m_rvp, true, NULL); 483 1.1 pooka puffs_setfhsize(pu, 0, PUFFS_FHFLAG_PASSTHROUGH); 484 1.1 pooka puffs_setstacksize(pu, PUFFS_STACKSIZE_MIN); 485 1.1 pooka puffs_fakecc = 1; 486 1.42 pooka puffs_set_prepost(pu, makelwp, NULL); 487 1.53 pooka 488 1.53 pooka if (p2m->p2m_hasdebug) { 489 1.53 pooka struct timespec ts; 490 1.53 pooka 491 1.53 pooka signal(SIGINFO, sighand); 492 1.53 pooka signal(SIGUSR1, sighand); 493 1.53 pooka 494 1.53 pooka ts.tv_sec = 0; 495 1.53 pooka ts.tv_nsec = 1000*1000*10; /* 10ms */ 496 1.53 pooka puffs_ml_setloopfn(pu, dumpmp); 497 1.53 pooka puffs_ml_settimeout(pu, &ts); 498 1.53 pooka } 499 1.10 pooka puffs_set_errnotify(pu, p2k_errcatcher); 500 1.1 pooka 501 1.35 pooka puffs_setspecific(pu, p2m); 502 1.26 pooka rv = puffs_mount(pu, mountpath, mntflags, p2n_root); 503 1.1 pooka 504 1.1 pooka out: 505 1.26 pooka if (rv == -1) { 506 1.26 pooka sverrno = errno; 507 1.26 pooka puffs_cancel(pu, sverrno); 508 1.21 pooka if (ukfs) 509 1.21 pooka ukfs_release(p2m->p2m_ukfs, UKFS_RELFLAG_FORCE); 510 1.26 pooka free(p2m); 511 1.1 pooka errno = sverrno; 512 1.1 pooka } 513 1.1 pooka 514 1.26 pooka return rv; 515 1.21 pooka } 516 1.21 pooka 517 1.21 pooka int 518 1.21 pooka p2k_mainloop(struct p2k_mount *p2m) 519 1.21 pooka { 520 1.21 pooka int rv, sverrno; 521 1.21 pooka 522 1.21 pooka rv = puffs_mainloop(p2m->p2m_pu); 523 1.21 pooka sverrno = errno; 524 1.21 pooka puffs_exit(p2m->p2m_pu, 1); 525 1.21 pooka if (p2m->p2m_ukfs) 526 1.21 pooka ukfs_release(p2m->p2m_ukfs, UKFS_RELFLAG_FORCE); 527 1.21 pooka free(p2m); 528 1.21 pooka 529 1.21 pooka if (rv == -1) 530 1.21 pooka errno = sverrno; 531 1.1 pooka return rv; 532 1.1 pooka } 533 1.1 pooka 534 1.19 pooka int 535 1.19 pooka p2k_run_fs(const char *vfsname, const char *devpath, const char *mountpath, 536 1.19 pooka int mntflags, void *arg, size_t alen, uint32_t puffs_flags) 537 1.19 pooka { 538 1.21 pooka struct p2k_mount *p2m; 539 1.26 pooka int rv; 540 1.19 pooka 541 1.26 pooka p2m = p2k_init(puffs_flags); 542 1.21 pooka if (p2m == NULL) 543 1.21 pooka return -1; 544 1.30 pooka rv = setupfs(p2m, vfsname, devpath, ukfs_part_na, mountpath, 545 1.26 pooka mntflags, arg, alen); 546 1.26 pooka if (rv == -1) 547 1.26 pooka return rv; 548 1.21 pooka return p2k_mainloop(p2m); 549 1.19 pooka } 550 1.19 pooka 551 1.19 pooka int 552 1.30 pooka p2k_run_diskfs(const char *vfsname, const char *devpath, struct ukfs_part *part, 553 1.19 pooka const char *mountpath, int mntflags, void *arg, size_t alen, 554 1.19 pooka uint32_t puffs_flags) 555 1.19 pooka { 556 1.21 pooka struct p2k_mount *p2m; 557 1.26 pooka int rv; 558 1.21 pooka 559 1.26 pooka p2m = p2k_init(puffs_flags); 560 1.21 pooka if (p2m == NULL) 561 1.21 pooka return -1; 562 1.30 pooka rv = setupfs(p2m, vfsname, devpath, part, mountpath, mntflags, 563 1.26 pooka arg, alen); 564 1.26 pooka if (rv == -1) 565 1.26 pooka return rv; 566 1.21 pooka return p2k_mainloop(p2m); 567 1.21 pooka } 568 1.21 pooka 569 1.26 pooka int 570 1.26 pooka p2k_setup_fs(struct p2k_mount *p2m, const char *vfsname, const char *devpath, 571 1.26 pooka const char *mountpath, int mntflags, void *arg, size_t alen) 572 1.21 pooka { 573 1.19 pooka 574 1.30 pooka return setupfs(p2m, vfsname, devpath, ukfs_part_na, mountpath, 575 1.26 pooka mntflags, arg, alen); 576 1.21 pooka } 577 1.21 pooka 578 1.26 pooka int 579 1.26 pooka p2k_setup_diskfs(struct p2k_mount *p2m, const char *vfsname, 580 1.30 pooka const char *devpath, struct ukfs_part *part, const char *mountpath, 581 1.26 pooka int mntflags, void *arg, size_t alen) 582 1.21 pooka { 583 1.21 pooka 584 1.30 pooka return setupfs(p2m, vfsname, devpath, part, mountpath, mntflags, 585 1.26 pooka arg, alen); 586 1.19 pooka } 587 1.19 pooka 588 1.1 pooka int 589 1.71 christos p2k_fs_statvfs(struct puffs_usermount *pu, struct puffs_statvfs *sbp) 590 1.1 pooka { 591 1.35 pooka struct p2k_mount *p2m = puffs_getspecific(pu); 592 1.35 pooka struct mount *mp = p2m->p2m_mp; 593 1.71 christos struct statvfs sb; 594 1.71 christos puffs_statvfs_to_statvfs(sbp, &sb); 595 1.1 pooka 596 1.71 christos return rump_pub_vfs_statvfs(mp, &sb); 597 1.1 pooka } 598 1.1 pooka 599 1.15 pooka /*ARGSUSED*/ 600 1.1 pooka int 601 1.1 pooka p2k_fs_unmount(struct puffs_usermount *pu, int flags) 602 1.1 pooka { 603 1.35 pooka struct p2k_mount *p2m = puffs_getspecific(pu); 604 1.35 pooka struct ukfs *fs = p2m->p2m_ukfs; 605 1.17 pooka int error = 0; 606 1.1 pooka 607 1.42 pooka rump_pub_vp_rele(p2m->p2m_rvp); 608 1.42 pooka 609 1.35 pooka if (fs) { 610 1.35 pooka if (ukfs_release(fs, 0) != 0) { 611 1.71 christos struct puffs_statvfs svfsb; 612 1.52 pooka 613 1.52 pooka if (p2m->p2m_hasdebug 614 1.52 pooka && p2k_fs_statvfs(pu, &svfsb) == 0) { 615 1.52 pooka printf("\nSOFT UNMOUNT FAILED, MP INFO DUMP\n"); 616 1.52 pooka rump_pub_vfs_mount_print(svfsb.f_mntonname, 1); 617 1.52 pooka } 618 1.35 pooka ukfs_release(fs, UKFS_RELFLAG_FORCE); 619 1.35 pooka error = 0; 620 1.35 pooka } 621 1.17 pooka } 622 1.21 pooka p2m->p2m_ukfs = NULL; 623 1.1 pooka 624 1.36 pooka if (p2m->p2m_hasdebug) { 625 1.36 pooka printf("-- rump kernel event counters --\n"); 626 1.36 pooka rump_printevcnts(); 627 1.36 pooka printf("-- end of event counters --\n"); 628 1.36 pooka } 629 1.36 pooka 630 1.17 pooka return error; 631 1.1 pooka } 632 1.1 pooka 633 1.1 pooka int 634 1.1 pooka p2k_fs_sync(struct puffs_usermount *pu, int waitfor, 635 1.1 pooka const struct puffs_cred *pcr) 636 1.1 pooka { 637 1.35 pooka struct p2k_mount *p2m = puffs_getspecific(pu); 638 1.35 pooka struct mount *mp = p2m->p2m_mp; 639 1.34 pooka struct kauth_cred *cred; 640 1.1 pooka int rv; 641 1.1 pooka 642 1.1 pooka cred = cred_create(pcr); 643 1.34 pooka rv = rump_pub_vfs_sync(mp, waitfor, cred); 644 1.1 pooka cred_destroy(cred); 645 1.1 pooka 646 1.1 pooka return rv; 647 1.1 pooka } 648 1.1 pooka 649 1.1 pooka /*ARGSUSED*/ 650 1.1 pooka int 651 1.1 pooka p2k_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, 652 1.1 pooka struct puffs_newinfo *pni) 653 1.1 pooka { 654 1.35 pooka struct p2k_mount *p2m = puffs_getspecific(pu); 655 1.35 pooka struct mount *mp = p2m->p2m_mp; 656 1.17 pooka struct p2k_node *p2n; 657 1.1 pooka struct vnode *vp; 658 1.58 pooka enum rump_vtype vtype; 659 1.1 pooka voff_t vsize; 660 1.17 pooka uint64_t rdev; /* XXX: allows running this on NetBSD 5.0 */ 661 1.1 pooka int rv; 662 1.1 pooka 663 1.23 pooka rv = rump_pub_vfs_fhtovp(mp, fid, &vp); 664 1.1 pooka if (rv) 665 1.1 pooka return rv; 666 1.41 hannken RUMP_VOP_UNLOCK(vp); 667 1.1 pooka 668 1.17 pooka p2n = getp2n(p2m, vp, false, NULL); 669 1.17 pooka if (p2n == NULL) 670 1.17 pooka return ENOMEM; 671 1.17 pooka 672 1.17 pooka puffs_newinfo_setcookie(pni, p2n); 673 1.23 pooka rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev); 674 1.60 joerg puffs_newinfo_setvtype(pni, (enum vtype)vtype); 675 1.1 pooka puffs_newinfo_setsize(pni, vsize); 676 1.17 pooka /* LINTED: yea, it'll lose accuracy, but that's life */ 677 1.1 pooka puffs_newinfo_setrdev(pni, rdev); 678 1.1 pooka 679 1.1 pooka return 0; 680 1.1 pooka } 681 1.1 pooka 682 1.1 pooka /*ARGSUSED*/ 683 1.1 pooka int 684 1.3 pooka p2k_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie, void *fid, 685 1.1 pooka size_t *fidsize) 686 1.1 pooka { 687 1.50 pooka struct vnode *vp = OPC2VP(cookie); 688 1.1 pooka 689 1.23 pooka return rump_pub_vfs_vptofh(vp, fid, fidsize); 690 1.1 pooka } 691 1.1 pooka 692 1.38 pooka int 693 1.38 pooka p2k_fs_extattrctl(struct puffs_usermount *pu, int cmd, 694 1.38 pooka puffs_cookie_t cookie, int flags, 695 1.38 pooka int attrnamespace, const char *attrname) 696 1.38 pooka { 697 1.38 pooka struct p2k_mount *p2m = puffs_getspecific(pu); 698 1.38 pooka struct mount *mp = p2m->p2m_mp; 699 1.38 pooka struct vnode *vp; 700 1.38 pooka 701 1.38 pooka if (flags & PUFFS_EXTATTRCTL_HASNODE) { 702 1.38 pooka vp = OPC2VP(cookie); 703 1.38 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY); 704 1.38 pooka } else { 705 1.38 pooka vp = NULL; 706 1.38 pooka } 707 1.38 pooka 708 1.38 pooka /* vfsop unlocks (but doesn't release) vnode, so we're done here */ 709 1.38 pooka return rump_pub_vfs_extattrctl(mp, cmd, vp, attrnamespace, attrname); 710 1.38 pooka } 711 1.38 pooka 712 1.1 pooka /*ARGSUSED*/ 713 1.1 pooka int 714 1.3 pooka p2k_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc, 715 1.1 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn) 716 1.1 pooka { 717 1.35 pooka struct p2k_mount *p2m = puffs_getspecific(pu); 718 1.17 pooka struct p2k_node *p2n_dir = opc, *p2n; 719 1.1 pooka struct componentname *cn; 720 1.17 pooka struct vnode *dvp = p2n_dir->p2n_vp, *vp; 721 1.58 pooka enum rump_vtype vtype; 722 1.1 pooka voff_t vsize; 723 1.14 pooka uint64_t rdev; /* XXX: uint64_t because of stack overwrite in compat */ 724 1.1 pooka int rv; 725 1.1 pooka 726 1.47 pooka cn = makecn(pcn); 727 1.17 pooka RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); 728 1.17 pooka rv = RUMP_VOP_LOOKUP(dvp, &vp, cn); 729 1.41 hannken RUMP_VOP_UNLOCK(dvp); 730 1.51 pooka freecn(cn); 731 1.47 pooka 732 1.1 pooka if (rv) { 733 1.59 pooka if (rv == RUMP_EJUSTRETURN) { 734 1.1 pooka rv = ENOENT; 735 1.17 pooka } 736 1.1 pooka return rv; 737 1.1 pooka } 738 1.1 pooka 739 1.17 pooka p2n = getp2n(p2m, vp, false, NULL); 740 1.17 pooka if (p2n == NULL) { 741 1.17 pooka return ENOMEM; 742 1.17 pooka } 743 1.17 pooka 744 1.17 pooka puffs_newinfo_setcookie(pni, p2n); 745 1.23 pooka rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev); 746 1.60 joerg puffs_newinfo_setvtype(pni, (enum vtype)vtype); 747 1.1 pooka puffs_newinfo_setsize(pni, vsize); 748 1.17 pooka /* LINTED: yea, it'll lose accuracy, but that's life */ 749 1.1 pooka puffs_newinfo_setrdev(pni, rdev); 750 1.1 pooka 751 1.1 pooka return 0; 752 1.1 pooka } 753 1.1 pooka 754 1.14 pooka #define VERS_TIMECHANGE 599000700 755 1.14 pooka static int 756 1.14 pooka needcompat(void) 757 1.14 pooka { 758 1.14 pooka 759 1.15 pooka /*LINTED*/ 760 1.14 pooka return __NetBSD_Version__ < VERS_TIMECHANGE 761 1.64 pooka && rump_getversion() >= VERS_TIMECHANGE; 762 1.14 pooka } 763 1.14 pooka 764 1.14 pooka #define DOCOMPAT(va, va_compat) \ 765 1.14 pooka do { \ 766 1.14 pooka if (needcompat()) { \ 767 1.23 pooka va_compat = rump_pub_vattr_init(); \ 768 1.23 pooka rump_pub_vattr50_to_vattr(va, va_compat); \ 769 1.14 pooka } else { \ 770 1.14 pooka va_compat = __UNCONST(va); \ 771 1.14 pooka } \ 772 1.74 rillig } while (0) 773 1.14 pooka 774 1.14 pooka #define UNDOCOMPAT(va_compat) \ 775 1.14 pooka do { \ 776 1.14 pooka if (needcompat()) \ 777 1.23 pooka rump_pub_vattr_free(va_compat); \ 778 1.74 rillig } while (0) 779 1.14 pooka 780 1.17 pooka static int 781 1.17 pooka do_makenode(struct puffs_usermount *pu, struct p2k_node *p2n_dir, 782 1.1 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn, 783 1.17 pooka const struct vattr *vap, char *link_target, 784 1.17 pooka int (*makefn)(struct vnode *, struct vnode **, struct componentname *, 785 1.17 pooka struct vattr *), 786 1.17 pooka int (*symfn)(struct vnode *, struct vnode **, struct componentname *, 787 1.17 pooka struct vattr *, char *)) 788 1.17 pooka { 789 1.35 pooka struct p2k_mount *p2m = puffs_getspecific(pu); 790 1.17 pooka struct vnode *dvp = p2n_dir->p2n_vp; 791 1.17 pooka struct p2k_node *p2n; 792 1.1 pooka struct componentname *cn; 793 1.14 pooka struct vattr *va_x; 794 1.72 riastrad struct vnode *vp = NULL; 795 1.1 pooka int rv; 796 1.1 pooka 797 1.17 pooka p2n = malloc(sizeof(*p2n)); 798 1.17 pooka if (p2n == NULL) 799 1.17 pooka return ENOMEM; 800 1.14 pooka DOCOMPAT(vap, va_x); 801 1.14 pooka 802 1.47 pooka cn = makecn(pcn); 803 1.17 pooka RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); 804 1.23 pooka rump_pub_vp_incref(dvp); 805 1.17 pooka if (makefn) { 806 1.17 pooka rv = makefn(dvp, &vp, cn, va_x); 807 1.17 pooka } else { 808 1.17 pooka rv = symfn(dvp, &vp, cn, va_x, link_target); 809 1.17 pooka } 810 1.65 riastrad rump_pub_vp_rele(dvp); 811 1.61 hannken RUMP_VOP_UNLOCK(dvp); 812 1.47 pooka freecn(cn); 813 1.17 pooka 814 1.1 pooka if (rv == 0) { 815 1.17 pooka p2n = getp2n(p2m, vp, true, p2n); 816 1.17 pooka puffs_newinfo_setcookie(pni, p2n); 817 1.17 pooka } else { 818 1.17 pooka free(p2n); 819 1.1 pooka } 820 1.1 pooka 821 1.14 pooka UNDOCOMPAT(va_x); 822 1.14 pooka 823 1.1 pooka return rv; 824 1.17 pooka 825 1.1 pooka } 826 1.1 pooka 827 1.1 pooka /*ARGSUSED*/ 828 1.1 pooka int 829 1.17 pooka p2k_node_create(struct puffs_usermount *pu, puffs_cookie_t opc, 830 1.3 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn, 831 1.3 pooka const struct vattr *vap) 832 1.1 pooka { 833 1.1 pooka 834 1.17 pooka return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_CREATE, NULL); 835 1.17 pooka } 836 1.14 pooka 837 1.17 pooka /*ARGSUSED*/ 838 1.17 pooka int 839 1.17 pooka p2k_node_mknod(struct puffs_usermount *pu, puffs_cookie_t opc, 840 1.17 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn, 841 1.17 pooka const struct vattr *vap) 842 1.17 pooka { 843 1.14 pooka 844 1.17 pooka return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_MKNOD, NULL); 845 1.1 pooka } 846 1.1 pooka 847 1.1 pooka /*ARGSUSED*/ 848 1.1 pooka int 849 1.3 pooka p2k_node_open(struct puffs_usermount *pu, puffs_cookie_t opc, int mode, 850 1.1 pooka const struct puffs_cred *pcr) 851 1.1 pooka { 852 1.17 pooka struct vnode *vp = OPC2VP(opc); 853 1.34 pooka struct kauth_cred *cred; 854 1.1 pooka int rv; 855 1.1 pooka 856 1.1 pooka cred = cred_create(pcr); 857 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 858 1.17 pooka rv = RUMP_VOP_OPEN(vp, mode, cred); 859 1.41 hannken RUMP_VOP_UNLOCK(vp); 860 1.1 pooka cred_destroy(cred); 861 1.1 pooka 862 1.1 pooka return rv; 863 1.1 pooka } 864 1.1 pooka 865 1.1 pooka /*ARGSUSED*/ 866 1.1 pooka int 867 1.3 pooka p2k_node_close(struct puffs_usermount *pu, puffs_cookie_t opc, int flags, 868 1.1 pooka const struct puffs_cred *pcr) 869 1.1 pooka { 870 1.17 pooka struct vnode *vp = OPC2VP(opc); 871 1.34 pooka struct kauth_cred *cred; 872 1.1 pooka 873 1.1 pooka cred = cred_create(pcr); 874 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 875 1.17 pooka RUMP_VOP_CLOSE(vp, flags, cred); 876 1.41 hannken RUMP_VOP_UNLOCK(vp); 877 1.1 pooka cred_destroy(cred); 878 1.1 pooka 879 1.1 pooka return 0; 880 1.1 pooka } 881 1.1 pooka 882 1.1 pooka /*ARGSUSED*/ 883 1.1 pooka int 884 1.3 pooka p2k_node_access(struct puffs_usermount *pu, puffs_cookie_t opc, int mode, 885 1.1 pooka const struct puffs_cred *pcr) 886 1.1 pooka { 887 1.17 pooka struct vnode *vp = OPC2VP(opc); 888 1.34 pooka struct kauth_cred *cred; 889 1.1 pooka int rv; 890 1.1 pooka 891 1.1 pooka cred = cred_create(pcr); 892 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 893 1.17 pooka rv = RUMP_VOP_ACCESS(vp, mode, cred); 894 1.41 hannken RUMP_VOP_UNLOCK(vp); 895 1.1 pooka cred_destroy(cred); 896 1.1 pooka 897 1.1 pooka return rv; 898 1.1 pooka } 899 1.1 pooka 900 1.1 pooka /*ARGSUSED*/ 901 1.1 pooka int 902 1.3 pooka p2k_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc, 903 1.3 pooka struct vattr *vap, const struct puffs_cred *pcr) 904 1.1 pooka { 905 1.17 pooka struct vnode *vp = OPC2VP(opc); 906 1.34 pooka struct kauth_cred *cred; 907 1.14 pooka struct vattr *va_x; 908 1.1 pooka int rv; 909 1.1 pooka 910 1.20 pooka /* "deadfs" */ 911 1.20 pooka if (!vp) 912 1.20 pooka return 0; 913 1.20 pooka 914 1.14 pooka if (needcompat()) { 915 1.23 pooka va_x = rump_pub_vattr_init(); 916 1.14 pooka } else { 917 1.14 pooka va_x = vap; 918 1.14 pooka } 919 1.14 pooka 920 1.1 pooka cred = cred_create(pcr); 921 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 922 1.17 pooka rv = RUMP_VOP_GETATTR(vp, va_x, cred); 923 1.41 hannken RUMP_VOP_UNLOCK(vp); 924 1.1 pooka cred_destroy(cred); 925 1.1 pooka 926 1.14 pooka if (needcompat()) { 927 1.23 pooka rump_pub_vattr_to_vattr50(va_x, vap); 928 1.23 pooka rump_pub_vattr_free(va_x); 929 1.14 pooka } 930 1.14 pooka 931 1.1 pooka return rv; 932 1.1 pooka } 933 1.1 pooka 934 1.1 pooka /*ARGSUSED*/ 935 1.1 pooka int 936 1.3 pooka p2k_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc, 937 1.3 pooka const struct vattr *vap, const struct puffs_cred *pcr) 938 1.1 pooka { 939 1.17 pooka struct vnode *vp = OPC2VP(opc); 940 1.34 pooka struct kauth_cred *cred; 941 1.14 pooka struct vattr *va_x; 942 1.1 pooka int rv; 943 1.1 pooka 944 1.17 pooka /* "deadfs" */ 945 1.17 pooka if (!vp) 946 1.17 pooka return 0; 947 1.17 pooka 948 1.14 pooka DOCOMPAT(vap, va_x); 949 1.14 pooka 950 1.1 pooka cred = cred_create(pcr); 951 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 952 1.17 pooka rv = RUMP_VOP_SETATTR(vp, va_x, cred); 953 1.41 hannken RUMP_VOP_UNLOCK(vp); 954 1.1 pooka cred_destroy(cred); 955 1.1 pooka 956 1.14 pooka UNDOCOMPAT(va_x); 957 1.14 pooka 958 1.1 pooka return rv; 959 1.1 pooka } 960 1.1 pooka 961 1.1 pooka /*ARGSUSED*/ 962 1.1 pooka int 963 1.3 pooka p2k_node_fsync(struct puffs_usermount *pu, puffs_cookie_t opc, 964 1.1 pooka const struct puffs_cred *pcr, int flags, off_t offlo, off_t offhi) 965 1.1 pooka { 966 1.17 pooka struct vnode *vp = OPC2VP(opc); 967 1.34 pooka struct kauth_cred *cred; 968 1.1 pooka int rv; 969 1.1 pooka 970 1.17 pooka /* "deadfs" */ 971 1.17 pooka if (!vp) 972 1.17 pooka return 0; 973 1.17 pooka 974 1.1 pooka cred = cred_create(pcr); 975 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 976 1.17 pooka rv = RUMP_VOP_FSYNC(vp, cred, flags, offlo, offhi); 977 1.41 hannken RUMP_VOP_UNLOCK(vp); 978 1.1 pooka cred_destroy(cred); 979 1.1 pooka 980 1.1 pooka return rv; 981 1.1 pooka } 982 1.1 pooka 983 1.1 pooka /*ARGSUSED*/ 984 1.1 pooka int 985 1.3 pooka p2k_node_mmap(struct puffs_usermount *pu, puffs_cookie_t opc, vm_prot_t flags, 986 1.1 pooka const struct puffs_cred *pcr) 987 1.1 pooka { 988 1.34 pooka struct kauth_cred *cred; 989 1.1 pooka int rv; 990 1.1 pooka 991 1.1 pooka cred = cred_create(pcr); 992 1.17 pooka rv = RUMP_VOP_MMAP(OPC2VP(opc), flags, cred); 993 1.1 pooka cred_destroy(cred); 994 1.1 pooka 995 1.1 pooka return rv; 996 1.1 pooka } 997 1.1 pooka 998 1.1 pooka /*ARGSUSED*/ 999 1.1 pooka int 1000 1.3 pooka p2k_node_seek(struct puffs_usermount *pu, puffs_cookie_t opc, 1001 1.3 pooka off_t oldoff, off_t newoff, const struct puffs_cred *pcr) 1002 1.1 pooka { 1003 1.17 pooka struct vnode *vp = OPC2VP(opc); 1004 1.34 pooka struct kauth_cred *cred; 1005 1.1 pooka int rv; 1006 1.1 pooka 1007 1.1 pooka cred = cred_create(pcr); 1008 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1009 1.17 pooka rv = RUMP_VOP_SEEK(vp, oldoff, newoff, cred); 1010 1.41 hannken RUMP_VOP_UNLOCK(vp); 1011 1.1 pooka cred_destroy(cred); 1012 1.1 pooka 1013 1.1 pooka return rv; 1014 1.1 pooka } 1015 1.1 pooka 1016 1.17 pooka static int 1017 1.17 pooka do_nukenode(struct p2k_node *p2n_dir, struct p2k_node *p2n, 1018 1.17 pooka const struct puffs_cn *pcn, 1019 1.17 pooka int (*nukefn)(struct vnode *, struct vnode *, struct componentname *)) 1020 1.1 pooka { 1021 1.17 pooka struct vnode *dvp = p2n_dir->p2n_vp, *vp = p2n->p2n_vp; 1022 1.1 pooka struct componentname *cn; 1023 1.1 pooka int rv; 1024 1.1 pooka 1025 1.47 pooka cn = makecn(pcn); 1026 1.17 pooka RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); 1027 1.23 pooka rump_pub_vp_incref(dvp); 1028 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1029 1.23 pooka rump_pub_vp_incref(vp); 1030 1.17 pooka rv = nukefn(dvp, vp, cn); 1031 1.70 riastrad assert(dvp != vp); 1032 1.70 riastrad assert(RUMP_VOP_ISLOCKED(dvp) == LK_EXCLUSIVE); 1033 1.17 pooka assert(RUMP_VOP_ISLOCKED(vp) == 0); 1034 1.70 riastrad rump_pub_vp_rele(dvp); 1035 1.70 riastrad RUMP_VOP_UNLOCK(dvp); 1036 1.47 pooka freecn(cn); 1037 1.1 pooka 1038 1.1 pooka return rv; 1039 1.17 pooka 1040 1.17 pooka } 1041 1.17 pooka 1042 1.17 pooka /*ARGSUSED*/ 1043 1.17 pooka int 1044 1.17 pooka p2k_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc, 1045 1.17 pooka puffs_cookie_t targ, const struct puffs_cn *pcn) 1046 1.17 pooka { 1047 1.17 pooka 1048 1.17 pooka return do_nukenode(opc, targ, pcn, RUMP_VOP_REMOVE); 1049 1.1 pooka } 1050 1.1 pooka 1051 1.1 pooka /*ARGSUSED*/ 1052 1.1 pooka int 1053 1.3 pooka p2k_node_link(struct puffs_usermount *pu, puffs_cookie_t opc, 1054 1.3 pooka puffs_cookie_t targ, const struct puffs_cn *pcn) 1055 1.1 pooka { 1056 1.17 pooka struct vnode *dvp = OPC2VP(opc); 1057 1.1 pooka struct componentname *cn; 1058 1.1 pooka int rv; 1059 1.1 pooka 1060 1.47 pooka cn = makecn(pcn); 1061 1.17 pooka RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE); 1062 1.23 pooka rump_pub_vp_incref(dvp); 1063 1.17 pooka rv = RUMP_VOP_LINK(dvp, OPC2VP(targ), cn); 1064 1.66 riastrad rump_pub_vp_rele(dvp); 1065 1.66 riastrad RUMP_VOP_UNLOCK(dvp); 1066 1.47 pooka freecn(cn); 1067 1.1 pooka 1068 1.1 pooka return rv; 1069 1.1 pooka } 1070 1.1 pooka 1071 1.1 pooka /*ARGSUSED*/ 1072 1.1 pooka int 1073 1.3 pooka p2k_node_rename(struct puffs_usermount *pu, 1074 1.3 pooka puffs_cookie_t src_dir, puffs_cookie_t src, 1075 1.3 pooka const struct puffs_cn *pcn_src, 1076 1.3 pooka puffs_cookie_t targ_dir, puffs_cookie_t targ, 1077 1.1 pooka const struct puffs_cn *pcn_targ) 1078 1.1 pooka { 1079 1.17 pooka struct vnode *dvp, *vp, *tdvp, *tvp = NULL; 1080 1.1 pooka struct componentname *cn_src, *cn_targ; 1081 1.1 pooka int rv; 1082 1.1 pooka 1083 1.51 pooka cn_src = makecn(pcn_src); 1084 1.51 pooka cn_targ = makecn(pcn_targ); 1085 1.17 pooka 1086 1.17 pooka dvp = OPC2VP(src_dir); 1087 1.17 pooka vp = OPC2VP(src); 1088 1.17 pooka tdvp = OPC2VP(targ_dir); 1089 1.1 pooka if (targ) { 1090 1.17 pooka tvp = OPC2VP(targ); 1091 1.1 pooka } 1092 1.17 pooka 1093 1.23 pooka rump_pub_vp_incref(dvp); 1094 1.23 pooka rump_pub_vp_incref(vp); 1095 1.17 pooka RUMP_VOP_LOCK(tdvp, LK_EXCLUSIVE); 1096 1.23 pooka rump_pub_vp_incref(tdvp); 1097 1.17 pooka if (tvp) { 1098 1.17 pooka RUMP_VOP_LOCK(tvp, LK_EXCLUSIVE); 1099 1.23 pooka rump_pub_vp_incref(tvp); 1100 1.17 pooka } 1101 1.17 pooka rv = RUMP_VOP_RENAME(dvp, vp, cn_src, tdvp, tvp, cn_targ); 1102 1.17 pooka assert(RUMP_VOP_ISLOCKED(tdvp) == 0); 1103 1.17 pooka if (tvp) { 1104 1.17 pooka assert(RUMP_VOP_ISLOCKED(tvp) == 0); 1105 1.17 pooka } 1106 1.47 pooka freecn(cn_src); 1107 1.47 pooka freecn(cn_targ); 1108 1.1 pooka 1109 1.1 pooka return rv; 1110 1.1 pooka } 1111 1.1 pooka 1112 1.1 pooka /*ARGSUSED*/ 1113 1.1 pooka int 1114 1.3 pooka p2k_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc, 1115 1.3 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn, 1116 1.3 pooka const struct vattr *vap) 1117 1.1 pooka { 1118 1.1 pooka 1119 1.17 pooka return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_MKDIR, NULL); 1120 1.1 pooka } 1121 1.1 pooka 1122 1.1 pooka /*ARGSUSED*/ 1123 1.1 pooka int 1124 1.3 pooka p2k_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc, 1125 1.3 pooka puffs_cookie_t targ, const struct puffs_cn *pcn) 1126 1.1 pooka { 1127 1.1 pooka 1128 1.17 pooka return do_nukenode(opc, targ, pcn, RUMP_VOP_RMDIR); 1129 1.1 pooka } 1130 1.1 pooka 1131 1.1 pooka /*ARGSUSED*/ 1132 1.1 pooka int 1133 1.3 pooka p2k_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc, 1134 1.17 pooka struct puffs_newinfo *pni, const struct puffs_cn *pcn, 1135 1.1 pooka const struct vattr *vap, const char *link_target) 1136 1.1 pooka { 1137 1.1 pooka 1138 1.17 pooka return do_makenode(pu, opc, pni, pcn, vap, 1139 1.17 pooka __UNCONST(link_target), NULL, RUMP_VOP_SYMLINK); 1140 1.1 pooka } 1141 1.1 pooka 1142 1.1 pooka /*ARGSUSED*/ 1143 1.1 pooka int 1144 1.3 pooka p2k_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc, 1145 1.3 pooka struct dirent *dent, off_t *readoff, size_t *reslen, 1146 1.3 pooka const struct puffs_cred *pcr, int *eofflag, 1147 1.3 pooka off_t *cookies, size_t *ncookies) 1148 1.1 pooka { 1149 1.17 pooka struct vnode *vp = OPC2VP(opc); 1150 1.34 pooka struct kauth_cred *cred; 1151 1.1 pooka struct uio *uio; 1152 1.1 pooka off_t *vop_cookies; 1153 1.1 pooka int vop_ncookies; 1154 1.1 pooka int rv; 1155 1.1 pooka 1156 1.1 pooka cred = cred_create(pcr); 1157 1.23 pooka uio = rump_pub_uio_setup(dent, *reslen, *readoff, RUMPUIO_READ); 1158 1.17 pooka RUMP_VOP_LOCK(vp, LK_SHARED); 1159 1.1 pooka if (cookies) { 1160 1.17 pooka rv = RUMP_VOP_READDIR(vp, uio, cred, eofflag, 1161 1.1 pooka &vop_cookies, &vop_ncookies); 1162 1.1 pooka memcpy(cookies, vop_cookies, vop_ncookies * sizeof(*cookies)); 1163 1.1 pooka *ncookies = vop_ncookies; 1164 1.1 pooka free(vop_cookies); 1165 1.1 pooka } else { 1166 1.17 pooka rv = RUMP_VOP_READDIR(vp, uio, cred, eofflag, NULL, NULL); 1167 1.1 pooka } 1168 1.41 hannken RUMP_VOP_UNLOCK(vp); 1169 1.1 pooka if (rv == 0) { 1170 1.23 pooka *reslen = rump_pub_uio_getresid(uio); 1171 1.23 pooka *readoff = rump_pub_uio_getoff(uio); 1172 1.1 pooka } 1173 1.23 pooka rump_pub_uio_free(uio); 1174 1.1 pooka cred_destroy(cred); 1175 1.1 pooka 1176 1.1 pooka return rv; 1177 1.1 pooka } 1178 1.1 pooka 1179 1.1 pooka /*ARGSUSED*/ 1180 1.1 pooka int 1181 1.3 pooka p2k_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc, 1182 1.1 pooka const struct puffs_cred *pcr, char *linkname, size_t *linklen) 1183 1.1 pooka { 1184 1.17 pooka struct vnode *vp = OPC2VP(opc); 1185 1.34 pooka struct kauth_cred *cred; 1186 1.1 pooka struct uio *uio; 1187 1.1 pooka int rv; 1188 1.1 pooka 1189 1.1 pooka cred = cred_create(pcr); 1190 1.23 pooka uio = rump_pub_uio_setup(linkname, *linklen, 0, RUMPUIO_READ); 1191 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1192 1.17 pooka rv = RUMP_VOP_READLINK(vp, uio, cred); 1193 1.41 hannken RUMP_VOP_UNLOCK(vp); 1194 1.23 pooka *linklen -= rump_pub_uio_free(uio); 1195 1.1 pooka cred_destroy(cred); 1196 1.1 pooka 1197 1.1 pooka return rv; 1198 1.1 pooka } 1199 1.1 pooka 1200 1.1 pooka /*ARGSUSED*/ 1201 1.1 pooka int 1202 1.3 pooka p2k_node_read(struct puffs_usermount *pu, puffs_cookie_t opc, 1203 1.1 pooka uint8_t *buf, off_t offset, size_t *resid, 1204 1.1 pooka const struct puffs_cred *pcr, int ioflag) 1205 1.1 pooka { 1206 1.17 pooka struct vnode *vp = OPC2VP(opc); 1207 1.34 pooka struct kauth_cred *cred; 1208 1.1 pooka struct uio *uio; 1209 1.1 pooka int rv; 1210 1.1 pooka 1211 1.1 pooka cred = cred_create(pcr); 1212 1.23 pooka uio = rump_pub_uio_setup(buf, *resid, offset, RUMPUIO_READ); 1213 1.17 pooka RUMP_VOP_LOCK(vp, LK_SHARED); 1214 1.17 pooka rv = RUMP_VOP_READ(vp, uio, ioflag, cred); 1215 1.41 hannken RUMP_VOP_UNLOCK(vp); 1216 1.23 pooka *resid = rump_pub_uio_free(uio); 1217 1.1 pooka cred_destroy(cred); 1218 1.1 pooka 1219 1.1 pooka return rv; 1220 1.1 pooka } 1221 1.1 pooka 1222 1.1 pooka /*ARGSUSED*/ 1223 1.1 pooka int 1224 1.3 pooka p2k_node_write(struct puffs_usermount *pu, puffs_cookie_t opc, 1225 1.1 pooka uint8_t *buf, off_t offset, size_t *resid, 1226 1.1 pooka const struct puffs_cred *pcr, int ioflag) 1227 1.1 pooka { 1228 1.17 pooka struct vnode *vp = OPC2VP(opc); 1229 1.34 pooka struct kauth_cred *cred; 1230 1.1 pooka struct uio *uio; 1231 1.1 pooka int rv; 1232 1.1 pooka 1233 1.17 pooka /* "deadfs" */ 1234 1.17 pooka if (!vp) 1235 1.17 pooka return 0; 1236 1.17 pooka 1237 1.1 pooka cred = cred_create(pcr); 1238 1.23 pooka uio = rump_pub_uio_setup(buf, *resid, offset, RUMPUIO_WRITE); 1239 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1240 1.17 pooka rv = RUMP_VOP_WRITE(vp, uio, ioflag, cred); 1241 1.41 hannken RUMP_VOP_UNLOCK(vp); 1242 1.23 pooka *resid = rump_pub_uio_free(uio); 1243 1.1 pooka cred_destroy(cred); 1244 1.1 pooka 1245 1.1 pooka return rv; 1246 1.1 pooka } 1247 1.1 pooka 1248 1.38 pooka /*ARGSUSED*/ 1249 1.38 pooka int 1250 1.39 pooka p2k_node_pathconf(struct puffs_usermount *pu, puffs_cookie_t opc, 1251 1.40 pooka int name, register_t *retval) 1252 1.39 pooka { 1253 1.39 pooka struct vnode *vp = OPC2VP(opc); 1254 1.39 pooka int rv; 1255 1.39 pooka 1256 1.39 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1257 1.40 pooka rv = RUMP_VOP_PATHCONF(vp, name, retval); 1258 1.41 hannken RUMP_VOP_UNLOCK(vp); 1259 1.39 pooka 1260 1.39 pooka return rv; 1261 1.39 pooka } 1262 1.39 pooka 1263 1.39 pooka /*ARGSUSED*/ 1264 1.39 pooka int 1265 1.38 pooka p2k_node_getextattr(struct puffs_usermount *pu, puffs_cookie_t opc, 1266 1.38 pooka int attrnamespace, const char *attrname, size_t *attrsize, 1267 1.38 pooka uint8_t *attr, size_t *resid, const struct puffs_cred *pcr) 1268 1.38 pooka { 1269 1.38 pooka struct vnode *vp = OPC2VP(opc); 1270 1.38 pooka struct kauth_cred *cred; 1271 1.38 pooka struct uio *uio; 1272 1.38 pooka int rv; 1273 1.38 pooka 1274 1.38 pooka if (attr) 1275 1.38 pooka uio = rump_pub_uio_setup(attr, *resid, 0, RUMPUIO_READ); 1276 1.38 pooka else 1277 1.38 pooka uio = NULL; 1278 1.38 pooka 1279 1.38 pooka cred = cred_create(pcr); 1280 1.38 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1281 1.38 pooka rv = RUMP_VOP_GETEXTATTR(vp, attrnamespace, attrname, uio, 1282 1.38 pooka attrsize, cred); 1283 1.41 hannken RUMP_VOP_UNLOCK(vp); 1284 1.38 pooka cred_destroy(cred); 1285 1.38 pooka 1286 1.38 pooka if (uio) 1287 1.38 pooka *resid = rump_pub_uio_free(uio); 1288 1.38 pooka 1289 1.38 pooka return rv; 1290 1.38 pooka } 1291 1.38 pooka 1292 1.38 pooka /*ARGSUSED*/ 1293 1.38 pooka int 1294 1.38 pooka p2k_node_setextattr(struct puffs_usermount *pu, puffs_cookie_t opc, 1295 1.38 pooka int attrnamespace, const char *attrname, 1296 1.38 pooka uint8_t *attr, size_t *resid, const struct puffs_cred *pcr) 1297 1.38 pooka { 1298 1.38 pooka struct vnode *vp = OPC2VP(opc); 1299 1.38 pooka struct kauth_cred *cred; 1300 1.38 pooka struct uio *uio; 1301 1.38 pooka int rv; 1302 1.38 pooka 1303 1.38 pooka if (attr) 1304 1.38 pooka uio = rump_pub_uio_setup(attr, *resid, 0, RUMPUIO_READ); 1305 1.38 pooka else 1306 1.38 pooka uio = NULL; 1307 1.38 pooka 1308 1.38 pooka cred = cred_create(pcr); 1309 1.38 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1310 1.38 pooka rv = RUMP_VOP_SETEXTATTR(vp, attrnamespace, attrname, uio, cred); 1311 1.41 hannken RUMP_VOP_UNLOCK(vp); 1312 1.38 pooka cred_destroy(cred); 1313 1.38 pooka 1314 1.38 pooka if (uio) 1315 1.38 pooka *resid = rump_pub_uio_free(uio); 1316 1.38 pooka 1317 1.38 pooka return rv; 1318 1.38 pooka } 1319 1.38 pooka 1320 1.38 pooka /*ARGSUSED*/ 1321 1.38 pooka int 1322 1.38 pooka p2k_node_listextattr(struct puffs_usermount *pu, puffs_cookie_t opc, 1323 1.55 manu int attrnamespace, size_t *attrsize, uint8_t *attrs, 1324 1.55 manu size_t *resid, int flags, const struct puffs_cred *pcr) 1325 1.38 pooka { 1326 1.38 pooka struct vnode *vp = OPC2VP(opc); 1327 1.38 pooka struct kauth_cred *cred; 1328 1.38 pooka struct uio *uio; 1329 1.38 pooka int rv; 1330 1.38 pooka 1331 1.38 pooka if (attrs) 1332 1.38 pooka uio = rump_pub_uio_setup(attrs, *resid, 0, RUMPUIO_READ); 1333 1.38 pooka else 1334 1.38 pooka uio = NULL; 1335 1.38 pooka 1336 1.38 pooka cred = cred_create(pcr); 1337 1.38 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1338 1.55 manu rv = RUMP_VOP_LISTEXTATTR(vp, attrnamespace, uio, attrsize, 1339 1.55 manu flags, cred); 1340 1.41 hannken RUMP_VOP_UNLOCK(vp); 1341 1.38 pooka cred_destroy(cred); 1342 1.38 pooka 1343 1.38 pooka if (uio) 1344 1.38 pooka *resid = rump_pub_uio_free(uio); 1345 1.38 pooka 1346 1.38 pooka return rv; 1347 1.38 pooka } 1348 1.38 pooka 1349 1.38 pooka /*ARGSUSED*/ 1350 1.38 pooka int 1351 1.38 pooka p2k_node_deleteextattr(struct puffs_usermount *pu, puffs_cookie_t opc, 1352 1.38 pooka int attrnamespace, const char *attrname, const struct puffs_cred *pcr) 1353 1.38 pooka { 1354 1.38 pooka struct vnode *vp = OPC2VP(opc); 1355 1.38 pooka struct kauth_cred *cred; 1356 1.38 pooka int rv; 1357 1.38 pooka 1358 1.38 pooka cred = cred_create(pcr); 1359 1.38 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1360 1.38 pooka rv = RUMP_VOP_DELETEEXTATTR(vp, attrnamespace, attrname, cred); 1361 1.41 hannken RUMP_VOP_UNLOCK(vp); 1362 1.38 pooka cred_destroy(cred); 1363 1.38 pooka 1364 1.38 pooka return rv; 1365 1.38 pooka } 1366 1.38 pooka 1367 1.17 pooka /* the kernel releases its last reference here */ 1368 1.1 pooka int 1369 1.3 pooka p2k_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc) 1370 1.1 pooka { 1371 1.35 pooka struct p2k_mount *p2m = puffs_getspecific(pu); 1372 1.17 pooka struct p2k_node *p2n = opc; 1373 1.17 pooka struct vnode *vp = OPC2VP(opc); 1374 1.27 pooka bool recycle = false; 1375 1.1 pooka int rv; 1376 1.1 pooka 1377 1.17 pooka /* deadfs */ 1378 1.17 pooka if (!vp) 1379 1.17 pooka return 0; 1380 1.17 pooka 1381 1.17 pooka /* 1382 1.17 pooka * Flush all cached vnode pages from the rump kernel -- they 1383 1.31 pooka * are kept in puffs for all things that matter. However, 1384 1.31 pooka * don't do this for tmpfs (vnodes are backed by an aobj), since that 1385 1.31 pooka * would cause us to clear the backing storage leaving us without 1386 1.31 pooka * a way to regain the data from "stable storage". 1387 1.17 pooka */ 1388 1.31 pooka if (!p2m->p2m_imtmpfsman) { 1389 1.73 ad rump_pub_vp_vmobjlock(vp, 1); 1390 1.31 pooka RUMP_VOP_PUTPAGES(vp, 0, 0, 1391 1.31 pooka PGO_ALLPAGES|PGO_CLEANIT|PGO_FREE); 1392 1.31 pooka } 1393 1.17 pooka 1394 1.17 pooka /* 1395 1.17 pooka * Ok, this is where we get nasty. We pretend the vnode is 1396 1.17 pooka * inactive and already tell the file system that. However, 1397 1.17 pooka * we are allowed to pretend it also grows a reference immediately 1398 1.17 pooka * after per vget(), so this does not do harm. Cheap trick, but ... 1399 1.17 pooka * 1400 1.17 pooka * If the file system thinks the inode is done for, we release 1401 1.17 pooka * our reference and clear all knowledge of the vnode. If, 1402 1.17 pooka * however, the inode is still active, we retain our reference 1403 1.17 pooka * until reclaim, since puffs might be flushing out some data 1404 1.17 pooka * later. 1405 1.17 pooka */ 1406 1.17 pooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE); 1407 1.1 pooka rv = RUMP_VOP_INACTIVE(vp, &recycle); 1408 1.69 riastrad RUMP_VOP_UNLOCK(vp); 1409 1.17 pooka if (recycle) { 1410 1.1 pooka puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1); 1411 1.23 pooka rump_pub_vp_rele(p2n->p2n_vp); 1412 1.17 pooka p2n->p2n_vp = NULL; 1413 1.17 pooka } 1414 1.1 pooka 1415 1.1 pooka return rv; 1416 1.1 pooka } 1417 1.1 pooka 1418 1.1 pooka /*ARGSUSED*/ 1419 1.1 pooka int 1420 1.3 pooka p2k_node_reclaim(struct puffs_usermount *pu, puffs_croissant_t opc) 1421 1.1 pooka { 1422 1.17 pooka struct p2k_node *p2n = opc; 1423 1.17 pooka 1424 1.17 pooka if (p2n->p2n_vp) { 1425 1.23 pooka rump_pub_vp_rele(p2n->p2n_vp); 1426 1.17 pooka p2n->p2n_vp = NULL; 1427 1.17 pooka } 1428 1.1 pooka 1429 1.17 pooka freep2n(p2n); 1430 1.1 pooka return 0; 1431 1.1 pooka } 1432