1*cdc507f0Sandvar /* $NetBSD: p2k.c,v 1.75 2022/05/24 20:50:17 andvar Exp $ */
2bdf6e0b0Spooka
3bdf6e0b0Spooka /*
40605ce2bSpooka * Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved.
5bdf6e0b0Spooka *
60605ce2bSpooka * Development of this software was supported by the
70605ce2bSpooka * Finnish Cultural Foundation.
8bdf6e0b0Spooka *
9bdf6e0b0Spooka * Redistribution and use in source and binary forms, with or without
10bdf6e0b0Spooka * modification, are permitted provided that the following conditions
11bdf6e0b0Spooka * are met:
12bdf6e0b0Spooka * 1. Redistributions of source code must retain the above copyright
13bdf6e0b0Spooka * notice, this list of conditions and the following disclaimer.
14bdf6e0b0Spooka * 2. Redistributions in binary form must reproduce the above copyright
15bdf6e0b0Spooka * notice, this list of conditions and the following disclaimer in the
16bdf6e0b0Spooka * documentation and/or other materials provided with the distribution.
17bdf6e0b0Spooka *
18bdf6e0b0Spooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19bdf6e0b0Spooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20bdf6e0b0Spooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21bdf6e0b0Spooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22bdf6e0b0Spooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23bdf6e0b0Spooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24bdf6e0b0Spooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25bdf6e0b0Spooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26bdf6e0b0Spooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27bdf6e0b0Spooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28bdf6e0b0Spooka * SUCH DAMAGE.
29bdf6e0b0Spooka */
30bdf6e0b0Spooka
31bdf6e0b0Spooka /*
32bdf6e0b0Spooka * puffs 2k, i.e. puffs 2 kernel. Converts the puffs protocol to
33bdf6e0b0Spooka * the kernel vfs protocol and vice versa.
34bdf6e0b0Spooka *
35bdf6e0b0Spooka * A word about reference counting: puffs in the kernel is the king of
36bdf6e0b0Spooka * reference counting. We must maintain a vnode alive and kicking
37bdf6e0b0Spooka * until the kernel tells us to reclaim it. Therefore we make sure
38bdf6e0b0Spooka * we never accidentally lose a vnode. Before calling operations which
39bdf6e0b0Spooka * decrease the refcount we always bump the refcount up to compensate.
40bdf6e0b0Spooka * Come inactive, if the file system thinks that the vnode should be
41bdf6e0b0Spooka * put out of its misery, it will set the recycle flag. We use this
42bdf6e0b0Spooka * to tell the kernel to reclaim the vnode. Only in reclaim do we
43bdf6e0b0Spooka * really nuke the last reference.
44bdf6e0b0Spooka */
45bdf6e0b0Spooka
4649d75a28Spooka #include <sys/cdefs.h>
47bdf6e0b0Spooka #include <sys/mount.h>
48bdf6e0b0Spooka #include <sys/param.h>
49bdf6e0b0Spooka #include <sys/lock.h>
50bdf6e0b0Spooka #include <sys/namei.h>
51bdf6e0b0Spooka #include <sys/dirent.h>
525290e6c8Spooka #include <sys/hash.h>
53bdf6e0b0Spooka
54bdf6e0b0Spooka #include <assert.h>
55bdf6e0b0Spooka #include <errno.h>
56bdf6e0b0Spooka #include <puffs.h>
57bdf6e0b0Spooka #include <stdlib.h>
58c67ff293Spooka #include <stdio.h>
59bdf6e0b0Spooka
60bdf6e0b0Spooka #include <rump/rump.h>
61d35b86acSpooka #include <rump/rumpvnode_if.h>
62bdf6e0b0Spooka #include <rump/p2k.h>
63bdf6e0b0Spooka #include <rump/ukfs.h>
64bdf6e0b0Spooka
65421f4561Schristos #include <uvm/uvm_pager.h>
66421f4561Schristos
6730df4c9fSpooka /* NetBSD-5 compat */
6830df4c9fSpooka #ifndef MOUNT_RUMPFS
6930df4c9fSpooka #define MOUNT_RUMPFS "rumpfs"
7030df4c9fSpooka #endif
7130df4c9fSpooka
72bdf6e0b0Spooka PUFFSOP_PROTOS(p2k)
73bdf6e0b0Spooka
745290e6c8Spooka LIST_HEAD(p2k_vp_hash, p2k_node);
755290e6c8Spooka #define NHASHBUCK (1<<16)
765290e6c8Spooka struct p2k_mount {
775290e6c8Spooka struct vnode *p2m_rvp;
78476b5ba6Spooka struct puffs_usermount *p2m_pu;
79476b5ba6Spooka struct ukfs *p2m_ukfs;
805290e6c8Spooka struct p2k_vp_hash p2m_vphash[NHASHBUCK];
8130df4c9fSpooka struct mount *p2m_mp;
825290e6c8Spooka int p2m_nvnodes;
8313777d56Spooka int p2m_imtmpfsman;
84d16346a2Spooka bool p2m_hasdebug;
855290e6c8Spooka };
865290e6c8Spooka
875290e6c8Spooka struct p2k_node {
88519089c8Smanu struct puffs_node p2n_pn;
895290e6c8Spooka struct vnode *p2n_vp;
905290e6c8Spooka
915290e6c8Spooka LIST_ENTRY(p2k_node) p2n_entries;
925290e6c8Spooka };
935290e6c8Spooka
945290e6c8Spooka #define OPC2VP(opc) (((struct p2k_node *)opc)->p2n_vp)
955290e6c8Spooka
9696ae77caSpooka static int haswizard;
9796ae77caSpooka static uid_t wizarduid;
9896ae77caSpooka
992734e549Spooka static struct kauth_cred *
cred_create(const struct puffs_cred * pcr)100bdf6e0b0Spooka cred_create(const struct puffs_cred *pcr)
101bdf6e0b0Spooka {
102bdf6e0b0Spooka gid_t groups[NGROUPS];
103bdf6e0b0Spooka uid_t uid;
104bdf6e0b0Spooka gid_t gid;
105251fbb35Spooka short ngroups = __arraycount(groups);
106bdf6e0b0Spooka
10796ae77caSpooka if (haswizard) {
10896ae77caSpooka uid = wizarduid;
10996ae77caSpooka } else {
110bdf6e0b0Spooka if (puffs_cred_getuid(pcr, &uid) == -1)
111bdf6e0b0Spooka uid = 0;
11296ae77caSpooka }
113bdf6e0b0Spooka if (puffs_cred_getgid(pcr, &gid) == -1)
114bdf6e0b0Spooka gid = 0;
115bdf6e0b0Spooka puffs_cred_getgroups(pcr, groups, &ngroups);
116bdf6e0b0Spooka
117bdf6e0b0Spooka /* LINTED: ngroups is ok */
118bf3992afSpooka return rump_pub_cred_create(uid, gid, ngroups, groups);
119bdf6e0b0Spooka }
120bdf6e0b0Spooka
121bdf6e0b0Spooka static __inline void
cred_destroy(struct kauth_cred * cred)1222734e549Spooka cred_destroy(struct kauth_cred *cred)
123bdf6e0b0Spooka {
124bdf6e0b0Spooka
125bf3992afSpooka rump_pub_cred_put(cred);
126bdf6e0b0Spooka }
127bdf6e0b0Spooka
128bdf6e0b0Spooka static struct componentname *
makecn(const struct puffs_cn * pcn)1299670fcafSpooka makecn(const struct puffs_cn *pcn)
130bdf6e0b0Spooka {
1312734e549Spooka struct kauth_cred *cred;
132bdf6e0b0Spooka
133bdf6e0b0Spooka cred = cred_create(pcn->pcn_cred);
134bdf6e0b0Spooka /* LINTED: prehistoric types in first two args */
1359670fcafSpooka return rump_pub_makecn(pcn->pcn_nameiop, pcn->pcn_flags,
136cd52561aSpooka pcn->pcn_name, pcn->pcn_namelen, cred, rump_pub_lwproc_curlwp());
137bdf6e0b0Spooka }
138bdf6e0b0Spooka
139bdf6e0b0Spooka static __inline void
freecn(struct componentname * cnp)1409670fcafSpooka freecn(struct componentname *cnp)
141bdf6e0b0Spooka {
142bdf6e0b0Spooka
1439670fcafSpooka rump_pub_freecn(cnp, RUMPCN_FREECRED);
144bdf6e0b0Spooka }
145bdf6e0b0Spooka
146bdf6e0b0Spooka static void
makelwp(struct puffs_usermount * pu)147bdf6e0b0Spooka makelwp(struct puffs_usermount *pu)
148bdf6e0b0Spooka {
149bdf6e0b0Spooka pid_t pid;
150bdf6e0b0Spooka lwpid_t lid;
151bdf6e0b0Spooka
152bdf6e0b0Spooka puffs_cc_getcaller(puffs_cc_getcc(pu), &pid, &lid);
153cd52561aSpooka rump_pub_allbetsareoff_setid(pid, lid);
154bdf6e0b0Spooka }
155bdf6e0b0Spooka
15627daa694Spooka static volatile sig_atomic_t dodump;
15727daa694Spooka static void
dumpmp(struct puffs_usermount * pu)15827daa694Spooka dumpmp(struct puffs_usermount *pu)
15927daa694Spooka {
16038a0431bSchristos struct puffs_statvfs svfsb;
16127daa694Spooka
16227daa694Spooka if (dodump && p2k_fs_statvfs(pu, &svfsb) == 0) {
16327daa694Spooka rump_pub_vfs_mount_print(svfsb.f_mntonname, dodump-1);
16427daa694Spooka }
16527daa694Spooka
16627daa694Spooka dodump = 0;
16727daa694Spooka }
16827daa694Spooka
16927daa694Spooka static void
sighand(int sig)17027daa694Spooka sighand(int sig)
17127daa694Spooka {
17227daa694Spooka
17327daa694Spooka if (sig == SIGINFO)
17427daa694Spooka dodump = 1;
17527daa694Spooka else if (sig == SIGUSR1)
17627daa694Spooka dodump = 2;
17727daa694Spooka }
17827daa694Spooka
1795290e6c8Spooka static __inline struct p2k_vp_hash *
gethash(struct p2k_mount * p2m,struct vnode * vp)1805290e6c8Spooka gethash(struct p2k_mount *p2m, struct vnode *vp)
1815290e6c8Spooka {
1825290e6c8Spooka uint32_t hash;
1835290e6c8Spooka
1845290e6c8Spooka hash = hash32_buf(&vp, sizeof(vp), HASH32_BUF_INIT);
1855290e6c8Spooka return &p2m->p2m_vphash[hash % NHASHBUCK];
1865290e6c8Spooka }
1875290e6c8Spooka
1885290e6c8Spooka /*
1895290e6c8Spooka * Find node based on hash of vnode pointer. If vnode is found,
1905290e6c8Spooka * releases one reference to vnode based on the fact that we just
1915290e6c8Spooka * performed a lookup for it.
1925290e6c8Spooka *
1935290e6c8Spooka * If the optinal p2n_storage parameter is passed, it is used instead
1945290e6c8Spooka * of allocating more memory. This allows for easier error recovery.
1955290e6c8Spooka */
1965290e6c8Spooka static struct p2k_node *
getp2n(struct p2k_mount * p2m,struct vnode * vp,bool initial,struct p2k_node * p2n_storage)1975290e6c8Spooka getp2n(struct p2k_mount *p2m, struct vnode *vp, bool initial,
1985290e6c8Spooka struct p2k_node *p2n_storage)
1995290e6c8Spooka {
2005290e6c8Spooka struct p2k_vp_hash *hl;
2015290e6c8Spooka struct p2k_node *p2n = NULL;
2025290e6c8Spooka
2035290e6c8Spooka /* p2n_storage => initial */
2045290e6c8Spooka assert(!p2n_storage || initial);
2055290e6c8Spooka
2065290e6c8Spooka hl = gethash(p2m, vp);
2075290e6c8Spooka if (!initial)
2085290e6c8Spooka LIST_FOREACH(p2n, hl, p2n_entries)
2095290e6c8Spooka if (p2n->p2n_vp == vp)
2105290e6c8Spooka break;
2115290e6c8Spooka
2125290e6c8Spooka hl = gethash(p2m, vp);
2135290e6c8Spooka if (p2n) {
214bf3992afSpooka rump_pub_vp_rele(vp);
2155290e6c8Spooka } else {
2165290e6c8Spooka if (p2n_storage)
2175290e6c8Spooka p2n = p2n_storage;
2185290e6c8Spooka else
2195290e6c8Spooka p2n = malloc(sizeof(*p2n));
2205290e6c8Spooka if (!p2n) {
221bf3992afSpooka rump_pub_vp_rele(vp);
2225290e6c8Spooka return NULL;
2235290e6c8Spooka }
2245290e6c8Spooka memset(p2n, 0, sizeof(*p2n));
2255290e6c8Spooka LIST_INSERT_HEAD(hl, p2n, p2n_entries);
2265290e6c8Spooka p2n->p2n_vp = vp;
2275290e6c8Spooka }
2285290e6c8Spooka return p2n;
2295290e6c8Spooka }
2305290e6c8Spooka
2315290e6c8Spooka static void
freep2n(struct p2k_node * p2n)2325290e6c8Spooka freep2n(struct p2k_node *p2n)
2335290e6c8Spooka {
2345290e6c8Spooka
2355290e6c8Spooka assert(p2n->p2n_vp == NULL);
2365290e6c8Spooka LIST_REMOVE(p2n, p2n_entries);
2375290e6c8Spooka free(p2n);
2385290e6c8Spooka }
2395290e6c8Spooka
240c69ace3cSpooka /*ARGSUSED*/
241c67ff293Spooka static void
p2k_errcatcher(struct puffs_usermount * pu,uint8_t type,int error,const char * str,puffs_cookie_t cook)242c67ff293Spooka p2k_errcatcher(struct puffs_usermount *pu, uint8_t type, int error,
243c67ff293Spooka const char *str, puffs_cookie_t cook)
244c67ff293Spooka {
245c67ff293Spooka
246c67ff293Spooka fprintf(stderr, "type %d, error %d, cookie %p (%s)\n",
247c67ff293Spooka type, error, cook, str);
248c67ff293Spooka
249c67ff293Spooka /*
250c67ff293Spooka * Trap all EINVAL responses to lookup. It most likely means
251c67ff293Spooka * that we supplied VNON/VBAD as the type. The real kernel
252c67ff293Spooka * doesn't panic from this either, but just handles it.
253c67ff293Spooka */
254c67ff293Spooka if (type != PUFFS_VN_LOOKUP && error == EINVAL)
255c67ff293Spooka abort();
256c67ff293Spooka }
257c67ff293Spooka
2585290e6c8Spooka /* just to avoid annoying loop when singlestepping */
25938a8ac9cSpooka static struct p2k_mount *
allocp2m(void)26038a8ac9cSpooka allocp2m(void)
2615290e6c8Spooka {
2625290e6c8Spooka struct p2k_mount *p2m;
2635290e6c8Spooka int i;
2645290e6c8Spooka
2655290e6c8Spooka p2m = malloc(sizeof(*p2m));
26638a8ac9cSpooka if (p2m == NULL)
26738a8ac9cSpooka return NULL;
268476b5ba6Spooka memset(p2m, 0, sizeof(*p2m));
269476b5ba6Spooka
2705290e6c8Spooka for (i = 0; i < NHASHBUCK; i++)
2715290e6c8Spooka LIST_INIT(&p2m->p2m_vphash[i]);
27238a8ac9cSpooka
27338a8ac9cSpooka return p2m;
2745290e6c8Spooka }
2755290e6c8Spooka
27638a8ac9cSpooka struct p2k_mount *
p2k_init(uint32_t puffs_flags)27738a8ac9cSpooka p2k_init(uint32_t puffs_flags)
278bdf6e0b0Spooka {
279bdf6e0b0Spooka struct puffs_ops *pops;
28038a8ac9cSpooka struct p2k_mount *p2m;
28196ae77caSpooka char *envbuf;
28202d2ab30Spooka bool dodaemon;
283d16346a2Spooka bool hasdebug;
284bdf6e0b0Spooka
285bdf6e0b0Spooka PUFFSOP_INIT(pops);
286bdf6e0b0Spooka
287bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, fs, statvfs);
288bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, fs, unmount);
289bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, fs, sync);
290bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, fs, fhtonode);
291bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, fs, nodetofh);
29255a23816Spooka PUFFSOP_SET(pops, p2k, fs, extattrctl);
293bdf6e0b0Spooka
294bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, lookup);
295bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, create);
296bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, mknod);
297bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, open);
298bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, close);
299bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, access);
300bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, getattr);
301bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, setattr);
302bdf6e0b0Spooka #if 0
303bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, poll);
304bdf6e0b0Spooka #endif
305bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, mmap);
306bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, fsync);
307bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, seek);
308bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, remove);
309bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, link);
310bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, rename);
311bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, mkdir);
312bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, rmdir);
313bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, symlink);
314bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, readdir);
315bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, readlink);
316bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, read);
317bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, write);
318bdf6e0b0Spooka
3191cfb9937Spooka PUFFSOP_SET(pops, p2k, node, pathconf);
3201cfb9937Spooka
321bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, inactive);
322bdf6e0b0Spooka PUFFSOP_SET(pops, p2k, node, reclaim);
323bdf6e0b0Spooka
32455a23816Spooka PUFFSOP_SET(pops, p2k, node, getextattr);
32555a23816Spooka PUFFSOP_SET(pops, p2k, node, setextattr);
32655a23816Spooka PUFFSOP_SET(pops, p2k, node, listextattr);
32755a23816Spooka PUFFSOP_SET(pops, p2k, node, deleteextattr);
32855a23816Spooka
32902d2ab30Spooka dodaemon = true;
3309a9b93d4Spooka hasdebug = false;
3319a9b93d4Spooka
33202d2ab30Spooka if (getenv("P2K_DEBUG") != NULL) {
33302d2ab30Spooka puffs_flags |= PUFFS_FLAG_OPDUMP;
33402d2ab30Spooka dodaemon = false;
335d16346a2Spooka hasdebug = true;
33602d2ab30Spooka }
33753b8d598Spooka if (getenv("P2K_NODETACH") != NULL) {
33853b8d598Spooka dodaemon = false;
33953b8d598Spooka }
34055a30cc8Spooka if (getenv("P2K_NOCACHE_PAGE") != NULL) {
34155a30cc8Spooka puffs_flags |= PUFFS_KFLAG_NOCACHE_PAGE;
34255a30cc8Spooka }
34355a30cc8Spooka if (getenv("P2K_NOCACHE_NAME") != NULL) {
34455a30cc8Spooka puffs_flags |= PUFFS_KFLAG_NOCACHE_NAME;
34555a30cc8Spooka }
34655a30cc8Spooka if (getenv("P2K_NOCACHE") != NULL) {
34755a30cc8Spooka puffs_flags |= PUFFS_KFLAG_NOCACHE;
34855a30cc8Spooka }
34996ae77caSpooka if ((envbuf = getenv("P2K_WIZARDUID")) != NULL) {
350357983ccSpooka char *ep;
351357983ccSpooka
352357983ccSpooka wizarduid = strtoul(envbuf, &ep, 10);
353357983ccSpooka if (envbuf[0] == '\0' || *ep != '\0') {
354357983ccSpooka printf("P2K_WIZARDUID: invalid uid %s\n", envbuf);
355357983ccSpooka } else if (wizarduid > UID_MAX) {
356357983ccSpooka printf("P2K_WIZARDUID: uid %s out-of-range\n", envbuf);
357357983ccSpooka } else {
35896ae77caSpooka haswizard = 1;
35996ae77caSpooka printf("P2K WIZARD MODE: using uid %d\n", wizarduid);
36096ae77caSpooka }
361357983ccSpooka }
36202d2ab30Spooka
363d256e384Smanu /*
364*cdc507f0Sandvar * Explicitly tell that our cookies can be treated as
365d256e384Smanu * puffs_node, since we never let libpuffs know by
366d256e384Smanu * calling call puffs_pn_new()
367d256e384Smanu */
368d256e384Smanu puffs_flags |= PUFFS_FLAG_PNCOOKIE;
369d256e384Smanu
37038a8ac9cSpooka p2m = allocp2m();
37138a8ac9cSpooka if (p2m == NULL)
37238a8ac9cSpooka return NULL;
37338a8ac9cSpooka p2m->p2m_pu = puffs_init(pops, PUFFS_DEFER, PUFFS_DEFER,
37438a8ac9cSpooka PUFFS_DEFER, puffs_flags);
37538a8ac9cSpooka if (p2m->p2m_pu == NULL) {
37638a8ac9cSpooka int sverrno = errno;
37738a8ac9cSpooka free(p2m);
37838a8ac9cSpooka errno = sverrno;
37938a8ac9cSpooka return NULL;
38038a8ac9cSpooka }
381d16346a2Spooka p2m->p2m_hasdebug = hasdebug;
38238a8ac9cSpooka
38338a8ac9cSpooka if (dodaemon) {
38438a8ac9cSpooka if (puffs_daemon(p2m->p2m_pu, 1, 1) == -1) {
38538a8ac9cSpooka int sverrno = errno;
38638a8ac9cSpooka p2k_cancel(p2m, sverrno);
38738a8ac9cSpooka errno = sverrno;
38838a8ac9cSpooka p2m = NULL;
38938a8ac9cSpooka }
39038a8ac9cSpooka }
39138a8ac9cSpooka if (p2m)
39238a8ac9cSpooka rump_init();
39338a8ac9cSpooka
3943daddc03Spooka rump_pub_lwproc_rfork(RUMP_RFCFDG);
395cd52561aSpooka
39638a8ac9cSpooka return p2m;
39738a8ac9cSpooka }
39838a8ac9cSpooka
39938a8ac9cSpooka void
p2k_cancel(struct p2k_mount * p2m,int error)40038a8ac9cSpooka p2k_cancel(struct p2k_mount *p2m, int error)
40138a8ac9cSpooka {
40238a8ac9cSpooka
40338a8ac9cSpooka puffs_cancel(p2m->p2m_pu, error);
40438a8ac9cSpooka free(p2m);
40538a8ac9cSpooka }
40638a8ac9cSpooka
40738a8ac9cSpooka static int
setupfs(struct p2k_mount * p2m,const char * vfsname,const char * devpath,struct ukfs_part * part,const char * mountpath,int mntflags,void * arg,size_t alen)40838a8ac9cSpooka setupfs(struct p2k_mount *p2m, const char *vfsname, const char *devpath,
409a1c46739Spooka struct ukfs_part *part, const char *mountpath, int mntflags,
41038a8ac9cSpooka void *arg, size_t alen)
41138a8ac9cSpooka {
412a1c46739Spooka char partpath[UKFS_DEVICE_MAXPATHLEN];
413a1c46739Spooka char partbuf[UKFS_DEVICE_MAXSTR];
41438a8ac9cSpooka char typebuf[PUFFS_TYPELEN];
41538a8ac9cSpooka struct puffs_usermount *pu = p2m->p2m_pu;
41638a8ac9cSpooka struct p2k_node *p2n_root;
41738a8ac9cSpooka struct ukfs *ukfs = NULL;
41838a8ac9cSpooka extern int puffs_fakecc;
41938a8ac9cSpooka int rv = -1, sverrno;
42038a8ac9cSpooka
421bdf6e0b0Spooka strcpy(typebuf, "p2k|");
422bdf6e0b0Spooka if (strcmp(vfsname, "puffs") == 0) { /* XXX */
423bdf6e0b0Spooka struct puffs_kargs *args = arg;
424bdf6e0b0Spooka strlcat(typebuf, args->pa_typename, sizeof(typebuf));
425bdf6e0b0Spooka } else {
426bdf6e0b0Spooka strlcat(typebuf, vfsname, sizeof(typebuf));
427bdf6e0b0Spooka }
428bdf6e0b0Spooka
4290605ce2bSpooka strlcpy(partpath, devpath, sizeof(partpath));
430a1c46739Spooka if (ukfs_part_tostring(part, partbuf, sizeof(partbuf))) {
4310605ce2bSpooka strlcat(partpath, partbuf, sizeof(partpath));
4320605ce2bSpooka }
43338a8ac9cSpooka puffs_setmntinfo(pu, partpath, typebuf);
434710e4c1aSpooka
435710e4c1aSpooka if (ukfs_init() == -1)
436476b5ba6Spooka goto out;
43730df4c9fSpooka
43830df4c9fSpooka /*
43930df4c9fSpooka * If we're mounting rumpfs, actually do no mount and redirect
44030df4c9fSpooka * requests to rump fs namespace root. Strictly speaking, this
441404fa78cSpooka * is not correct, but I don't think anyone will notice.
442404fa78cSpooka * After all, we're mostly interested in things which reside
443404fa78cSpooka * specifically on the rootfs, namely the contents of /dev
44430df4c9fSpooka */
44530df4c9fSpooka if (strcmp(vfsname, MOUNT_RUMPFS) == 0) {
44630df4c9fSpooka if ((rv = rump_pub_vfs_getmp("/", &p2m->p2m_mp)) != 0) {
44730df4c9fSpooka errno = rv;
44830df4c9fSpooka rv = -1;
44930df4c9fSpooka goto out;
45030df4c9fSpooka }
45130df4c9fSpooka } else {
452a1c46739Spooka if (part != ukfs_part_na)
453a1c46739Spooka ukfs = ukfs_mount_disk(vfsname, devpath, part,
4540605ce2bSpooka mountpath, mntflags, arg, alen);
4550605ce2bSpooka else
4560605ce2bSpooka ukfs = ukfs_mount(vfsname, devpath, mountpath, mntflags,
4570605ce2bSpooka arg, alen);
458710e4c1aSpooka if (ukfs == NULL)
459710e4c1aSpooka goto out;
46038a8ac9cSpooka ukfs_setspecific(ukfs, p2m);
461476b5ba6Spooka p2m->p2m_ukfs = ukfs;
46230df4c9fSpooka p2m->p2m_mp = ukfs_getmp(ukfs);
463607d9b61Spooka }
464607d9b61Spooka if ((rv = rump_pub_vfs_root(p2m->p2m_mp, &p2m->p2m_rvp, 0)) != 0) {
465607d9b61Spooka errno = rv;
466607d9b61Spooka rv = -1;
467607d9b61Spooka goto out;
46830df4c9fSpooka }
46930df4c9fSpooka
470476b5ba6Spooka p2m->p2m_pu = pu;
471710e4c1aSpooka
47213777d56Spooka /*
47313777d56Spooka * Detect tmpfs. XXX: this is a kludge. See inactive().
47413777d56Spooka *
47513777d56Spooka * In reality we'd want "does file system use anon objects
47613777d56Spooka * for storage?". But since tmpfs hides the anon object from
47713777d56Spooka * the public interface, we can't actually detect it sanely.
47813777d56Spooka * Therefore, use this kludge.
47913777d56Spooka */
48013777d56Spooka p2m->p2m_imtmpfsman = strcmp(vfsname, MOUNT_TMPFS) == 0;
48113777d56Spooka
4825290e6c8Spooka p2n_root = getp2n(p2m, p2m->p2m_rvp, true, NULL);
483bdf6e0b0Spooka puffs_setfhsize(pu, 0, PUFFS_FHFLAG_PASSTHROUGH);
484bdf6e0b0Spooka puffs_setstacksize(pu, PUFFS_STACKSIZE_MIN);
485bdf6e0b0Spooka puffs_fakecc = 1;
486cd52561aSpooka puffs_set_prepost(pu, makelwp, NULL);
48727daa694Spooka
48827daa694Spooka if (p2m->p2m_hasdebug) {
48927daa694Spooka struct timespec ts;
49027daa694Spooka
49127daa694Spooka signal(SIGINFO, sighand);
49227daa694Spooka signal(SIGUSR1, sighand);
49327daa694Spooka
49427daa694Spooka ts.tv_sec = 0;
49527daa694Spooka ts.tv_nsec = 1000*1000*10; /* 10ms */
49627daa694Spooka puffs_ml_setloopfn(pu, dumpmp);
49727daa694Spooka puffs_ml_settimeout(pu, &ts);
49827daa694Spooka }
499c67ff293Spooka puffs_set_errnotify(pu, p2k_errcatcher);
500bdf6e0b0Spooka
50130df4c9fSpooka puffs_setspecific(pu, p2m);
50238a8ac9cSpooka rv = puffs_mount(pu, mountpath, mntflags, p2n_root);
503bdf6e0b0Spooka
504bdf6e0b0Spooka out:
50538a8ac9cSpooka if (rv == -1) {
506bdf6e0b0Spooka sverrno = errno;
50738a8ac9cSpooka puffs_cancel(pu, sverrno);
508710e4c1aSpooka if (ukfs)
509476b5ba6Spooka ukfs_release(p2m->p2m_ukfs, UKFS_RELFLAG_FORCE);
510476b5ba6Spooka free(p2m);
511bdf6e0b0Spooka errno = sverrno;
512bdf6e0b0Spooka }
513bdf6e0b0Spooka
51438a8ac9cSpooka return rv;
515476b5ba6Spooka }
516476b5ba6Spooka
517476b5ba6Spooka int
p2k_mainloop(struct p2k_mount * p2m)518476b5ba6Spooka p2k_mainloop(struct p2k_mount *p2m)
519476b5ba6Spooka {
520476b5ba6Spooka int rv, sverrno;
521476b5ba6Spooka
522476b5ba6Spooka rv = puffs_mainloop(p2m->p2m_pu);
523476b5ba6Spooka sverrno = errno;
524476b5ba6Spooka puffs_exit(p2m->p2m_pu, 1);
525476b5ba6Spooka if (p2m->p2m_ukfs)
526476b5ba6Spooka ukfs_release(p2m->p2m_ukfs, UKFS_RELFLAG_FORCE);
527476b5ba6Spooka free(p2m);
528476b5ba6Spooka
529476b5ba6Spooka if (rv == -1)
530476b5ba6Spooka errno = sverrno;
531bdf6e0b0Spooka return rv;
532bdf6e0b0Spooka }
533bdf6e0b0Spooka
5340605ce2bSpooka int
p2k_run_fs(const char * vfsname,const char * devpath,const char * mountpath,int mntflags,void * arg,size_t alen,uint32_t puffs_flags)5350605ce2bSpooka p2k_run_fs(const char *vfsname, const char *devpath, const char *mountpath,
5360605ce2bSpooka int mntflags, void *arg, size_t alen, uint32_t puffs_flags)
5370605ce2bSpooka {
538476b5ba6Spooka struct p2k_mount *p2m;
53938a8ac9cSpooka int rv;
5400605ce2bSpooka
54138a8ac9cSpooka p2m = p2k_init(puffs_flags);
542476b5ba6Spooka if (p2m == NULL)
543476b5ba6Spooka return -1;
544a1c46739Spooka rv = setupfs(p2m, vfsname, devpath, ukfs_part_na, mountpath,
54538a8ac9cSpooka mntflags, arg, alen);
54638a8ac9cSpooka if (rv == -1)
54738a8ac9cSpooka return rv;
548476b5ba6Spooka return p2k_mainloop(p2m);
5490605ce2bSpooka }
5500605ce2bSpooka
5510605ce2bSpooka int
p2k_run_diskfs(const char * vfsname,const char * devpath,struct ukfs_part * part,const char * mountpath,int mntflags,void * arg,size_t alen,uint32_t puffs_flags)552a1c46739Spooka p2k_run_diskfs(const char *vfsname, const char *devpath, struct ukfs_part *part,
5530605ce2bSpooka const char *mountpath, int mntflags, void *arg, size_t alen,
5540605ce2bSpooka uint32_t puffs_flags)
5550605ce2bSpooka {
556476b5ba6Spooka struct p2k_mount *p2m;
55738a8ac9cSpooka int rv;
5580605ce2bSpooka
55938a8ac9cSpooka p2m = p2k_init(puffs_flags);
560476b5ba6Spooka if (p2m == NULL)
561476b5ba6Spooka return -1;
562a1c46739Spooka rv = setupfs(p2m, vfsname, devpath, part, mountpath, mntflags,
56338a8ac9cSpooka arg, alen);
56438a8ac9cSpooka if (rv == -1)
56538a8ac9cSpooka return rv;
566476b5ba6Spooka return p2k_mainloop(p2m);
567476b5ba6Spooka }
568476b5ba6Spooka
56938a8ac9cSpooka int
p2k_setup_fs(struct p2k_mount * p2m,const char * vfsname,const char * devpath,const char * mountpath,int mntflags,void * arg,size_t alen)57038a8ac9cSpooka p2k_setup_fs(struct p2k_mount *p2m, const char *vfsname, const char *devpath,
57138a8ac9cSpooka const char *mountpath, int mntflags, void *arg, size_t alen)
572476b5ba6Spooka {
573476b5ba6Spooka
574a1c46739Spooka return setupfs(p2m, vfsname, devpath, ukfs_part_na, mountpath,
57538a8ac9cSpooka mntflags, arg, alen);
576476b5ba6Spooka }
577476b5ba6Spooka
57838a8ac9cSpooka int
p2k_setup_diskfs(struct p2k_mount * p2m,const char * vfsname,const char * devpath,struct ukfs_part * part,const char * mountpath,int mntflags,void * arg,size_t alen)57938a8ac9cSpooka p2k_setup_diskfs(struct p2k_mount *p2m, const char *vfsname,
580a1c46739Spooka const char *devpath, struct ukfs_part *part, const char *mountpath,
58138a8ac9cSpooka int mntflags, void *arg, size_t alen)
582476b5ba6Spooka {
583476b5ba6Spooka
584a1c46739Spooka return setupfs(p2m, vfsname, devpath, part, mountpath, mntflags,
58538a8ac9cSpooka arg, alen);
5860605ce2bSpooka }
5870605ce2bSpooka
588bdf6e0b0Spooka int
p2k_fs_statvfs(struct puffs_usermount * pu,struct puffs_statvfs * sbp)58938a0431bSchristos p2k_fs_statvfs(struct puffs_usermount *pu, struct puffs_statvfs *sbp)
590bdf6e0b0Spooka {
59130df4c9fSpooka struct p2k_mount *p2m = puffs_getspecific(pu);
59230df4c9fSpooka struct mount *mp = p2m->p2m_mp;
59338a0431bSchristos struct statvfs sb;
59438a0431bSchristos puffs_statvfs_to_statvfs(sbp, &sb);
595bdf6e0b0Spooka
59638a0431bSchristos return rump_pub_vfs_statvfs(mp, &sb);
597bdf6e0b0Spooka }
598bdf6e0b0Spooka
599d51d08a7Spooka /*ARGSUSED*/
600bdf6e0b0Spooka int
p2k_fs_unmount(struct puffs_usermount * pu,int flags)601bdf6e0b0Spooka p2k_fs_unmount(struct puffs_usermount *pu, int flags)
602bdf6e0b0Spooka {
60330df4c9fSpooka struct p2k_mount *p2m = puffs_getspecific(pu);
60430df4c9fSpooka struct ukfs *fs = p2m->p2m_ukfs;
6055290e6c8Spooka int error = 0;
606bdf6e0b0Spooka
607bf3992afSpooka rump_pub_vp_rele(p2m->p2m_rvp);
608cd52561aSpooka
60930df4c9fSpooka if (fs) {
6105290e6c8Spooka if (ukfs_release(fs, 0) != 0) {
61138a0431bSchristos struct puffs_statvfs svfsb;
612d32ef440Spooka
613d32ef440Spooka if (p2m->p2m_hasdebug
614d32ef440Spooka && p2k_fs_statvfs(pu, &svfsb) == 0) {
615d32ef440Spooka printf("\nSOFT UNMOUNT FAILED, MP INFO DUMP\n");
616d32ef440Spooka rump_pub_vfs_mount_print(svfsb.f_mntonname, 1);
617d32ef440Spooka }
618d51d08a7Spooka ukfs_release(fs, UKFS_RELFLAG_FORCE);
6195290e6c8Spooka error = 0;
6205290e6c8Spooka }
62130df4c9fSpooka }
622476b5ba6Spooka p2m->p2m_ukfs = NULL;
623bdf6e0b0Spooka
624d16346a2Spooka if (p2m->p2m_hasdebug) {
625d16346a2Spooka printf("-- rump kernel event counters --\n");
626d16346a2Spooka rump_printevcnts();
627d16346a2Spooka printf("-- end of event counters --\n");
628d16346a2Spooka }
629d16346a2Spooka
6305290e6c8Spooka return error;
631bdf6e0b0Spooka }
632bdf6e0b0Spooka
633bdf6e0b0Spooka int
p2k_fs_sync(struct puffs_usermount * pu,int waitfor,const struct puffs_cred * pcr)634bdf6e0b0Spooka p2k_fs_sync(struct puffs_usermount *pu, int waitfor,
635bdf6e0b0Spooka const struct puffs_cred *pcr)
636bdf6e0b0Spooka {
63730df4c9fSpooka struct p2k_mount *p2m = puffs_getspecific(pu);
63830df4c9fSpooka struct mount *mp = p2m->p2m_mp;
6392734e549Spooka struct kauth_cred *cred;
640bdf6e0b0Spooka int rv;
641bdf6e0b0Spooka
642bdf6e0b0Spooka cred = cred_create(pcr);
6432734e549Spooka rv = rump_pub_vfs_sync(mp, waitfor, cred);
644bdf6e0b0Spooka cred_destroy(cred);
645bdf6e0b0Spooka
646bdf6e0b0Spooka return rv;
647bdf6e0b0Spooka }
648bdf6e0b0Spooka
649bdf6e0b0Spooka /*ARGSUSED*/
650bdf6e0b0Spooka int
p2k_fs_fhtonode(struct puffs_usermount * pu,void * fid,size_t fidsize,struct puffs_newinfo * pni)651bdf6e0b0Spooka p2k_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
652bdf6e0b0Spooka struct puffs_newinfo *pni)
653bdf6e0b0Spooka {
65430df4c9fSpooka struct p2k_mount *p2m = puffs_getspecific(pu);
65530df4c9fSpooka struct mount *mp = p2m->p2m_mp;
6565290e6c8Spooka struct p2k_node *p2n;
657bdf6e0b0Spooka struct vnode *vp;
658005755d8Spooka enum rump_vtype vtype;
659bdf6e0b0Spooka voff_t vsize;
6605290e6c8Spooka uint64_t rdev; /* XXX: allows running this on NetBSD 5.0 */
661bdf6e0b0Spooka int rv;
662bdf6e0b0Spooka
663bf3992afSpooka rv = rump_pub_vfs_fhtovp(mp, fid, &vp);
664bdf6e0b0Spooka if (rv)
665bdf6e0b0Spooka return rv;
6661423e65bShannken RUMP_VOP_UNLOCK(vp);
667bdf6e0b0Spooka
6685290e6c8Spooka p2n = getp2n(p2m, vp, false, NULL);
6695290e6c8Spooka if (p2n == NULL)
6705290e6c8Spooka return ENOMEM;
6715290e6c8Spooka
6725290e6c8Spooka puffs_newinfo_setcookie(pni, p2n);
673bf3992afSpooka rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev);
674d3095eb5Sjoerg puffs_newinfo_setvtype(pni, (enum vtype)vtype);
675bdf6e0b0Spooka puffs_newinfo_setsize(pni, vsize);
6765290e6c8Spooka /* LINTED: yea, it'll lose accuracy, but that's life */
677bdf6e0b0Spooka puffs_newinfo_setrdev(pni, rdev);
678bdf6e0b0Spooka
679bdf6e0b0Spooka return 0;
680bdf6e0b0Spooka }
681bdf6e0b0Spooka
682bdf6e0b0Spooka /*ARGSUSED*/
683bdf6e0b0Spooka int
p2k_fs_nodetofh(struct puffs_usermount * pu,puffs_cookie_t cookie,void * fid,size_t * fidsize)6843fd391abSpooka p2k_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie, void *fid,
685bdf6e0b0Spooka size_t *fidsize)
686bdf6e0b0Spooka {
6874063bc51Spooka struct vnode *vp = OPC2VP(cookie);
688bdf6e0b0Spooka
689bf3992afSpooka return rump_pub_vfs_vptofh(vp, fid, fidsize);
690bdf6e0b0Spooka }
691bdf6e0b0Spooka
69255a23816Spooka int
p2k_fs_extattrctl(struct puffs_usermount * pu,int cmd,puffs_cookie_t cookie,int flags,int attrnamespace,const char * attrname)69355a23816Spooka p2k_fs_extattrctl(struct puffs_usermount *pu, int cmd,
69455a23816Spooka puffs_cookie_t cookie, int flags,
69555a23816Spooka int attrnamespace, const char *attrname)
69655a23816Spooka {
69755a23816Spooka struct p2k_mount *p2m = puffs_getspecific(pu);
69855a23816Spooka struct mount *mp = p2m->p2m_mp;
69955a23816Spooka struct vnode *vp;
70055a23816Spooka
70155a23816Spooka if (flags & PUFFS_EXTATTRCTL_HASNODE) {
70255a23816Spooka vp = OPC2VP(cookie);
70355a23816Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE | LK_RETRY);
70455a23816Spooka } else {
70555a23816Spooka vp = NULL;
70655a23816Spooka }
70755a23816Spooka
70855a23816Spooka /* vfsop unlocks (but doesn't release) vnode, so we're done here */
70955a23816Spooka return rump_pub_vfs_extattrctl(mp, cmd, vp, attrnamespace, attrname);
71055a23816Spooka }
71155a23816Spooka
712bdf6e0b0Spooka /*ARGSUSED*/
713bdf6e0b0Spooka int
p2k_node_lookup(struct puffs_usermount * pu,puffs_cookie_t opc,struct puffs_newinfo * pni,const struct puffs_cn * pcn)7143fd391abSpooka p2k_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc,
715bdf6e0b0Spooka struct puffs_newinfo *pni, const struct puffs_cn *pcn)
716bdf6e0b0Spooka {
71730df4c9fSpooka struct p2k_mount *p2m = puffs_getspecific(pu);
7185290e6c8Spooka struct p2k_node *p2n_dir = opc, *p2n;
719bdf6e0b0Spooka struct componentname *cn;
7205290e6c8Spooka struct vnode *dvp = p2n_dir->p2n_vp, *vp;
721005755d8Spooka enum rump_vtype vtype;
722bdf6e0b0Spooka voff_t vsize;
72325c08576Spooka uint64_t rdev; /* XXX: uint64_t because of stack overwrite in compat */
724bdf6e0b0Spooka int rv;
725bdf6e0b0Spooka
7269670fcafSpooka cn = makecn(pcn);
7275290e6c8Spooka RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE);
7285290e6c8Spooka rv = RUMP_VOP_LOOKUP(dvp, &vp, cn);
7291423e65bShannken RUMP_VOP_UNLOCK(dvp);
7309670fcafSpooka freecn(cn);
7319670fcafSpooka
732bdf6e0b0Spooka if (rv) {
733e6d33ac9Spooka if (rv == RUMP_EJUSTRETURN) {
734bdf6e0b0Spooka rv = ENOENT;
7355290e6c8Spooka }
736bdf6e0b0Spooka return rv;
737bdf6e0b0Spooka }
738bdf6e0b0Spooka
7395290e6c8Spooka p2n = getp2n(p2m, vp, false, NULL);
7405290e6c8Spooka if (p2n == NULL) {
7415290e6c8Spooka return ENOMEM;
7425290e6c8Spooka }
7435290e6c8Spooka
7445290e6c8Spooka puffs_newinfo_setcookie(pni, p2n);
745bf3992afSpooka rump_pub_getvninfo(vp, &vtype, &vsize, (void *)&rdev);
746d3095eb5Sjoerg puffs_newinfo_setvtype(pni, (enum vtype)vtype);
747bdf6e0b0Spooka puffs_newinfo_setsize(pni, vsize);
7485290e6c8Spooka /* LINTED: yea, it'll lose accuracy, but that's life */
749bdf6e0b0Spooka puffs_newinfo_setrdev(pni, rdev);
750bdf6e0b0Spooka
751bdf6e0b0Spooka return 0;
752bdf6e0b0Spooka }
753bdf6e0b0Spooka
75425c08576Spooka #define VERS_TIMECHANGE 599000700
75525c08576Spooka static int
needcompat(void)75625c08576Spooka needcompat(void)
75725c08576Spooka {
75825c08576Spooka
759d51d08a7Spooka /*LINTED*/
76025c08576Spooka return __NetBSD_Version__ < VERS_TIMECHANGE
76143925050Spooka && rump_getversion() >= VERS_TIMECHANGE;
76225c08576Spooka }
76325c08576Spooka
76425c08576Spooka #define DOCOMPAT(va, va_compat) \
76525c08576Spooka do { \
76625c08576Spooka if (needcompat()) { \
767bf3992afSpooka va_compat = rump_pub_vattr_init(); \
768bf3992afSpooka rump_pub_vattr50_to_vattr(va, va_compat); \
76925c08576Spooka } else { \
77025c08576Spooka va_compat = __UNCONST(va); \
77125c08576Spooka } \
772388550b0Srillig } while (0)
77325c08576Spooka
77425c08576Spooka #define UNDOCOMPAT(va_compat) \
77525c08576Spooka do { \
77625c08576Spooka if (needcompat()) \
777bf3992afSpooka rump_pub_vattr_free(va_compat); \
778388550b0Srillig } while (0)
77925c08576Spooka
7805290e6c8Spooka static int
do_makenode(struct puffs_usermount * pu,struct p2k_node * p2n_dir,struct puffs_newinfo * pni,const struct puffs_cn * pcn,const struct vattr * vap,char * link_target,int (* makefn)(struct vnode *,struct vnode **,struct componentname *,struct vattr *),int (* symfn)(struct vnode *,struct vnode **,struct componentname *,struct vattr *,char *))7815290e6c8Spooka do_makenode(struct puffs_usermount *pu, struct p2k_node *p2n_dir,
7825290e6c8Spooka struct puffs_newinfo *pni, const struct puffs_cn *pcn,
7835290e6c8Spooka const struct vattr *vap, char *link_target,
7845290e6c8Spooka int (*makefn)(struct vnode *, struct vnode **, struct componentname *,
7855290e6c8Spooka struct vattr *),
7865290e6c8Spooka int (*symfn)(struct vnode *, struct vnode **, struct componentname *,
7875290e6c8Spooka struct vattr *, char *))
7885290e6c8Spooka {
78930df4c9fSpooka struct p2k_mount *p2m = puffs_getspecific(pu);
7905290e6c8Spooka struct vnode *dvp = p2n_dir->p2n_vp;
7915290e6c8Spooka struct p2k_node *p2n;
7925290e6c8Spooka struct componentname *cn;
7935290e6c8Spooka struct vattr *va_x;
794f638f19cSriastradh struct vnode *vp = NULL;
7955290e6c8Spooka int rv;
7965290e6c8Spooka
7975290e6c8Spooka p2n = malloc(sizeof(*p2n));
7985290e6c8Spooka if (p2n == NULL)
7995290e6c8Spooka return ENOMEM;
8005290e6c8Spooka DOCOMPAT(vap, va_x);
8015290e6c8Spooka
8029670fcafSpooka cn = makecn(pcn);
8035290e6c8Spooka RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE);
804bf3992afSpooka rump_pub_vp_incref(dvp);
8055290e6c8Spooka if (makefn) {
8065290e6c8Spooka rv = makefn(dvp, &vp, cn, va_x);
8075290e6c8Spooka } else {
8085290e6c8Spooka rv = symfn(dvp, &vp, cn, va_x, link_target);
8095290e6c8Spooka }
810c89a5913Sriastradh rump_pub_vp_rele(dvp);
81111392744Shannken RUMP_VOP_UNLOCK(dvp);
8129670fcafSpooka freecn(cn);
8135290e6c8Spooka
8145290e6c8Spooka if (rv == 0) {
8155290e6c8Spooka p2n = getp2n(p2m, vp, true, p2n);
8165290e6c8Spooka puffs_newinfo_setcookie(pni, p2n);
8175290e6c8Spooka } else {
8185290e6c8Spooka free(p2n);
8195290e6c8Spooka }
8205290e6c8Spooka
8215290e6c8Spooka UNDOCOMPAT(va_x);
8225290e6c8Spooka
8235290e6c8Spooka return rv;
8245290e6c8Spooka
8255290e6c8Spooka }
8265290e6c8Spooka
827bdf6e0b0Spooka /*ARGSUSED*/
828bdf6e0b0Spooka int
p2k_node_create(struct puffs_usermount * pu,puffs_cookie_t opc,struct puffs_newinfo * pni,const struct puffs_cn * pcn,const struct vattr * vap)8293fd391abSpooka p2k_node_create(struct puffs_usermount *pu, puffs_cookie_t opc,
830bdf6e0b0Spooka struct puffs_newinfo *pni, const struct puffs_cn *pcn,
831bdf6e0b0Spooka const struct vattr *vap)
832bdf6e0b0Spooka {
833bdf6e0b0Spooka
8345290e6c8Spooka return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_CREATE, NULL);
835bdf6e0b0Spooka }
836bdf6e0b0Spooka
837bdf6e0b0Spooka /*ARGSUSED*/
838bdf6e0b0Spooka int
p2k_node_mknod(struct puffs_usermount * pu,puffs_cookie_t opc,struct puffs_newinfo * pni,const struct puffs_cn * pcn,const struct vattr * vap)8393fd391abSpooka p2k_node_mknod(struct puffs_usermount *pu, puffs_cookie_t opc,
8403fd391abSpooka struct puffs_newinfo *pni, const struct puffs_cn *pcn,
8413fd391abSpooka const struct vattr *vap)
842bdf6e0b0Spooka {
843bdf6e0b0Spooka
8445290e6c8Spooka return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_MKNOD, NULL);
845bdf6e0b0Spooka }
846bdf6e0b0Spooka
847bdf6e0b0Spooka /*ARGSUSED*/
848bdf6e0b0Spooka int
p2k_node_open(struct puffs_usermount * pu,puffs_cookie_t opc,int mode,const struct puffs_cred * pcr)8493fd391abSpooka p2k_node_open(struct puffs_usermount *pu, puffs_cookie_t opc, int mode,
850bdf6e0b0Spooka const struct puffs_cred *pcr)
851bdf6e0b0Spooka {
8525290e6c8Spooka struct vnode *vp = OPC2VP(opc);
8532734e549Spooka struct kauth_cred *cred;
854bdf6e0b0Spooka int rv;
855bdf6e0b0Spooka
856bdf6e0b0Spooka cred = cred_create(pcr);
8575290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
8585290e6c8Spooka rv = RUMP_VOP_OPEN(vp, mode, cred);
8591423e65bShannken RUMP_VOP_UNLOCK(vp);
860bdf6e0b0Spooka cred_destroy(cred);
861bdf6e0b0Spooka
862bdf6e0b0Spooka return rv;
863bdf6e0b0Spooka }
864bdf6e0b0Spooka
865bdf6e0b0Spooka /*ARGSUSED*/
866bdf6e0b0Spooka int
p2k_node_close(struct puffs_usermount * pu,puffs_cookie_t opc,int flags,const struct puffs_cred * pcr)8673fd391abSpooka p2k_node_close(struct puffs_usermount *pu, puffs_cookie_t opc, int flags,
868bdf6e0b0Spooka const struct puffs_cred *pcr)
869bdf6e0b0Spooka {
8705290e6c8Spooka struct vnode *vp = OPC2VP(opc);
8712734e549Spooka struct kauth_cred *cred;
872bdf6e0b0Spooka
873bdf6e0b0Spooka cred = cred_create(pcr);
8745290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
8755290e6c8Spooka RUMP_VOP_CLOSE(vp, flags, cred);
8761423e65bShannken RUMP_VOP_UNLOCK(vp);
877bdf6e0b0Spooka cred_destroy(cred);
878bdf6e0b0Spooka
879bdf6e0b0Spooka return 0;
880bdf6e0b0Spooka }
881bdf6e0b0Spooka
882bdf6e0b0Spooka /*ARGSUSED*/
883bdf6e0b0Spooka int
p2k_node_access(struct puffs_usermount * pu,puffs_cookie_t opc,int mode,const struct puffs_cred * pcr)8843fd391abSpooka p2k_node_access(struct puffs_usermount *pu, puffs_cookie_t opc, int mode,
885bdf6e0b0Spooka const struct puffs_cred *pcr)
886bdf6e0b0Spooka {
8875290e6c8Spooka struct vnode *vp = OPC2VP(opc);
8882734e549Spooka struct kauth_cred *cred;
889bdf6e0b0Spooka int rv;
890bdf6e0b0Spooka
891bdf6e0b0Spooka cred = cred_create(pcr);
8925290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
8935290e6c8Spooka rv = RUMP_VOP_ACCESS(vp, mode, cred);
8941423e65bShannken RUMP_VOP_UNLOCK(vp);
895bdf6e0b0Spooka cred_destroy(cred);
896bdf6e0b0Spooka
897bdf6e0b0Spooka return rv;
898bdf6e0b0Spooka }
899bdf6e0b0Spooka
900bdf6e0b0Spooka /*ARGSUSED*/
901bdf6e0b0Spooka int
p2k_node_getattr(struct puffs_usermount * pu,puffs_cookie_t opc,struct vattr * vap,const struct puffs_cred * pcr)9023fd391abSpooka p2k_node_getattr(struct puffs_usermount *pu, puffs_cookie_t opc,
9033fd391abSpooka struct vattr *vap, const struct puffs_cred *pcr)
904bdf6e0b0Spooka {
9055290e6c8Spooka struct vnode *vp = OPC2VP(opc);
9062734e549Spooka struct kauth_cred *cred;
90725c08576Spooka struct vattr *va_x;
908bdf6e0b0Spooka int rv;
909bdf6e0b0Spooka
910a06931dbSpooka /* "deadfs" */
911a06931dbSpooka if (!vp)
912a06931dbSpooka return 0;
913a06931dbSpooka
91425c08576Spooka if (needcompat()) {
915bf3992afSpooka va_x = rump_pub_vattr_init();
91625c08576Spooka } else {
91725c08576Spooka va_x = vap;
91825c08576Spooka }
91925c08576Spooka
920bdf6e0b0Spooka cred = cred_create(pcr);
9215290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
9225290e6c8Spooka rv = RUMP_VOP_GETATTR(vp, va_x, cred);
9231423e65bShannken RUMP_VOP_UNLOCK(vp);
924bdf6e0b0Spooka cred_destroy(cred);
925bdf6e0b0Spooka
92625c08576Spooka if (needcompat()) {
927bf3992afSpooka rump_pub_vattr_to_vattr50(va_x, vap);
928bf3992afSpooka rump_pub_vattr_free(va_x);
92925c08576Spooka }
93025c08576Spooka
931bdf6e0b0Spooka return rv;
932bdf6e0b0Spooka }
933bdf6e0b0Spooka
934bdf6e0b0Spooka /*ARGSUSED*/
935bdf6e0b0Spooka int
p2k_node_setattr(struct puffs_usermount * pu,puffs_cookie_t opc,const struct vattr * vap,const struct puffs_cred * pcr)9363fd391abSpooka p2k_node_setattr(struct puffs_usermount *pu, puffs_cookie_t opc,
9373fd391abSpooka const struct vattr *vap, const struct puffs_cred *pcr)
938bdf6e0b0Spooka {
9395290e6c8Spooka struct vnode *vp = OPC2VP(opc);
9402734e549Spooka struct kauth_cred *cred;
94125c08576Spooka struct vattr *va_x;
942bdf6e0b0Spooka int rv;
943bdf6e0b0Spooka
9445290e6c8Spooka /* "deadfs" */
9455290e6c8Spooka if (!vp)
9465290e6c8Spooka return 0;
9475290e6c8Spooka
94825c08576Spooka DOCOMPAT(vap, va_x);
94925c08576Spooka
950bdf6e0b0Spooka cred = cred_create(pcr);
9515290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
9525290e6c8Spooka rv = RUMP_VOP_SETATTR(vp, va_x, cred);
9531423e65bShannken RUMP_VOP_UNLOCK(vp);
954bdf6e0b0Spooka cred_destroy(cred);
955bdf6e0b0Spooka
95625c08576Spooka UNDOCOMPAT(va_x);
95725c08576Spooka
958bdf6e0b0Spooka return rv;
959bdf6e0b0Spooka }
960bdf6e0b0Spooka
961bdf6e0b0Spooka /*ARGSUSED*/
962bdf6e0b0Spooka int
p2k_node_fsync(struct puffs_usermount * pu,puffs_cookie_t opc,const struct puffs_cred * pcr,int flags,off_t offlo,off_t offhi)9633fd391abSpooka p2k_node_fsync(struct puffs_usermount *pu, puffs_cookie_t opc,
964bdf6e0b0Spooka const struct puffs_cred *pcr, int flags, off_t offlo, off_t offhi)
965bdf6e0b0Spooka {
9665290e6c8Spooka struct vnode *vp = OPC2VP(opc);
9672734e549Spooka struct kauth_cred *cred;
968bdf6e0b0Spooka int rv;
969bdf6e0b0Spooka
9705290e6c8Spooka /* "deadfs" */
9715290e6c8Spooka if (!vp)
9725290e6c8Spooka return 0;
9735290e6c8Spooka
974bdf6e0b0Spooka cred = cred_create(pcr);
9755290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
9765290e6c8Spooka rv = RUMP_VOP_FSYNC(vp, cred, flags, offlo, offhi);
9771423e65bShannken RUMP_VOP_UNLOCK(vp);
978bdf6e0b0Spooka cred_destroy(cred);
979bdf6e0b0Spooka
980bdf6e0b0Spooka return rv;
981bdf6e0b0Spooka }
982bdf6e0b0Spooka
983bdf6e0b0Spooka /*ARGSUSED*/
984bdf6e0b0Spooka int
p2k_node_mmap(struct puffs_usermount * pu,puffs_cookie_t opc,vm_prot_t flags,const struct puffs_cred * pcr)9853fd391abSpooka p2k_node_mmap(struct puffs_usermount *pu, puffs_cookie_t opc, vm_prot_t flags,
986bdf6e0b0Spooka const struct puffs_cred *pcr)
987bdf6e0b0Spooka {
9882734e549Spooka struct kauth_cred *cred;
989bdf6e0b0Spooka int rv;
990bdf6e0b0Spooka
991bdf6e0b0Spooka cred = cred_create(pcr);
9925290e6c8Spooka rv = RUMP_VOP_MMAP(OPC2VP(opc), flags, cred);
993bdf6e0b0Spooka cred_destroy(cred);
994bdf6e0b0Spooka
995bdf6e0b0Spooka return rv;
996bdf6e0b0Spooka }
997bdf6e0b0Spooka
998bdf6e0b0Spooka /*ARGSUSED*/
999bdf6e0b0Spooka int
p2k_node_seek(struct puffs_usermount * pu,puffs_cookie_t opc,off_t oldoff,off_t newoff,const struct puffs_cred * pcr)10003fd391abSpooka p2k_node_seek(struct puffs_usermount *pu, puffs_cookie_t opc,
10013fd391abSpooka off_t oldoff, off_t newoff, const struct puffs_cred *pcr)
1002bdf6e0b0Spooka {
10035290e6c8Spooka struct vnode *vp = OPC2VP(opc);
10042734e549Spooka struct kauth_cred *cred;
1005bdf6e0b0Spooka int rv;
1006bdf6e0b0Spooka
1007bdf6e0b0Spooka cred = cred_create(pcr);
10085290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
10095290e6c8Spooka rv = RUMP_VOP_SEEK(vp, oldoff, newoff, cred);
10101423e65bShannken RUMP_VOP_UNLOCK(vp);
1011bdf6e0b0Spooka cred_destroy(cred);
1012bdf6e0b0Spooka
1013bdf6e0b0Spooka return rv;
1014bdf6e0b0Spooka }
1015bdf6e0b0Spooka
10165290e6c8Spooka static int
do_nukenode(struct p2k_node * p2n_dir,struct p2k_node * p2n,const struct puffs_cn * pcn,int (* nukefn)(struct vnode *,struct vnode *,struct componentname *))10175290e6c8Spooka do_nukenode(struct p2k_node *p2n_dir, struct p2k_node *p2n,
10185290e6c8Spooka const struct puffs_cn *pcn,
10195290e6c8Spooka int (*nukefn)(struct vnode *, struct vnode *, struct componentname *))
10205290e6c8Spooka {
10215290e6c8Spooka struct vnode *dvp = p2n_dir->p2n_vp, *vp = p2n->p2n_vp;
10225290e6c8Spooka struct componentname *cn;
10235290e6c8Spooka int rv;
10245290e6c8Spooka
10259670fcafSpooka cn = makecn(pcn);
10265290e6c8Spooka RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE);
1027bf3992afSpooka rump_pub_vp_incref(dvp);
10285290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1029bf3992afSpooka rump_pub_vp_incref(vp);
10305290e6c8Spooka rv = nukefn(dvp, vp, cn);
10316fa7b158Sriastradh assert(dvp != vp);
10326fa7b158Sriastradh assert(RUMP_VOP_ISLOCKED(dvp) == LK_EXCLUSIVE);
10335290e6c8Spooka assert(RUMP_VOP_ISLOCKED(vp) == 0);
10346fa7b158Sriastradh rump_pub_vp_rele(dvp);
10356fa7b158Sriastradh RUMP_VOP_UNLOCK(dvp);
10369670fcafSpooka freecn(cn);
10375290e6c8Spooka
10385290e6c8Spooka return rv;
10395290e6c8Spooka
10405290e6c8Spooka }
10415290e6c8Spooka
1042bdf6e0b0Spooka /*ARGSUSED*/
1043bdf6e0b0Spooka int
p2k_node_remove(struct puffs_usermount * pu,puffs_cookie_t opc,puffs_cookie_t targ,const struct puffs_cn * pcn)10443fd391abSpooka p2k_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc,
10453fd391abSpooka puffs_cookie_t targ, const struct puffs_cn *pcn)
1046bdf6e0b0Spooka {
1047bdf6e0b0Spooka
10485290e6c8Spooka return do_nukenode(opc, targ, pcn, RUMP_VOP_REMOVE);
1049bdf6e0b0Spooka }
1050bdf6e0b0Spooka
1051bdf6e0b0Spooka /*ARGSUSED*/
1052bdf6e0b0Spooka int
p2k_node_link(struct puffs_usermount * pu,puffs_cookie_t opc,puffs_cookie_t targ,const struct puffs_cn * pcn)10533fd391abSpooka p2k_node_link(struct puffs_usermount *pu, puffs_cookie_t opc,
10543fd391abSpooka puffs_cookie_t targ, const struct puffs_cn *pcn)
1055bdf6e0b0Spooka {
10565290e6c8Spooka struct vnode *dvp = OPC2VP(opc);
1057bdf6e0b0Spooka struct componentname *cn;
1058bdf6e0b0Spooka int rv;
1059bdf6e0b0Spooka
10609670fcafSpooka cn = makecn(pcn);
10615290e6c8Spooka RUMP_VOP_LOCK(dvp, LK_EXCLUSIVE);
1062bf3992afSpooka rump_pub_vp_incref(dvp);
10635290e6c8Spooka rv = RUMP_VOP_LINK(dvp, OPC2VP(targ), cn);
106446e71c7dSriastradh rump_pub_vp_rele(dvp);
106546e71c7dSriastradh RUMP_VOP_UNLOCK(dvp);
10669670fcafSpooka freecn(cn);
1067bdf6e0b0Spooka
1068bdf6e0b0Spooka return rv;
1069bdf6e0b0Spooka }
1070bdf6e0b0Spooka
1071bdf6e0b0Spooka /*ARGSUSED*/
1072bdf6e0b0Spooka int
p2k_node_rename(struct puffs_usermount * pu,puffs_cookie_t src_dir,puffs_cookie_t src,const struct puffs_cn * pcn_src,puffs_cookie_t targ_dir,puffs_cookie_t targ,const struct puffs_cn * pcn_targ)10733fd391abSpooka p2k_node_rename(struct puffs_usermount *pu,
10743fd391abSpooka puffs_cookie_t src_dir, puffs_cookie_t src,
10753fd391abSpooka const struct puffs_cn *pcn_src,
10763fd391abSpooka puffs_cookie_t targ_dir, puffs_cookie_t targ,
1077bdf6e0b0Spooka const struct puffs_cn *pcn_targ)
1078bdf6e0b0Spooka {
10795290e6c8Spooka struct vnode *dvp, *vp, *tdvp, *tvp = NULL;
1080bdf6e0b0Spooka struct componentname *cn_src, *cn_targ;
1081bdf6e0b0Spooka int rv;
1082bdf6e0b0Spooka
10839670fcafSpooka cn_src = makecn(pcn_src);
10849670fcafSpooka cn_targ = makecn(pcn_targ);
10855290e6c8Spooka
10865290e6c8Spooka dvp = OPC2VP(src_dir);
10875290e6c8Spooka vp = OPC2VP(src);
10885290e6c8Spooka tdvp = OPC2VP(targ_dir);
10895290e6c8Spooka if (targ) {
10905290e6c8Spooka tvp = OPC2VP(targ);
10915290e6c8Spooka }
10925290e6c8Spooka
1093bf3992afSpooka rump_pub_vp_incref(dvp);
1094bf3992afSpooka rump_pub_vp_incref(vp);
10955290e6c8Spooka RUMP_VOP_LOCK(tdvp, LK_EXCLUSIVE);
1096bf3992afSpooka rump_pub_vp_incref(tdvp);
10975290e6c8Spooka if (tvp) {
10985290e6c8Spooka RUMP_VOP_LOCK(tvp, LK_EXCLUSIVE);
1099bf3992afSpooka rump_pub_vp_incref(tvp);
11005290e6c8Spooka }
11015290e6c8Spooka rv = RUMP_VOP_RENAME(dvp, vp, cn_src, tdvp, tvp, cn_targ);
11025290e6c8Spooka assert(RUMP_VOP_ISLOCKED(tdvp) == 0);
11035290e6c8Spooka if (tvp) {
11045290e6c8Spooka assert(RUMP_VOP_ISLOCKED(tvp) == 0);
11055290e6c8Spooka }
11069670fcafSpooka freecn(cn_src);
11079670fcafSpooka freecn(cn_targ);
1108bdf6e0b0Spooka
1109bdf6e0b0Spooka return rv;
1110bdf6e0b0Spooka }
1111bdf6e0b0Spooka
1112bdf6e0b0Spooka /*ARGSUSED*/
1113bdf6e0b0Spooka int
p2k_node_mkdir(struct puffs_usermount * pu,puffs_cookie_t opc,struct puffs_newinfo * pni,const struct puffs_cn * pcn,const struct vattr * vap)11143fd391abSpooka p2k_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc,
11153fd391abSpooka struct puffs_newinfo *pni, const struct puffs_cn *pcn,
11163fd391abSpooka const struct vattr *vap)
1117bdf6e0b0Spooka {
1118bdf6e0b0Spooka
11195290e6c8Spooka return do_makenode(pu, opc, pni, pcn, vap, NULL, RUMP_VOP_MKDIR, NULL);
1120bdf6e0b0Spooka }
1121bdf6e0b0Spooka
1122bdf6e0b0Spooka /*ARGSUSED*/
1123bdf6e0b0Spooka int
p2k_node_rmdir(struct puffs_usermount * pu,puffs_cookie_t opc,puffs_cookie_t targ,const struct puffs_cn * pcn)11243fd391abSpooka p2k_node_rmdir(struct puffs_usermount *pu, puffs_cookie_t opc,
11253fd391abSpooka puffs_cookie_t targ, const struct puffs_cn *pcn)
1126bdf6e0b0Spooka {
1127bdf6e0b0Spooka
11285290e6c8Spooka return do_nukenode(opc, targ, pcn, RUMP_VOP_RMDIR);
1129bdf6e0b0Spooka }
1130bdf6e0b0Spooka
1131bdf6e0b0Spooka /*ARGSUSED*/
1132bdf6e0b0Spooka int
p2k_node_symlink(struct puffs_usermount * pu,puffs_cookie_t opc,struct puffs_newinfo * pni,const struct puffs_cn * pcn,const struct vattr * vap,const char * link_target)11333fd391abSpooka p2k_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc,
11345290e6c8Spooka struct puffs_newinfo *pni, const struct puffs_cn *pcn,
1135bdf6e0b0Spooka const struct vattr *vap, const char *link_target)
1136bdf6e0b0Spooka {
1137bdf6e0b0Spooka
11385290e6c8Spooka return do_makenode(pu, opc, pni, pcn, vap,
11395290e6c8Spooka __UNCONST(link_target), NULL, RUMP_VOP_SYMLINK);
1140bdf6e0b0Spooka }
1141bdf6e0b0Spooka
1142bdf6e0b0Spooka /*ARGSUSED*/
1143bdf6e0b0Spooka int
p2k_node_readdir(struct puffs_usermount * pu,puffs_cookie_t opc,struct dirent * dent,off_t * readoff,size_t * reslen,const struct puffs_cred * pcr,int * eofflag,off_t * cookies,size_t * ncookies)11443fd391abSpooka p2k_node_readdir(struct puffs_usermount *pu, puffs_cookie_t opc,
11453fd391abSpooka struct dirent *dent, off_t *readoff, size_t *reslen,
11463fd391abSpooka const struct puffs_cred *pcr, int *eofflag,
11473fd391abSpooka off_t *cookies, size_t *ncookies)
1148bdf6e0b0Spooka {
11495290e6c8Spooka struct vnode *vp = OPC2VP(opc);
11502734e549Spooka struct kauth_cred *cred;
1151bdf6e0b0Spooka struct uio *uio;
1152bdf6e0b0Spooka off_t *vop_cookies;
1153bdf6e0b0Spooka int vop_ncookies;
1154bdf6e0b0Spooka int rv;
1155bdf6e0b0Spooka
1156bdf6e0b0Spooka cred = cred_create(pcr);
1157bf3992afSpooka uio = rump_pub_uio_setup(dent, *reslen, *readoff, RUMPUIO_READ);
11585290e6c8Spooka RUMP_VOP_LOCK(vp, LK_SHARED);
1159bdf6e0b0Spooka if (cookies) {
11605290e6c8Spooka rv = RUMP_VOP_READDIR(vp, uio, cred, eofflag,
1161bdf6e0b0Spooka &vop_cookies, &vop_ncookies);
1162bdf6e0b0Spooka memcpy(cookies, vop_cookies, vop_ncookies * sizeof(*cookies));
1163bdf6e0b0Spooka *ncookies = vop_ncookies;
1164bdf6e0b0Spooka free(vop_cookies);
1165bdf6e0b0Spooka } else {
11665290e6c8Spooka rv = RUMP_VOP_READDIR(vp, uio, cred, eofflag, NULL, NULL);
1167bdf6e0b0Spooka }
11681423e65bShannken RUMP_VOP_UNLOCK(vp);
1169bdf6e0b0Spooka if (rv == 0) {
1170bf3992afSpooka *reslen = rump_pub_uio_getresid(uio);
1171bf3992afSpooka *readoff = rump_pub_uio_getoff(uio);
1172bdf6e0b0Spooka }
1173bf3992afSpooka rump_pub_uio_free(uio);
1174bdf6e0b0Spooka cred_destroy(cred);
1175bdf6e0b0Spooka
1176bdf6e0b0Spooka return rv;
1177bdf6e0b0Spooka }
1178bdf6e0b0Spooka
1179bdf6e0b0Spooka /*ARGSUSED*/
1180bdf6e0b0Spooka int
p2k_node_readlink(struct puffs_usermount * pu,puffs_cookie_t opc,const struct puffs_cred * pcr,char * linkname,size_t * linklen)11813fd391abSpooka p2k_node_readlink(struct puffs_usermount *pu, puffs_cookie_t opc,
1182bdf6e0b0Spooka const struct puffs_cred *pcr, char *linkname, size_t *linklen)
1183bdf6e0b0Spooka {
11845290e6c8Spooka struct vnode *vp = OPC2VP(opc);
11852734e549Spooka struct kauth_cred *cred;
1186bdf6e0b0Spooka struct uio *uio;
1187bdf6e0b0Spooka int rv;
1188bdf6e0b0Spooka
1189bdf6e0b0Spooka cred = cred_create(pcr);
1190bf3992afSpooka uio = rump_pub_uio_setup(linkname, *linklen, 0, RUMPUIO_READ);
11915290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
11925290e6c8Spooka rv = RUMP_VOP_READLINK(vp, uio, cred);
11931423e65bShannken RUMP_VOP_UNLOCK(vp);
1194bf3992afSpooka *linklen -= rump_pub_uio_free(uio);
1195bdf6e0b0Spooka cred_destroy(cred);
1196bdf6e0b0Spooka
1197bdf6e0b0Spooka return rv;
1198bdf6e0b0Spooka }
1199bdf6e0b0Spooka
1200bdf6e0b0Spooka /*ARGSUSED*/
1201bdf6e0b0Spooka int
p2k_node_read(struct puffs_usermount * pu,puffs_cookie_t opc,uint8_t * buf,off_t offset,size_t * resid,const struct puffs_cred * pcr,int ioflag)12023fd391abSpooka p2k_node_read(struct puffs_usermount *pu, puffs_cookie_t opc,
1203bdf6e0b0Spooka uint8_t *buf, off_t offset, size_t *resid,
1204bdf6e0b0Spooka const struct puffs_cred *pcr, int ioflag)
1205bdf6e0b0Spooka {
12065290e6c8Spooka struct vnode *vp = OPC2VP(opc);
12072734e549Spooka struct kauth_cred *cred;
1208bdf6e0b0Spooka struct uio *uio;
1209bdf6e0b0Spooka int rv;
1210bdf6e0b0Spooka
1211bdf6e0b0Spooka cred = cred_create(pcr);
1212bf3992afSpooka uio = rump_pub_uio_setup(buf, *resid, offset, RUMPUIO_READ);
12135290e6c8Spooka RUMP_VOP_LOCK(vp, LK_SHARED);
12145290e6c8Spooka rv = RUMP_VOP_READ(vp, uio, ioflag, cred);
12151423e65bShannken RUMP_VOP_UNLOCK(vp);
1216bf3992afSpooka *resid = rump_pub_uio_free(uio);
1217bdf6e0b0Spooka cred_destroy(cred);
1218bdf6e0b0Spooka
1219bdf6e0b0Spooka return rv;
1220bdf6e0b0Spooka }
1221bdf6e0b0Spooka
1222bdf6e0b0Spooka /*ARGSUSED*/
1223bdf6e0b0Spooka int
p2k_node_write(struct puffs_usermount * pu,puffs_cookie_t opc,uint8_t * buf,off_t offset,size_t * resid,const struct puffs_cred * pcr,int ioflag)12243fd391abSpooka p2k_node_write(struct puffs_usermount *pu, puffs_cookie_t opc,
1225bdf6e0b0Spooka uint8_t *buf, off_t offset, size_t *resid,
1226bdf6e0b0Spooka const struct puffs_cred *pcr, int ioflag)
1227bdf6e0b0Spooka {
12285290e6c8Spooka struct vnode *vp = OPC2VP(opc);
12292734e549Spooka struct kauth_cred *cred;
1230bdf6e0b0Spooka struct uio *uio;
1231bdf6e0b0Spooka int rv;
1232bdf6e0b0Spooka
12335290e6c8Spooka /* "deadfs" */
12345290e6c8Spooka if (!vp)
12355290e6c8Spooka return 0;
12365290e6c8Spooka
1237bdf6e0b0Spooka cred = cred_create(pcr);
1238bf3992afSpooka uio = rump_pub_uio_setup(buf, *resid, offset, RUMPUIO_WRITE);
12395290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
12405290e6c8Spooka rv = RUMP_VOP_WRITE(vp, uio, ioflag, cred);
12411423e65bShannken RUMP_VOP_UNLOCK(vp);
1242bf3992afSpooka *resid = rump_pub_uio_free(uio);
1243bdf6e0b0Spooka cred_destroy(cred);
1244bdf6e0b0Spooka
1245bdf6e0b0Spooka return rv;
1246bdf6e0b0Spooka }
1247bdf6e0b0Spooka
124855a23816Spooka /*ARGSUSED*/
124955a23816Spooka int
p2k_node_pathconf(struct puffs_usermount * pu,puffs_cookie_t opc,int name,register_t * retval)12501cfb9937Spooka p2k_node_pathconf(struct puffs_usermount *pu, puffs_cookie_t opc,
1251388dad17Spooka int name, register_t *retval)
12521cfb9937Spooka {
12531cfb9937Spooka struct vnode *vp = OPC2VP(opc);
12541cfb9937Spooka int rv;
12551cfb9937Spooka
12561cfb9937Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1257388dad17Spooka rv = RUMP_VOP_PATHCONF(vp, name, retval);
12581423e65bShannken RUMP_VOP_UNLOCK(vp);
12591cfb9937Spooka
12601cfb9937Spooka return rv;
12611cfb9937Spooka }
12621cfb9937Spooka
12631cfb9937Spooka /*ARGSUSED*/
12641cfb9937Spooka int
p2k_node_getextattr(struct puffs_usermount * pu,puffs_cookie_t opc,int attrnamespace,const char * attrname,size_t * attrsize,uint8_t * attr,size_t * resid,const struct puffs_cred * pcr)126555a23816Spooka p2k_node_getextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
126655a23816Spooka int attrnamespace, const char *attrname, size_t *attrsize,
126755a23816Spooka uint8_t *attr, size_t *resid, const struct puffs_cred *pcr)
126855a23816Spooka {
126955a23816Spooka struct vnode *vp = OPC2VP(opc);
127055a23816Spooka struct kauth_cred *cred;
127155a23816Spooka struct uio *uio;
127255a23816Spooka int rv;
127355a23816Spooka
127455a23816Spooka if (attr)
127555a23816Spooka uio = rump_pub_uio_setup(attr, *resid, 0, RUMPUIO_READ);
127655a23816Spooka else
127755a23816Spooka uio = NULL;
127855a23816Spooka
127955a23816Spooka cred = cred_create(pcr);
128055a23816Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
128155a23816Spooka rv = RUMP_VOP_GETEXTATTR(vp, attrnamespace, attrname, uio,
128255a23816Spooka attrsize, cred);
12831423e65bShannken RUMP_VOP_UNLOCK(vp);
128455a23816Spooka cred_destroy(cred);
128555a23816Spooka
128655a23816Spooka if (uio)
128755a23816Spooka *resid = rump_pub_uio_free(uio);
128855a23816Spooka
128955a23816Spooka return rv;
129055a23816Spooka }
129155a23816Spooka
129255a23816Spooka /*ARGSUSED*/
129355a23816Spooka int
p2k_node_setextattr(struct puffs_usermount * pu,puffs_cookie_t opc,int attrnamespace,const char * attrname,uint8_t * attr,size_t * resid,const struct puffs_cred * pcr)129455a23816Spooka p2k_node_setextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
129555a23816Spooka int attrnamespace, const char *attrname,
129655a23816Spooka uint8_t *attr, size_t *resid, const struct puffs_cred *pcr)
129755a23816Spooka {
129855a23816Spooka struct vnode *vp = OPC2VP(opc);
129955a23816Spooka struct kauth_cred *cred;
130055a23816Spooka struct uio *uio;
130155a23816Spooka int rv;
130255a23816Spooka
130355a23816Spooka if (attr)
130455a23816Spooka uio = rump_pub_uio_setup(attr, *resid, 0, RUMPUIO_READ);
130555a23816Spooka else
130655a23816Spooka uio = NULL;
130755a23816Spooka
130855a23816Spooka cred = cred_create(pcr);
130955a23816Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
131055a23816Spooka rv = RUMP_VOP_SETEXTATTR(vp, attrnamespace, attrname, uio, cred);
13111423e65bShannken RUMP_VOP_UNLOCK(vp);
131255a23816Spooka cred_destroy(cred);
131355a23816Spooka
131455a23816Spooka if (uio)
131555a23816Spooka *resid = rump_pub_uio_free(uio);
131655a23816Spooka
131755a23816Spooka return rv;
131855a23816Spooka }
131955a23816Spooka
132055a23816Spooka /*ARGSUSED*/
132155a23816Spooka int
p2k_node_listextattr(struct puffs_usermount * pu,puffs_cookie_t opc,int attrnamespace,size_t * attrsize,uint8_t * attrs,size_t * resid,int flags,const struct puffs_cred * pcr)132255a23816Spooka p2k_node_listextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
1323be95d607Smanu int attrnamespace, size_t *attrsize, uint8_t *attrs,
1324be95d607Smanu size_t *resid, int flags, const struct puffs_cred *pcr)
132555a23816Spooka {
132655a23816Spooka struct vnode *vp = OPC2VP(opc);
132755a23816Spooka struct kauth_cred *cred;
132855a23816Spooka struct uio *uio;
132955a23816Spooka int rv;
133055a23816Spooka
133155a23816Spooka if (attrs)
133255a23816Spooka uio = rump_pub_uio_setup(attrs, *resid, 0, RUMPUIO_READ);
133355a23816Spooka else
133455a23816Spooka uio = NULL;
133555a23816Spooka
133655a23816Spooka cred = cred_create(pcr);
133755a23816Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1338be95d607Smanu rv = RUMP_VOP_LISTEXTATTR(vp, attrnamespace, uio, attrsize,
1339be95d607Smanu flags, cred);
13401423e65bShannken RUMP_VOP_UNLOCK(vp);
134155a23816Spooka cred_destroy(cred);
134255a23816Spooka
134355a23816Spooka if (uio)
134455a23816Spooka *resid = rump_pub_uio_free(uio);
134555a23816Spooka
134655a23816Spooka return rv;
134755a23816Spooka }
134855a23816Spooka
134955a23816Spooka /*ARGSUSED*/
135055a23816Spooka int
p2k_node_deleteextattr(struct puffs_usermount * pu,puffs_cookie_t opc,int attrnamespace,const char * attrname,const struct puffs_cred * pcr)135155a23816Spooka p2k_node_deleteextattr(struct puffs_usermount *pu, puffs_cookie_t opc,
135255a23816Spooka int attrnamespace, const char *attrname, const struct puffs_cred *pcr)
135355a23816Spooka {
135455a23816Spooka struct vnode *vp = OPC2VP(opc);
135555a23816Spooka struct kauth_cred *cred;
135655a23816Spooka int rv;
135755a23816Spooka
135855a23816Spooka cred = cred_create(pcr);
135955a23816Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
136055a23816Spooka rv = RUMP_VOP_DELETEEXTATTR(vp, attrnamespace, attrname, cred);
13611423e65bShannken RUMP_VOP_UNLOCK(vp);
136255a23816Spooka cred_destroy(cred);
136355a23816Spooka
136455a23816Spooka return rv;
136555a23816Spooka }
136655a23816Spooka
13675290e6c8Spooka /* the kernel releases its last reference here */
1368bdf6e0b0Spooka int
p2k_node_inactive(struct puffs_usermount * pu,puffs_cookie_t opc)13693fd391abSpooka p2k_node_inactive(struct puffs_usermount *pu, puffs_cookie_t opc)
1370bdf6e0b0Spooka {
137130df4c9fSpooka struct p2k_mount *p2m = puffs_getspecific(pu);
13725290e6c8Spooka struct p2k_node *p2n = opc;
13735290e6c8Spooka struct vnode *vp = OPC2VP(opc);
1374a37ccec1Spooka bool recycle = false;
1375bdf6e0b0Spooka int rv;
1376bdf6e0b0Spooka
13775290e6c8Spooka /* deadfs */
13785290e6c8Spooka if (!vp)
13795290e6c8Spooka return 0;
13805290e6c8Spooka
13815290e6c8Spooka /*
13825290e6c8Spooka * Flush all cached vnode pages from the rump kernel -- they
138313777d56Spooka * are kept in puffs for all things that matter. However,
138413777d56Spooka * don't do this for tmpfs (vnodes are backed by an aobj), since that
138513777d56Spooka * would cause us to clear the backing storage leaving us without
138613777d56Spooka * a way to regain the data from "stable storage".
13875290e6c8Spooka */
138813777d56Spooka if (!p2m->p2m_imtmpfsman) {
1389d2a0ebb6Sad rump_pub_vp_vmobjlock(vp, 1);
139013777d56Spooka RUMP_VOP_PUTPAGES(vp, 0, 0,
139113777d56Spooka PGO_ALLPAGES|PGO_CLEANIT|PGO_FREE);
139213777d56Spooka }
13935290e6c8Spooka
13945290e6c8Spooka /*
13955290e6c8Spooka * Ok, this is where we get nasty. We pretend the vnode is
13965290e6c8Spooka * inactive and already tell the file system that. However,
13975290e6c8Spooka * we are allowed to pretend it also grows a reference immediately
13985290e6c8Spooka * after per vget(), so this does not do harm. Cheap trick, but ...
13995290e6c8Spooka *
14005290e6c8Spooka * If the file system thinks the inode is done for, we release
14015290e6c8Spooka * our reference and clear all knowledge of the vnode. If,
14025290e6c8Spooka * however, the inode is still active, we retain our reference
14035290e6c8Spooka * until reclaim, since puffs might be flushing out some data
14045290e6c8Spooka * later.
14055290e6c8Spooka */
14065290e6c8Spooka RUMP_VOP_LOCK(vp, LK_EXCLUSIVE);
1407bdf6e0b0Spooka rv = RUMP_VOP_INACTIVE(vp, &recycle);
140887fb3229Sriastradh RUMP_VOP_UNLOCK(vp);
14095290e6c8Spooka if (recycle) {
1410bdf6e0b0Spooka puffs_setback(puffs_cc_getcc(pu), PUFFS_SETBACK_NOREF_N1);
1411bf3992afSpooka rump_pub_vp_rele(p2n->p2n_vp);
14125290e6c8Spooka p2n->p2n_vp = NULL;
14135290e6c8Spooka }
1414bdf6e0b0Spooka
1415bdf6e0b0Spooka return rv;
1416bdf6e0b0Spooka }
1417bdf6e0b0Spooka
1418bdf6e0b0Spooka /*ARGSUSED*/
1419bdf6e0b0Spooka int
p2k_node_reclaim(struct puffs_usermount * pu,puffs_croissant_t opc)14203fd391abSpooka p2k_node_reclaim(struct puffs_usermount *pu, puffs_croissant_t opc)
1421bdf6e0b0Spooka {
14225290e6c8Spooka struct p2k_node *p2n = opc;
1423bdf6e0b0Spooka
14245290e6c8Spooka if (p2n->p2n_vp) {
1425bf3992afSpooka rump_pub_vp_rele(p2n->p2n_vp);
14265290e6c8Spooka p2n->p2n_vp = NULL;
14275290e6c8Spooka }
14285290e6c8Spooka
14295290e6c8Spooka freep2n(p2n);
1430bdf6e0b0Spooka return 0;
1431bdf6e0b0Spooka }
1432