diff --git a/sys/rump/fs/bin/fsconsole/fsconsole.c b/sys/rump/fs/bin/fsconsole/fsconsole.c index 9cf681aa3b3e..14d6b910f262 100644 --- a/sys/rump/fs/bin/fsconsole/fsconsole.c +++ b/sys/rump/fs/bin/fsconsole/fsconsole.c @@ -1,4 +1,4 @@ -/* $NetBSD: fsconsole.c,v 1.6 2007/09/02 13:55:27 pooka Exp $ */ +/* $NetBSD: fsconsole.c,v 1.7 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -53,6 +53,7 @@ main(int argc, char *argv[]) uint8_t buf[8192]; struct ukfs *fs; struct fscons_args args; + off_t off; #ifdef __NetBSD__ struct dirent *dent; #endif @@ -73,7 +74,8 @@ main(int argc, char *argv[]) printf("got fs at %p\n", fs); - rv = ukfs_getdents(fs, "/", 0, buf, sizeof(buf)); + off = 0; + rv = ukfs_getdents(fs, "/", &off, buf, sizeof(buf)); printf("rv %d\n", rv); if (rv == -1) rv = 0; @@ -121,7 +123,8 @@ main(int argc, char *argv[]) buf[rv] = '\0'; printf("readlink rv %d result \"%s\"\n", rv, buf); - rv = ukfs_getdents(fs, "/etc", 0, buf, sizeof(buf)); + off = 0; + rv = ukfs_getdents(fs, "/etc", &off, buf, sizeof(buf)); printf("rv %d\n", rv); if (rv == -1) rv = 0; diff --git a/sys/rump/fs/lib/libp2k/p2k.c b/sys/rump/fs/lib/libp2k/p2k.c index de918dbc58a7..8dbc26dba159 100644 --- a/sys/rump/fs/lib/libp2k/p2k.c +++ b/sys/rump/fs/lib/libp2k/p2k.c @@ -1,4 +1,4 @@ -/* $NetBSD: p2k.c,v 1.41 2008/01/28 11:52:38 pooka Exp $ */ +/* $NetBSD: p2k.c,v 1.42 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -222,7 +222,7 @@ p2k_fs_statvfs(struct puffs_usermount *pu, struct statvfs *sbp) { struct mount *mp = puffs_getspecific(pu); - return VFS_STATVFS(mp, sbp); + return rump_vfs_statvfs(mp, sbp); } int @@ -251,13 +251,12 @@ p2k_fs_unmount(struct puffs_usermount *pu, int flags) * against the root cookie, which might change (blah2). */ rump_vp_recycle_nokidding(rvp); - rv = VFS_UNMOUNT(mp, flags); + rv = rump_vfs_unmount(mp, flags); if (rv) { int rv2; - rv2 = VFS_ROOT(mp, &rvp2); + rv2 = rump_vfs_root(mp, &rvp2, 0); assert(rv2 == 0 && rvp == rvp2); - VUL(rvp); } return rv; } @@ -271,7 +270,7 @@ p2k_fs_sync(struct puffs_usermount *pu, int waitfor, int rv; cred = cred_create(pcr); - rv = VFS_SYNC(mp, waitfor, (kauth_cred_t)cred); + rv = rump_vfs_sync(mp, waitfor, (kauth_cred_t)cred); cred_destroy(cred); rump_bioops_sync(); @@ -290,7 +289,7 @@ p2k_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize, dev_t rdev; int rv; - rv = VFS_FHTOVP(mp, fid, &vp); + rv = rump_vfs_fhtovp(mp, fid, &vp); if (rv) return rv; @@ -309,7 +308,7 @@ p2k_fs_nodetofh(struct puffs_usermount *pu, void *cookie, void *fid, { struct vnode *vp = cookie; - return VFS_VPTOFH(vp, fid, fidsize); + return rump_vfs_vptofh(vp, fid, fidsize); } int diff --git a/sys/rump/fs/lib/libukfs/ukfs.c b/sys/rump/fs/lib/libukfs/ukfs.c index 446b469224f1..f396125783af 100644 --- a/sys/rump/fs/lib/libukfs/ukfs.c +++ b/sys/rump/fs/lib/libukfs/ukfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: ukfs.c,v 1.18 2008/01/27 20:01:29 pooka Exp $ */ +/* $NetBSD: ukfs.c,v 1.19 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -35,6 +35,8 @@ #include #include +#include +#include #include #include @@ -87,6 +89,7 @@ struct ukfs * ukfs_mount(const char *vfsname, const char *devpath, const char *mountpath, int mntflags, void *arg, size_t alen) { + extern struct vnode *rootvnode; /* XXX */ struct ukfs *fs = NULL; struct vfsops *vfsops; struct mount *mp; @@ -116,6 +119,12 @@ ukfs_mount(const char *vfsname, const char *devpath, const char *mountpath, fs->ukfs_mp = mp; rump_fakeblk_deregister(devpath); + /* + * XXX: this is not threadsafe handling with multiple ukfs in + * the same process. use cwdi? + */ + rootvnode = ukfs_getrvp(fs); + out: if (rv) { if (fs && fs->ukfs_mp) @@ -136,6 +145,7 @@ ukfs_release(struct ukfs *fs, int dounmount) if (dounmount) { rv = rump_vfs_sync(fs->ukfs_mp, 1, NULL); + rump_vp_recycle_nokidding(ukfs_getrvp(fs)); rv |= rump_vfs_unmount(fs->ukfs_mp, 0); assert(rv == 0); } @@ -152,111 +162,26 @@ ukfs_release(struct ukfs *fs, int dounmount) #define VUL(a) rump_vp_unlock(a) #define AUL(a) assert(rump_vp_islocked(a) == 0) +/* free willy */ void -ukfs_ll_recycle(struct vnode *vp) +ukfs_ll_rele(struct vnode *vp) { - bool recycle; - /* XXXXX */ - if (vp == NULL || rump_vp_getref(vp)) - return; - - VLE(vp); - RUMP_VOP_FSYNC(vp, NULL, 0, 0, 0); - RUMP_VOP_INACTIVE(vp, &recycle); - rump_vp_recycle_nokidding(vp); -} - -/* - * simplo (well, horrid) namei. doesn't do symlinks & anything else - * hard, though. (ok, ok, it's a mess, it's a messssss!) - * - * XXX: maybe I should just try running the kernel namei(), although - * it would require a wrapping due to the name collision in - * librump vfs.c - */ -int -ukfs_ll_namei(struct vnode *rvp, const char **pnp, u_long op, - struct vnode **dvpp, struct vnode **vpp) -{ - struct vnode *dvp, *vp; - struct componentname *cnp; - const char *pn, *p_next, *p_end; - size_t pnlen; - u_long flags; - int rv; - - /* remove trailing slashes */ - pn = *pnp; - assert(strlen(pn) > 0); - p_end = pn + strlen(pn)-1; - while (*p_end == '/' && p_end != *pnp) - p_end--; - - /* caller wanted root? */ - if (p_end == *pnp) { - if (dvpp) - *dvpp = rvp; - if (vpp) - *vpp = rvp; - - *pnp = p_end; - return 0; - } - - dvp = NULL; - vp = rvp; - p_end++; - for (;;) { - while (*pn == '/') - pn++; - assert(*pn != '\0'); - - flags = 0; - dvp = vp; - vp = NULL; - - p_next = strchr(pn, '/'); - if (p_next == NULL || p_next == p_end) { - p_next = p_end; - flags |= RUMP_NAMEI_ISLASTCN; - } - pnlen = p_next - pn; - - if (pnlen == 2 && strcmp(pn, "..") == 0) - flags |= RUMP_NAMEI_ISDOTDOT; - - VLE(dvp); - cnp = rump_makecn(op, flags, pn, pnlen, RUMPCRED_SUSER, curlwp); - rv = RUMP_VOP_LOOKUP(dvp, &vp, cnp); - rump_freecn(cnp, RUMPCN_ISLOOKUP | RUMPCN_FREECRED); - VUL(dvp); - if (rv == 0) - VUL(vp); - - if (!((flags & RUMP_NAMEI_ISLASTCN) && dvpp)) - ukfs_ll_recycle(dvp); - - if (rv || (flags & RUMP_NAMEI_ISLASTCN)) - break; - - pn += pnlen; - } - assert((rv != 0) || (flags & RUMP_NAMEI_ISLASTCN)); - if (vp && vpp == NULL) - ukfs_ll_recycle(vp); - - if (dvpp) - *dvpp = dvp; - if (vpp) - *vpp = vp; - *pnp = pn; - - return rv; + rump_vp_rele(vp); } int -ukfs_getdents(struct ukfs *ukfs, const char *dirname, off_t off, +ukfs_ll_namei(struct ukfs *ukfs, uint32_t op, uint32_t flags, const char *name, + struct vnode **dvpp, struct vnode **vpp, struct componentname **cnpp) +{ + + /* XXX: rootvnode dance */ + + return rump_namei(op, flags, name, dvpp, vpp, cnpp); +} + +int +ukfs_getdents(struct ukfs *ukfs, const char *dirname, off_t *off, uint8_t *buf, size_t bufsize) { struct uio *uio; @@ -264,20 +189,19 @@ ukfs_getdents(struct ukfs *ukfs, const char *dirname, off_t off, size_t resid; int rv, eofflag; - rv = ukfs_ll_namei(ukfs_getrvp(ukfs), &dirname, RUMP_NAMEI_LOOKUP, - NULL, &vp); + rv = ukfs_ll_namei(ukfs, RUMP_NAMEI_LOOKUP, NAMEI_LOCKLEAF, dirname, + NULL, &vp, NULL); if (rv) goto out; - uio = rump_uio_setup(buf, bufsize, off, RUMPUIO_READ); - VLE(vp); + uio = rump_uio_setup(buf, bufsize, *off, RUMPUIO_READ); rv = RUMP_VOP_READDIR(vp, uio, NULL, &eofflag, NULL, NULL); VUL(vp); + *off = rump_uio_getoff(uio); resid = rump_uio_free(uio); + rump_vp_rele(vp); out: - ukfs_ll_recycle(vp); - if (rv) { errno = rv; return -1; @@ -297,30 +221,31 @@ readwrite(struct ukfs *ukfs, const char *filename, off_t off, size_t resid; int rv; - rv = ukfs_ll_namei(ukfs_getrvp(ukfs), &filename, RUMP_NAMEI_LOOKUP, - NULL, &vp); + rv = ukfs_ll_namei(ukfs, RUMP_NAMEI_LOOKUP, 0, filename, + NULL, &vp, NULL); if (rv) goto out; uio = rump_uio_setup(buf, bufsize, off, rw); - VLS(vp); switch (ukrw) { case UKFS_READ: + VLS(vp); rv = RUMP_VOP_READ(vp, uio, 0, NULL); break; case UKFS_WRITE: + VLE(vp); rv = RUMP_VOP_WRITE(vp, uio, 0, NULL); break; case UKFS_READLINK: + VLE(vp); rv = RUMP_VOP_READLINK(vp, uio, NULL); break; } VUL(vp); + ukfs_ll_rele(vp); resid = rump_uio_free(uio); out: - ukfs_ll_recycle(vp); - if (rv) { errno = rv; return -1; @@ -354,16 +279,27 @@ create(struct ukfs *ukfs, const char *filename, mode_t mode, struct componentname *cnp; struct vnode *dvp = NULL, *vp = NULL; struct vattr *vap; - int rv; + int rv, flags; int (*do_fn)(struct vnode *, struct vnode **, struct componentname *, struct vattr *); - rv = ukfs_ll_namei(ukfs_getrvp(ukfs), &filename, RUMP_NAMEI_CREATE, - &dvp, NULL); - if (rv == 0) - rv = EEXIST; - if (rv != EJUSTRETURN) + flags = NAMEI_LOCKPARENT; + if (vt == VDIR) { + flags |= NAMEI_CREATEDIR; + } + rv = ukfs_ll_namei(ukfs, RUMP_NAMEI_CREATE, NAMEI_LOCKPARENT, filename, + &dvp, &vp, &cnp); + if (rv) { goto out; + } + + if (vp) { + rv = EEXIST; + VUL(dvp); + ukfs_ll_rele(dvp); + ukfs_ll_rele(vp); + goto out; + } switch (vt) { case VDIR: @@ -378,6 +314,7 @@ create(struct ukfs *ukfs, const char *filename, mode_t mode, do_fn = RUMP_VOP_MKNOD; break; default: + ukfs_ll_rele(dvp); rv = EINVAL; goto out; } @@ -386,22 +323,17 @@ create(struct ukfs *ukfs, const char *filename, mode_t mode, rump_vattr_settype(vap, vt); rump_vattr_setmode(vap, mode); rump_vattr_setrdev(vap, dev); - cnp = rump_makecn(RUMP_NAMEI_CREATE, - RUMP_NAMEI_HASBUF|RUMP_NAMEI_SAVENAME, filename, - strlen(filename), RUMPCRED_SUSER, curlwp); - VLE(dvp); rv = do_fn(dvp, &vp, cnp, vap); - if (rv == 0) + if (rv == 0) { VUL(vp); + ukfs_ll_rele(vp); + } rump_freecn(cnp, RUMPCN_FREECRED); rump_vattr_free(vap); out: - ukfs_ll_recycle(dvp); - ukfs_ll_recycle(vp); - if (rv) { errno = rv; return -1; @@ -423,7 +355,8 @@ ukfs_create(struct ukfs *ukfs, const char *filename, mode_t mode) vt = VSOCK; break; default: - return EINVAL; + errno = EINVAL; + return -1; } return create(ukfs, filename, mode, vt, /*XXX*/(dev_t)-1); @@ -442,17 +375,66 @@ ukfs_mknod(struct ukfs *ukfs, const char *filename, mode_t mode, dev_t dev) vt = VCHR; break; default: - return EINVAL; + errno = EINVAL; + return -1; } return create(ukfs, filename, mode, vt, dev); } +static int +builddirs(struct ukfs *ukfs, const char *filename, mode_t mode) +{ + char *f1, *f2; + int rv; + + /* does it exist? */ + rv = ukfs_ll_namei(ukfs, RUMP_NAMEI_LOOKUP, 0, filename, + NULL, NULL, NULL); + if (rv == 0) + return 0; + + /* If we didn't find it, create dirs by path games */ + f1 = f2 = strdup(filename); + if (!f1) { + errno = ENOMEM; + return -1; + } + + for (;;) { + /* find next component */ + f2 += strspn(f2, "/"); + f2 += strcspn(f2, "/"); + *f2 = '\0'; + + rv = ukfs_mkdir(ukfs, f1, 0777, false); + if (rv == EEXIST) + rv = 0; + if (rv) + break; + + if (!*f2) + break; + *f2 = '/'; + } + + free(f1); + if (rv) { + errno = rv; + return -1; + } + return 0; +} + int -ukfs_mkdir(struct ukfs *ukfs, const char *filename, mode_t mode) +ukfs_mkdir(struct ukfs *ukfs, const char *filename, mode_t mode, bool p) { - return create(ukfs, filename, mode, VDIR, (dev_t)-1); + if (p) { + return builddirs(ukfs, filename, mode); + } else { + return create(ukfs, filename, mode, VDIR, (dev_t)-1); + } } static int @@ -463,22 +445,15 @@ doremove(struct ukfs *ukfs, const char *filename, struct vnode *dvp = NULL, *vp = NULL; int rv; - rv = ukfs_ll_namei(ukfs_getrvp(ukfs), &filename, RUMP_NAMEI_DELETE, - &dvp, &vp); + rv = ukfs_ll_namei(ukfs, RUMP_NAMEI_DELETE, + NAMEI_LOCKPARENT | NAMEI_LOCKLEAF, filename, &dvp, &vp, &cnp); if (rv) goto out; - cnp = rump_makecn(RUMP_NAMEI_DELETE, 0, filename, - strlen(filename), RUMPCRED_SUSER, curlwp); - VLE(dvp); - VLE(vp); rv = do_fn(dvp, vp, cnp); - rump_freecn(cnp, RUMPCN_FREECRED); + rump_freecn(cnp, RUMPCN_FREECRED | RUMPCN_HASNTBUF); /* XXX */ out: - ukfs_ll_recycle(dvp); - ukfs_ll_recycle(vp); - if (rv) { errno = rv; return -1; @@ -508,32 +483,24 @@ ukfs_link(struct ukfs *ukfs, const char *filename, const char *f_create) struct componentname *cnp; int rv; - rv = ukfs_ll_namei(ukfs_getrvp(ukfs), &filename, RUMP_NAMEI_LOOKUP, - NULL, &vp); + rv = ukfs_ll_namei(ukfs, RUMP_NAMEI_LOOKUP, NAMEI_LOCKLEAF, filename, + NULL, &vp, NULL); if (rv) goto out; + VUL(vp); - rump_vp_incref(vp); /* XXX kludge of the year */ - rv = ukfs_ll_namei(ukfs_getrvp(ukfs), &f_create, RUMP_NAMEI_CREATE, - &dvp, NULL); - rump_vp_decref(vp); /* XXX */ - - if (rv == 0) - rv = EEXIST; - if (rv != EJUSTRETURN) + rv = ukfs_ll_namei(ukfs, RUMP_NAMEI_CREATE, NAMEI_LOCKPARENT, f_create, + &dvp, NULL, &cnp); + if (rv) { + VUL(dvp); + ukfs_ll_rele(dvp); goto out; + } - cnp = rump_makecn(RUMP_NAMEI_CREATE, - RUMP_NAMEI_HASBUF | RUMP_NAMEI_SAVENAME, - f_create, strlen(f_create), RUMPCRED_SUSER, curlwp); - VLE(dvp); rv = RUMP_VOP_LINK(dvp, vp, cnp); rump_freecn(cnp, RUMPCN_FREECRED); out: - ukfs_ll_recycle(dvp); - ukfs_ll_recycle(vp); - if (rv) { errno = rv; return -1; @@ -550,32 +517,32 @@ ukfs_symlink(struct ukfs *ukfs, const char *filename, char *linkname) struct vattr *vap; int rv; - rv = ukfs_ll_namei(ukfs_getrvp(ukfs), &filename, RUMP_NAMEI_CREATE, - &dvp, NULL); - if (rv == 0) - rv = EEXIST; - if (rv != EJUSTRETURN) + rv = ukfs_ll_namei(ukfs, RUMP_NAMEI_CREATE, NAMEI_LOCKPARENT, filename, + &dvp, &vp, &cnp); + if (rv) { goto out; + } + + if (vp) { + VUL(dvp); + ukfs_ll_rele(dvp); + ukfs_ll_rele(vp); + goto out; + } vap = rump_vattr_init(); rump_vattr_setmode(vap, UKFS_MODE_DEFAULT); rump_vattr_settype(vap, VLNK); - cnp = rump_makecn(RUMP_NAMEI_CREATE, - RUMP_NAMEI_HASBUF|RUMP_NAMEI_SAVENAME, filename, - strlen(filename), RUMPCRED_SUSER, curlwp); - - VLE(dvp); rv = RUMP_VOP_SYMLINK(dvp, &vp, cnp, vap, linkname); - if (rv == 0) + if (rv == 0) { VUL(vp); + ukfs_ll_rele(vp); + } rump_freecn(cnp, RUMPCN_FREECRED); rump_vattr_free(vap); out: - ukfs_ll_recycle(dvp); - ukfs_ll_recycle(vp); - if (rv) { errno = rv; return -1; @@ -592,3 +559,12 @@ ukfs_readlink(struct ukfs *ukfs, const char *filename, return readwrite(ukfs, filename, 0, (uint8_t *)linkbuf, buflen, RUMPUIO_READ, UKFS_READLINK); } + +/* XXX: need vfs_syscalls.h, but it's in the kernel headers */ +int do_sys_rename(const char *, const char *, enum uio_seg, int); +int +ukfs_rename(struct ukfs *ukfs, const char *from, const char *to) +{ + + return do_sys_rename(from, to, UIO_SYSSPACE, 0); +} diff --git a/sys/rump/fs/lib/libukfs/ukfs.h b/sys/rump/fs/lib/libukfs/ukfs.h index e32eb107f707..0ba100e31cd8 100644 --- a/sys/rump/fs/lib/libukfs/ukfs.h +++ b/sys/rump/fs/lib/libukfs/ukfs.h @@ -1,4 +1,4 @@ -/* $NetBSD: ukfs.h,v 1.6 2007/09/18 19:59:21 pooka Exp $ */ +/* $NetBSD: ukfs.h,v 1.7 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -34,22 +34,25 @@ #include #include +#include #include struct vnode; - struct ukfs; +#include "rump.h" + int ukfs_init(void); struct ukfs *ukfs_mount(const char *, const char *, const char *, int, void *, size_t); void ukfs_release(struct ukfs *, int); -int ukfs_ll_namei(struct vnode *, const char **, u_long, - struct vnode **, struct vnode **); -void ukfs_ll_recycle(struct vnode *); +int ukfs_ll_namei(struct ukfs *, uint32_t, uint32_t, const char *, + struct vnode **, struct vnode **, + struct componentname **); +void ukfs_ll_rele(struct vnode *); -int ukfs_getdents(struct ukfs *, const char *, off_t, +int ukfs_getdents(struct ukfs *, const char *, off_t *, uint8_t *, size_t); ssize_t ukfs_read(struct ukfs *, const char *, off_t, uint8_t *, size_t); @@ -58,7 +61,7 @@ ssize_t ukfs_write(struct ukfs *, const char *, off_t, ssize_t ukfs_readlink(struct ukfs *, const char *, char *, size_t); int ukfs_create(struct ukfs *, const char *, mode_t); -int ukfs_mkdir(struct ukfs *, const char *, mode_t); +int ukfs_mkdir(struct ukfs *, const char *, mode_t, bool); int ukfs_mknod(struct ukfs *, const char *, mode_t, dev_t); int ukfs_symlink(struct ukfs *, const char *, char *); @@ -66,6 +69,7 @@ int ukfs_remove(struct ukfs *, const char *); int ukfs_rmdir(struct ukfs *, const char *); int ukfs_link(struct ukfs *, const char *, const char *); +int ukfs_rename(struct ukfs *, const char *, const char *); struct mount *ukfs_getmp(struct ukfs *); struct vnode *ukfs_getrvp(struct ukfs *); diff --git a/sys/rump/librump/rumpkern/Makefile b/sys/rump/librump/rumpkern/Makefile index 8b53fcc4471b..abf50e26f6ab 100644 --- a/sys/rump/librump/rumpkern/Makefile +++ b/sys/rump/librump/rumpkern/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.29 2008/01/28 15:48:18 pooka Exp $ +# $NetBSD: Makefile,v 1.30 2008/03/11 10:50:16 pooka Exp $ # .include @@ -22,8 +22,8 @@ SRCS+= fstrans_stub.c misc_stub.c pmap_stub.c vfsops_stub.c SRCS+= clock_subr.c kern_descrip.c kern_lock.c kern_stub.c param.c \ subr_bufq.c subr_hash.c subr_prf2.c subr_specificdata.c \ subr_time.c subr_workqueue.c sys_generic.c vfs_bio.c \ - vfs_cache.c vfs_getcwd.c vfs_init.c vfs_lookup.c vfs_subr.c \ - vfs_subr2.c vfs_vnops.c vnode_if.c + vfs_cache.c vfs_getcwd.c vfs_hooks.c vfs_init.c vfs_lookup.c \ + vfs_subr.c vfs_subr2.c vfs_vnops.c vfs_syscalls.c vnode_if.c # sys/miscfs SRCS+= genfs_vfsops.c genfs_vnops.c sync_subr.c @@ -43,7 +43,7 @@ OBJS+= ${RUMPUSEROBJDIR}/rumpuser.o ${RUMPUSEROBJDIR}/rumpuser_pth.o CPPFLAGS+= -I${NETBSDSRCDIR}/sys -I${NETBSDSRCDIR}/common/include \ -I${NETBSDSRCDIR}/sys/rump/librump/rumpuser \ -I${.CURDIR}/opt -DMAXUSERS=32 -#CPPFLAGS+= -DRUMP_WITHOUT_THREADS +CPPFLAGS+= -DRUMP_WITHOUT_THREADS CFLAGS+= -Wno-pointer-sign diff --git a/sys/rump/librump/rumpkern/auth.c b/sys/rump/librump/rumpkern/auth.c index 633ced71076a..b42f724bc680 100644 --- a/sys/rump/librump/rumpkern/auth.c +++ b/sys/rump/librump/rumpkern/auth.c @@ -1,4 +1,4 @@ -/* $NetBSD: auth.c,v 1.6 2008/01/24 22:41:08 pooka Exp $ */ +/* $NetBSD: auth.c,v 1.7 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -64,7 +64,8 @@ void rump_cred_destroy(kauth_cred_t cred) { - kmem_free(cred, sizeof(struct kauth_cred)); + if (cred != RUMPCRED_SUSER) + kmem_free(cred, sizeof(struct kauth_cred)); } int @@ -99,6 +100,13 @@ kauth_cred_getuid(kauth_cred_t cred) return kauth_cred_geteuid(cred); } +gid_t +kauth_cred_getgid(kauth_cred_t cred) +{ + + return cred == RUMPCRED_SUSER ? 0 : cred->cr_gid; +} + uid_t kauth_cred_geteuid(kauth_cred_t cred) { @@ -173,6 +181,26 @@ kauth_cred_to_uucred(struct uucred *uucred, const kauth_cred_t cred) cred->cr_ngroups * sizeof(gid_t)); } +void +kauth_cred_seteuid(kauth_cred_t cred, uid_t uid) +{ + + if (cred == RUMPCRED_SUSER) + return; + + cred->cr_uid = uid; +} + +void +kauth_cred_setegid(kauth_cred_t cred, gid_t gid) +{ + + if (cred == RUMPCRED_SUSER) + return; + + cred->cr_gid = gid; +} + void kauth_cred_hold(kauth_cred_t cred) { @@ -193,3 +221,10 @@ kauth_cred_get() return curlwp->l_cred; } + +kauth_cred_t +kauth_cred_dup(kauth_cred_t cred) +{ + + panic("%s: unimplemented", __func__); +} diff --git a/sys/rump/librump/rumpkern/emul.c b/sys/rump/librump/rumpkern/emul.c index 2f6c4569ae72..785b009fadef 100644 --- a/sys/rump/librump/rumpkern/emul.c +++ b/sys/rump/librump/rumpkern/emul.c @@ -1,4 +1,4 @@ -/* $NetBSD: emul.c,v 1.29 2008/02/15 23:36:26 ad Exp $ */ +/* $NetBSD: emul.c,v 1.30 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -67,10 +67,8 @@ int physmem = 256*256; /* 256 * 1024*1024 / 4k, PAGE_SIZE not always set */ int doing_shutdown; int ncpu = 1; const int schedppq = 1; -int dovfsusermount = 1; int hardclock_ticks; -MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct"); MALLOC_DEFINE(M_UFSMNT, "UFS mount", "UFS mount structure"); MALLOC_DEFINE(M_TEMP, "temp", "misc. temporary data buffers"); MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory"); @@ -175,7 +173,7 @@ copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done) { strlcpy(kaddr, uaddr, len); - *done = strlen(kaddr); + *done = strlen(kaddr)+1; /* includes termination */ return 0; } diff --git a/sys/rump/librump/rumpkern/locks.c b/sys/rump/librump/rumpkern/locks.c index fcd0ae628b6b..0163285917be 100644 --- a/sys/rump/librump/rumpkern/locks.c +++ b/sys/rump/librump/rumpkern/locks.c @@ -1,4 +1,4 @@ -/* $NetBSD: locks.c,v 1.11 2008/01/30 10:22:02 ad Exp $ */ +/* $NetBSD: locks.c,v 1.12 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -67,13 +67,8 @@ mutex_spin_enter(kmutex_t *mtx) int mutex_tryenter(kmutex_t *mtx) { - int rv; - rv = rumpuser_mutex_tryenter(mtx->kmtx_mtx); - if (rv) - return 0; - else - return 1; + return rumpuser_mutex_tryenter(mtx->kmtx_mtx); } void diff --git a/sys/rump/librump/rumpkern/opt/fss.h b/sys/rump/librump/rumpkern/opt/fss.h new file mode 100644 index 000000000000..df1bbfd83cab --- /dev/null +++ b/sys/rump/librump/rumpkern/opt/fss.h @@ -0,0 +1 @@ +/* $NetBSD: fss.h,v 1.1 2008/03/11 10:50:16 pooka Exp $ */ diff --git a/sys/rump/librump/rumpkern/opt/opt_fileassoc.h b/sys/rump/librump/rumpkern/opt/opt_fileassoc.h new file mode 100644 index 000000000000..f4b2f99954c0 --- /dev/null +++ b/sys/rump/librump/rumpkern/opt/opt_fileassoc.h @@ -0,0 +1 @@ +/* $NetBSD: opt_fileassoc.h,v 1.1 2008/03/11 10:50:16 pooka Exp $ */ diff --git a/sys/rump/librump/rumpkern/rump.c b/sys/rump/librump/rumpkern/rump.c index d3c3db452421..6f3e53b31206 100644 --- a/sys/rump/librump/rumpkern/rump.c +++ b/sys/rump/librump/rumpkern/rump.c @@ -1,4 +1,4 @@ -/* $NetBSD: rump.c,v 1.35 2008/01/30 14:57:24 ad Exp $ */ +/* $NetBSD: rump.c,v 1.36 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -51,6 +52,7 @@ struct plimit rump_limits; kauth_cred_t rump_cred = RUMPCRED_SUSER; struct cpu_info rump_cpu; struct filedesc0 rump_filedesc0; +struct proclist allproc; kmutex_t rump_giantlock; @@ -82,6 +84,7 @@ rump_init() extern char hostname[]; extern size_t hostnamelen; extern kmutex_t rump_atomic_lock; + char buf[256]; struct proc *p; struct lwp *l; int error; @@ -91,6 +94,12 @@ rump_init() return; rump_inited = 1; + if (rumpuser_getenv("RUMP_NVNODES", buf, sizeof(buf), &error) == 0) { + desiredvnodes = strtoul(buf, NULL, 10); + } else { + desiredvnodes = 1<<16; + } + l = &lwp0; p = &rump_proc; p->p_stats = &rump_stats; @@ -102,6 +111,9 @@ rump_init() l->l_cred = rump_cred; l->l_proc = p; l->l_lid = 1; + + LIST_INSERT_HEAD(&allproc, p, p_list); + rw_init(&rump_cwdi.cwdi_lock); mutex_init(&rump_atomic_lock, MUTEX_DEFAULT, IPL_NONE); @@ -110,8 +122,8 @@ rump_init() rump_limits.pl_rlimit[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; rump_limits.pl_rlimit[RLIMIT_NOFILE].rlim_cur = RLIM_INFINITY; - /* should be "enough" */ syncdelay = 0; + dovfsusermount = 1; vfsinit(); bufinit(); @@ -151,6 +163,7 @@ rump_mnt_init(struct vfsops *vfsops, int mntflags) mp->mnt_flag = mntflags; TAILQ_INIT(&mp->mnt_vnodelist); rw_init(&mp->mnt_lock); + mutex_init(&mp->mnt_renamelock, MUTEX_DEFAULT, IPL_NONE); mp->mnt_refcnt = 1; mount_initspecific(mp); @@ -213,15 +226,61 @@ rump_freecn(struct componentname *cnp, int flags) if (flags & RUMPCN_FREECRED) rump_cred_destroy(cnp->cn_cred); - if (cnp->cn_flags & SAVENAME) { - if (flags & RUMPCN_ISLOOKUP || cnp->cn_flags & SAVESTART) + if ((flags & RUMPCN_HASNTBUF) == 0) { + if (cnp->cn_flags & SAVENAME) { + if (flags & RUMPCN_ISLOOKUP ||cnp->cn_flags & SAVESTART) + PNBUF_PUT(cnp->cn_pnbuf); + } else { PNBUF_PUT(cnp->cn_pnbuf); - } else { - PNBUF_PUT(cnp->cn_pnbuf); + } } kmem_free(cnp, sizeof(*cnp)); } +/* hey baby, what's your namei? */ +int +rump_namei(uint32_t op, uint32_t flags, const char *namep, + struct vnode **dvpp, struct vnode **vpp, struct componentname **cnpp) +{ + struct nameidata nd; + int rv; + + NDINIT(&nd, op, flags, UIO_SYSSPACE, namep); + rv = namei(&nd); + if (rv) + return rv; + + if (dvpp) { + KASSERT(flags & LOCKPARENT); + *dvpp = nd.ni_dvp; + } else { + KASSERT((flags & LOCKPARENT) == 0); + } + + if (vpp) { + *vpp = nd.ni_vp; + } else { + if (nd.ni_vp) { + if (flags & LOCKLEAF) + vput(nd.ni_vp); + else + vrele(nd.ni_vp); + } + } + + if (cnpp) { + struct componentname *cnp; + + cnp = kmem_alloc(sizeof(*cnp), KM_SLEEP); + memcpy(cnp, &nd.ni_cnd, sizeof(*cnp)); + *cnpp = cnp; + } else if (nd.ni_cnd.cn_flags & HASBUF) { + panic("%s: pathbuf mismatch", __func__); + } + + return rv; +} + static struct fakeblk * _rump_fakeblk_find(const char *path) { @@ -514,15 +573,12 @@ rump_vfs_root(struct mount *mp, struct vnode **vpp, int lock) return 0; } -/* XXX: statvfs is different from system to system */ -#if 0 int rump_vfs_statvfs(struct mount *mp, struct statvfs *sbp) { return VFS_STATVFS(mp, sbp); } -#endif int rump_vfs_sync(struct mount *mp, int wait, kauth_cred_t cred) diff --git a/sys/rump/librump/rumpkern/rump.h b/sys/rump/librump/rumpkern/rump.h index 190f2b40170d..6485c191c49f 100644 --- a/sys/rump/librump/rumpkern/rump.h +++ b/sys/rump/librump/rumpkern/rump.h @@ -1,4 +1,4 @@ -/* $NetBSD: rump.h,v 1.23 2008/01/27 20:01:29 pooka Exp $ */ +/* $NetBSD: rump.h,v 1.24 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -32,6 +32,7 @@ #include #include +#include struct mount; struct vnode; @@ -64,6 +65,10 @@ struct componentname *rump_makecn(u_long, u_long, const char *, size_t, void rump_freecn(struct componentname *, int); #define RUMPCN_ISLOOKUP 0x01 #define RUMPCN_FREECRED 0x02 +#define RUMPCN_HASNTBUF 0x04 +int rump_namei(uint32_t, uint32_t, const char *, + struct vnode **, struct vnode **, + struct componentname **); void rump_getvninfo(struct vnode *, enum vtype *, off_t * /*XXX*/, dev_t *); @@ -106,9 +111,7 @@ void rump_cred_destroy(kauth_cred_t); int rump_vfs_unmount(struct mount *, int); int rump_vfs_root(struct mount *, struct vnode **, int); -#if 0 int rump_vfs_statvfs(struct mount *, struct statvfs *); -#endif int rump_vfs_sync(struct mount *, int, kauth_cred_t); int rump_vfs_fhtovp(struct mount *, struct fid *, struct vnode **); int rump_vfs_vptofh(struct vnode *, struct fid *, size_t *); diff --git a/sys/rump/librump/rumpkern/vfs.c b/sys/rump/librump/rumpkern/vfs.c index eaa95391a756..d1832cb922c6 100644 --- a/sys/rump/librump/rumpkern/vfs.c +++ b/sys/rump/librump/rumpkern/vfs.c @@ -1,4 +1,4 @@ -/* $NetBSD: vfs.c,v 1.35 2008/01/30 09:50:24 ad Exp $ */ +/* $NetBSD: vfs.c,v 1.36 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -92,21 +92,6 @@ const struct vnodeopv_desc * const rump_opv_descs[] = { vnode_t *specfs_hash[SPECHSZ]; int (*mountroot)(void); -int -sys_sync(struct lwp *l, const void *v, register_t *rv) -{ - - panic("%s: unimplemented", __func__); -} - -int -dounmount(struct mount *mp, int flags, struct lwp *l) -{ - - VFS_UNMOUNT(mp, MNT_FORCE); - panic("control fd is dead"); -} - int vfs_stdextattrctl(struct mount *mp, int cmt, struct vnode *vp, int attrnamespace, const char *attrname) @@ -117,6 +102,20 @@ vfs_stdextattrctl(struct mount *mp, int cmt, struct vnode *vp, return EOPNOTSUPP; } +int +vfs_allocate_syncvnode(struct mount *mp) +{ + + panic("%s: unimplemented", __func__); +} + +void +vfs_deallocate_syncvnode(struct mount *mp) +{ + + panic("%s: unimplemented", __func__); +} + struct mount mnt_dummy; static struct vnode * @@ -220,7 +219,7 @@ int lf_advlock(struct vop_advlock_args *ap, struct lockf **head, off_t size) { - return 0; + panic("%s: unimplemented", __func__); } void diff --git a/sys/rump/librump/rumpkern/vm.c b/sys/rump/librump/rumpkern/vm.c index 641503d6875a..c3373ecc21ee 100644 --- a/sys/rump/librump/rumpkern/vm.c +++ b/sys/rump/librump/rumpkern/vm.c @@ -1,4 +1,4 @@ -/* $NetBSD: vm.c,v 1.29 2008/01/27 20:10:53 pooka Exp $ */ +/* $NetBSD: vm.c,v 1.30 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -539,14 +539,18 @@ void uvm_vnp_setsize(struct vnode *vp, voff_t newsize) { + mutex_enter(&vp->v_interlock); vp->v_size = vp->v_writesize = newsize; + mutex_exit(&vp->v_interlock); } void uvm_vnp_setwritesize(struct vnode *vp, voff_t newsize) { + mutex_enter(&vp->v_interlock); vp->v_writesize = newsize; + mutex_exit(&vp->v_interlock); } void diff --git a/sys/rump/librump/rumpuser/Makefile b/sys/rump/librump/rumpuser/Makefile index df6f628830c5..48cd62c9e8e4 100644 --- a/sys/rump/librump/rumpuser/Makefile +++ b/sys/rump/librump/rumpuser/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.5 2008/01/24 22:41:08 pooka Exp $ +# $NetBSD: Makefile,v 1.6 2008/03/11 10:50:16 pooka Exp $ # .include @@ -7,7 +7,7 @@ LIB= rumpuser SRCS= rumpuser.c rumpuser_pth.c -#CPPFLAGS+= -DRUMP_WITHOUT_THREADS +CPPFLAGS+= -DRUMP_WITHOUT_THREADS RUMPKERNEL= no diff --git a/sys/rump/librump/rumpuser/rumpuser.c b/sys/rump/librump/rumpuser/rumpuser.c index 37da07e4c1c2..9063b17e7024 100644 --- a/sys/rump/librump/rumpuser/rumpuser.c +++ b/sys/rump/librump/rumpuser/rumpuser.c @@ -1,4 +1,4 @@ -/* $NetBSD: rumpuser.c,v 1.13 2008/02/19 20:37:09 ad Exp $ */ +/* $NetBSD: rumpuser.c,v 1.14 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -246,6 +246,13 @@ rumpuser_gettimeofday(struct timeval *tv, int *error) DOCALL(int, gettimeofday(tv, NULL)); } +int +rumpuser_getenv(const char *name, char *buf, size_t blen, int *error) +{ + + DOCALL(int, getenv_r(name, buf, blen)); +} + int rumpuser_gethostname(char *name, size_t namelen, int *error) { diff --git a/sys/rump/librump/rumpuser/rumpuser.h b/sys/rump/librump/rumpuser/rumpuser.h index 53e7a2195e53..903ae815499e 100644 --- a/sys/rump/librump/rumpuser/rumpuser.h +++ b/sys/rump/librump/rumpuser/rumpuser.h @@ -1,4 +1,4 @@ -/* $NetBSD: rumpuser.h,v 1.15 2008/02/15 23:36:27 ad Exp $ */ +/* $NetBSD: rumpuser.h,v 1.16 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -58,6 +58,7 @@ void rumpuser_read_bio(int, void *, size_t, off_t, void *); void rumpuser_write_bio(int, const void *, size_t, off_t, void *); int rumpuser_gettimeofday(struct timeval *, int *); +int rumpuser_getenv(const char *, char *, size_t, int *); uint16_t rumpuser_bswap16(uint16_t); uint32_t rumpuser_bswap32(uint32_t); diff --git a/sys/rump/librump/rumpuser/rumpuser_pth.c b/sys/rump/librump/rumpuser/rumpuser_pth.c index 1c726721f747..6122644e7168 100644 --- a/sys/rump/librump/rumpuser/rumpuser_pth.c +++ b/sys/rump/librump/rumpuser/rumpuser_pth.c @@ -1,4 +1,4 @@ -/* $NetBSD: rumpuser_pth.c,v 1.11 2008/01/30 09:50:24 ad Exp $ */ +/* $NetBSD: rumpuser_pth.c,v 1.12 2008/03/11 10:50:16 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -36,6 +36,7 @@ #include #include #include +#include #include "rumpuser.h" @@ -43,6 +44,15 @@ static pthread_key_t curlwpkey; static pthread_key_t isintr; #define NOFAIL(a) do {if (!(a)) abort();} while (/*CONSTCOND*/0) +#define NOFAIL_ERRNO(a) \ +do { \ + int fail_rv = (a); \ + if (fail_rv) { \ + printf("panic: rumpuser fatal failure %d (%s)\n", \ + fail_rv, strerror(fail_rv)); \ + abort(); \ + } \ +} while (/*CONSTCOND*/0) struct rumpuser_mtx { pthread_mutex_t pthmtx; @@ -69,11 +79,11 @@ iothread(void *arg) { struct rumpuser_aio *rua; - NOFAIL(pthread_mutex_lock(&rua_mtx.pthmtx) == 0); + NOFAIL_ERRNO(pthread_mutex_lock(&rua_mtx.pthmtx)); for (;;) { while (rua_head == rua_tail) { - NOFAIL(pthread_cond_wait(&rua_cv.pthcv, - &rua_mtx.pthmtx) == 0); + NOFAIL_ERRNO(pthread_cond_wait(&rua_cv.pthcv, + &rua_mtx.pthmtx)); } rua = rua_aios[rua_tail]; @@ -88,7 +98,7 @@ iothread(void *arg) rua->rua_dlen, rua->rua_off, rua->rua_bp); free(rua); - NOFAIL(pthread_mutex_lock(&rua_mtx.pthmtx) == 0); + NOFAIL_ERRNO(pthread_mutex_lock(&rua_mtx.pthmtx)); } } #endif /* RUMP_WITHOUT_THREADS */ @@ -140,7 +150,7 @@ void rumpuser_mutex_init(struct rumpuser_mtx **mtx) { NOFAIL(*mtx = malloc(sizeof(struct rumpuser_mtx))); - NOFAIL(pthread_mutex_init(&((*mtx)->pthmtx), NULL) == 0); + NOFAIL_ERRNO(pthread_mutex_init(&((*mtx)->pthmtx), NULL)); } void @@ -152,7 +162,7 @@ rumpuser_mutex_recursive_init(struct rumpuser_mtx **mtx) pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); NOFAIL(*mtx = malloc(sizeof(struct rumpuser_mtx))); - NOFAIL(pthread_mutex_init(&((*mtx)->pthmtx), &mattr) == 0); + NOFAIL_ERRNO(pthread_mutex_init(&((*mtx)->pthmtx), &mattr)); pthread_mutexattr_destroy(&mattr); } @@ -161,7 +171,7 @@ void rumpuser_mutex_enter(struct rumpuser_mtx *mtx) { - NOFAIL(pthread_mutex_lock(&mtx->pthmtx) == 0); + NOFAIL_ERRNO(pthread_mutex_lock(&mtx->pthmtx)); } int @@ -175,14 +185,14 @@ void rumpuser_mutex_exit(struct rumpuser_mtx *mtx) { - NOFAIL(pthread_mutex_unlock(&mtx->pthmtx) == 0); + NOFAIL_ERRNO(pthread_mutex_unlock(&mtx->pthmtx)); } void rumpuser_mutex_destroy(struct rumpuser_mtx *mtx) { - NOFAIL(pthread_mutex_destroy(&mtx->pthmtx) == 0); + NOFAIL_ERRNO(pthread_mutex_destroy(&mtx->pthmtx)); free(mtx); } @@ -198,7 +208,7 @@ rumpuser_rw_init(struct rumpuser_rw **rw) { NOFAIL(*rw = malloc(sizeof(struct rumpuser_rw))); - NOFAIL(pthread_rwlock_init(&((*rw)->pthrw), NULL) == 0); + NOFAIL_ERRNO(pthread_rwlock_init(&((*rw)->pthrw), NULL)); } void @@ -206,9 +216,9 @@ rumpuser_rw_enter(struct rumpuser_rw *rw, int write) { if (write) - NOFAIL(pthread_rwlock_wrlock(&rw->pthrw) == 0); + NOFAIL_ERRNO(pthread_rwlock_wrlock(&rw->pthrw)); else - NOFAIL(pthread_rwlock_rdlock(&rw->pthrw) == 0); + NOFAIL_ERRNO(pthread_rwlock_rdlock(&rw->pthrw)); } int @@ -225,14 +235,14 @@ void rumpuser_rw_exit(struct rumpuser_rw *rw) { - NOFAIL(pthread_rwlock_unlock(&rw->pthrw) == 0); + NOFAIL_ERRNO(pthread_rwlock_unlock(&rw->pthrw)); } void rumpuser_rw_destroy(struct rumpuser_rw *rw) { - NOFAIL(pthread_rwlock_destroy(&rw->pthrw) == 0); + NOFAIL_ERRNO(pthread_rwlock_destroy(&rw->pthrw)); free(rw); } @@ -262,14 +272,14 @@ rumpuser_cv_init(struct rumpuser_cv **cv) { NOFAIL(*cv = malloc(sizeof(struct rumpuser_cv))); - NOFAIL(pthread_cond_init(&((*cv)->pthcv), NULL) == 0); + NOFAIL_ERRNO(pthread_cond_init(&((*cv)->pthcv), NULL)); } void rumpuser_cv_destroy(struct rumpuser_cv *cv) { - NOFAIL(pthread_cond_destroy(&cv->pthcv) == 0); + NOFAIL_ERRNO(pthread_cond_destroy(&cv->pthcv)); free(cv); } @@ -277,7 +287,7 @@ void rumpuser_cv_wait(struct rumpuser_cv *cv, struct rumpuser_mtx *mtx) { - NOFAIL(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx) == 0); + NOFAIL_ERRNO(pthread_cond_wait(&cv->pthcv, &mtx->pthmtx)); } int @@ -306,14 +316,14 @@ void rumpuser_cv_signal(struct rumpuser_cv *cv) { - NOFAIL(pthread_cond_signal(&cv->pthcv) == 0); + NOFAIL_ERRNO(pthread_cond_signal(&cv->pthcv)); } void rumpuser_cv_broadcast(struct rumpuser_cv *cv) { - NOFAIL(pthread_cond_broadcast(&cv->pthcv) == 0); + NOFAIL_ERRNO(pthread_cond_broadcast(&cv->pthcv)); } /*