xref: /minix3/sys/fs/puffs/puffs_subr.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: puffs_subr.c,v 1.67 2014/11/10 18:46:33 maxv Exp $	*/
284d9c625SLionel Sambuc 
384d9c625SLionel Sambuc /*
484d9c625SLionel Sambuc  * Copyright (c) 2006, 2007  Antti Kantee.  All Rights Reserved.
584d9c625SLionel Sambuc  *
684d9c625SLionel Sambuc  * Development of this software was supported by the
784d9c625SLionel Sambuc  * Ulla Tuominen Foundation and the Finnish Cultural Foundation.
884d9c625SLionel Sambuc  *
984d9c625SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
1084d9c625SLionel Sambuc  * modification, are permitted provided that the following conditions
1184d9c625SLionel Sambuc  * are met:
1284d9c625SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
1384d9c625SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
1484d9c625SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
1584d9c625SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
1684d9c625SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
1784d9c625SLionel Sambuc  *
1884d9c625SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
1984d9c625SLionel Sambuc  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2084d9c625SLionel Sambuc  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2184d9c625SLionel Sambuc  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2284d9c625SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2384d9c625SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2484d9c625SLionel Sambuc  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2584d9c625SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2684d9c625SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2784d9c625SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2884d9c625SLionel Sambuc  * SUCH DAMAGE.
2984d9c625SLionel Sambuc  */
3084d9c625SLionel Sambuc 
3184d9c625SLionel Sambuc #include <sys/cdefs.h>
32*0a6a1f1dSLionel Sambuc __KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.67 2014/11/10 18:46:33 maxv Exp $");
3384d9c625SLionel Sambuc 
3484d9c625SLionel Sambuc #include <sys/param.h>
3584d9c625SLionel Sambuc #include <sys/buf.h>
3684d9c625SLionel Sambuc #include <sys/mount.h>
3784d9c625SLionel Sambuc #include <sys/namei.h>
3884d9c625SLionel Sambuc #include <sys/poll.h>
3984d9c625SLionel Sambuc #include <sys/proc.h>
4084d9c625SLionel Sambuc 
4184d9c625SLionel Sambuc #include <fs/puffs/puffs_msgif.h>
4284d9c625SLionel Sambuc #include <fs/puffs/puffs_sys.h>
4384d9c625SLionel Sambuc 
4484d9c625SLionel Sambuc #ifdef PUFFSDEBUG
4584d9c625SLionel Sambuc int puffsdebug;
4684d9c625SLionel Sambuc #endif
4784d9c625SLionel Sambuc 
4884d9c625SLionel Sambuc void
puffs_makecn(struct puffs_kcn * pkcn,struct puffs_kcred * pkcr,const struct componentname * cn,int full)4984d9c625SLionel Sambuc puffs_makecn(struct puffs_kcn *pkcn, struct puffs_kcred *pkcr,
5084d9c625SLionel Sambuc 	const struct componentname *cn, int full)
5184d9c625SLionel Sambuc {
5284d9c625SLionel Sambuc 
5384d9c625SLionel Sambuc 	pkcn->pkcn_nameiop = cn->cn_nameiop;
5484d9c625SLionel Sambuc 	pkcn->pkcn_flags = cn->cn_flags;
5584d9c625SLionel Sambuc 
5684d9c625SLionel Sambuc 	if (full) {
5784d9c625SLionel Sambuc 		(void)strcpy(pkcn->pkcn_name, cn->cn_nameptr);
5884d9c625SLionel Sambuc 	} else {
5984d9c625SLionel Sambuc 		(void)memcpy(pkcn->pkcn_name, cn->cn_nameptr, cn->cn_namelen);
6084d9c625SLionel Sambuc 		pkcn->pkcn_name[cn->cn_namelen] = '\0';
6184d9c625SLionel Sambuc 	}
6284d9c625SLionel Sambuc 	pkcn->pkcn_namelen = cn->cn_namelen;
6384d9c625SLionel Sambuc 	pkcn->pkcn_consume = 0;
6484d9c625SLionel Sambuc 
6584d9c625SLionel Sambuc 	puffs_credcvt(pkcr, cn->cn_cred);
6684d9c625SLionel Sambuc }
6784d9c625SLionel Sambuc 
6884d9c625SLionel Sambuc /*
6984d9c625SLionel Sambuc  * Convert given credentials to struct puffs_kcred for userspace.
7084d9c625SLionel Sambuc  */
7184d9c625SLionel Sambuc void
puffs_credcvt(struct puffs_kcred * pkcr,const kauth_cred_t cred)7284d9c625SLionel Sambuc puffs_credcvt(struct puffs_kcred *pkcr, const kauth_cred_t cred)
7384d9c625SLionel Sambuc {
7484d9c625SLionel Sambuc 
7584d9c625SLionel Sambuc 	memset(pkcr, 0, sizeof(struct puffs_kcred));
7684d9c625SLionel Sambuc 
7784d9c625SLionel Sambuc 	if (cred == NOCRED || cred == FSCRED) {
7884d9c625SLionel Sambuc 		pkcr->pkcr_type = PUFFCRED_TYPE_INTERNAL;
7984d9c625SLionel Sambuc 		if (cred == NOCRED)
8084d9c625SLionel Sambuc 			pkcr->pkcr_internal = PUFFCRED_CRED_NOCRED;
8184d9c625SLionel Sambuc 		if (cred == FSCRED)
8284d9c625SLionel Sambuc 			pkcr->pkcr_internal = PUFFCRED_CRED_FSCRED;
8384d9c625SLionel Sambuc  	} else {
8484d9c625SLionel Sambuc 		pkcr->pkcr_type = PUFFCRED_TYPE_UUC;
8584d9c625SLionel Sambuc 		kauth_cred_to_uucred(&pkcr->pkcr_uuc, cred);
8684d9c625SLionel Sambuc 	}
8784d9c625SLionel Sambuc }
8884d9c625SLionel Sambuc 
8984d9c625SLionel Sambuc void
puffs_parkdone_asyncbioread(struct puffs_mount * pmp,struct puffs_req * preq,void * arg)9084d9c625SLionel Sambuc puffs_parkdone_asyncbioread(struct puffs_mount *pmp,
9184d9c625SLionel Sambuc 	struct puffs_req *preq, void *arg)
9284d9c625SLionel Sambuc {
9384d9c625SLionel Sambuc 	struct puffs_vnmsg_read *read_msg = (void *)preq;
9484d9c625SLionel Sambuc 	struct buf *bp = arg;
9584d9c625SLionel Sambuc 	size_t moved;
9684d9c625SLionel Sambuc 
9784d9c625SLionel Sambuc 	DPRINTF(("%s\n", __func__));
9884d9c625SLionel Sambuc 
9984d9c625SLionel Sambuc 	bp->b_error = checkerr(pmp, preq->preq_rv, __func__);
10084d9c625SLionel Sambuc 	if (bp->b_error == 0) {
10184d9c625SLionel Sambuc 		if (read_msg->pvnr_resid > bp->b_bcount) {
10284d9c625SLionel Sambuc 			puffs_senderr(pmp, PUFFS_ERR_READ, E2BIG,
10384d9c625SLionel Sambuc 			    "resid grew", preq->preq_cookie);
10484d9c625SLionel Sambuc 			bp->b_error = E2BIG;
10584d9c625SLionel Sambuc 		} else {
10684d9c625SLionel Sambuc 			moved = bp->b_bcount - read_msg->pvnr_resid;
10784d9c625SLionel Sambuc 			bp->b_resid = read_msg->pvnr_resid;
10884d9c625SLionel Sambuc 
10984d9c625SLionel Sambuc 			memcpy(bp->b_data, read_msg->pvnr_data, moved);
11084d9c625SLionel Sambuc 		}
11184d9c625SLionel Sambuc 	}
11284d9c625SLionel Sambuc 
11384d9c625SLionel Sambuc 	biodone(bp);
11484d9c625SLionel Sambuc }
11584d9c625SLionel Sambuc 
11684d9c625SLionel Sambuc void
puffs_parkdone_asyncbiowrite(struct puffs_mount * pmp,struct puffs_req * preq,void * arg)11784d9c625SLionel Sambuc puffs_parkdone_asyncbiowrite(struct puffs_mount *pmp,
11884d9c625SLionel Sambuc 	struct puffs_req *preq, void *arg)
11984d9c625SLionel Sambuc {
12084d9c625SLionel Sambuc 	struct puffs_vnmsg_write *write_msg = (void *)preq;
12184d9c625SLionel Sambuc 	struct buf *bp = arg;
12284d9c625SLionel Sambuc 
12384d9c625SLionel Sambuc 	DPRINTF(("%s\n", __func__));
12484d9c625SLionel Sambuc 
12584d9c625SLionel Sambuc 	bp->b_error = checkerr(pmp, preq->preq_rv, __func__);
12684d9c625SLionel Sambuc 	if (bp->b_error == 0) {
12784d9c625SLionel Sambuc 		if (write_msg->pvnr_resid > bp->b_bcount) {
12884d9c625SLionel Sambuc 			puffs_senderr(pmp, PUFFS_ERR_WRITE, E2BIG,
12984d9c625SLionel Sambuc 			    "resid grew", preq->preq_cookie);
13084d9c625SLionel Sambuc 			bp->b_error = E2BIG;
13184d9c625SLionel Sambuc 		} else {
13284d9c625SLionel Sambuc 			bp->b_resid = write_msg->pvnr_resid;
13384d9c625SLionel Sambuc 		}
13484d9c625SLionel Sambuc 	}
13584d9c625SLionel Sambuc 
13684d9c625SLionel Sambuc 	biodone(bp);
13784d9c625SLionel Sambuc }
13884d9c625SLionel Sambuc 
13984d9c625SLionel Sambuc /* XXX: userspace can leak kernel resources */
14084d9c625SLionel Sambuc void
puffs_parkdone_poll(struct puffs_mount * pmp,struct puffs_req * preq,void * arg)14184d9c625SLionel Sambuc puffs_parkdone_poll(struct puffs_mount *pmp, struct puffs_req *preq, void *arg)
14284d9c625SLionel Sambuc {
14384d9c625SLionel Sambuc 	struct puffs_vnmsg_poll *poll_msg = (void *)preq;
14484d9c625SLionel Sambuc 	struct puffs_node *pn = arg;
14584d9c625SLionel Sambuc 	int revents, error;
14684d9c625SLionel Sambuc 
14784d9c625SLionel Sambuc 	error = checkerr(pmp, preq->preq_rv, __func__);
14884d9c625SLionel Sambuc 	if (error)
14984d9c625SLionel Sambuc 		revents = poll_msg->pvnr_events;
15084d9c625SLionel Sambuc 	else
15184d9c625SLionel Sambuc 		revents = POLLERR;
15284d9c625SLionel Sambuc 
15384d9c625SLionel Sambuc 	mutex_enter(&pn->pn_mtx);
15484d9c625SLionel Sambuc 	pn->pn_revents |= revents;
15584d9c625SLionel Sambuc 	mutex_exit(&pn->pn_mtx);
15684d9c625SLionel Sambuc 
15784d9c625SLionel Sambuc 	selnotify(&pn->pn_sel, revents, 0);
15884d9c625SLionel Sambuc 
15984d9c625SLionel Sambuc 	puffs_releasenode(pn);
16084d9c625SLionel Sambuc }
16184d9c625SLionel Sambuc 
16284d9c625SLionel Sambuc void
puffs_mp_reference(struct puffs_mount * pmp)16384d9c625SLionel Sambuc puffs_mp_reference(struct puffs_mount *pmp)
16484d9c625SLionel Sambuc {
16584d9c625SLionel Sambuc 
16684d9c625SLionel Sambuc 	KASSERT(mutex_owned(&pmp->pmp_lock));
16784d9c625SLionel Sambuc 	pmp->pmp_refcount++;
16884d9c625SLionel Sambuc }
16984d9c625SLionel Sambuc 
17084d9c625SLionel Sambuc void
puffs_mp_release(struct puffs_mount * pmp)17184d9c625SLionel Sambuc puffs_mp_release(struct puffs_mount *pmp)
17284d9c625SLionel Sambuc {
17384d9c625SLionel Sambuc 
17484d9c625SLionel Sambuc 	KASSERT(mutex_owned(&pmp->pmp_lock));
17584d9c625SLionel Sambuc 	if (--pmp->pmp_refcount == 0)
17684d9c625SLionel Sambuc 		cv_broadcast(&pmp->pmp_refcount_cv);
17784d9c625SLionel Sambuc }
17884d9c625SLionel Sambuc 
17984d9c625SLionel Sambuc void
puffs_gop_size(struct vnode * vp,off_t size,off_t * eobp,int flags)18084d9c625SLionel Sambuc puffs_gop_size(struct vnode *vp, off_t size, off_t *eobp,
18184d9c625SLionel Sambuc 	int flags)
18284d9c625SLionel Sambuc {
18384d9c625SLionel Sambuc 
18484d9c625SLionel Sambuc 	*eobp = size;
18584d9c625SLionel Sambuc }
18684d9c625SLionel Sambuc 
18784d9c625SLionel Sambuc void
puffs_gop_markupdate(struct vnode * vp,int flags)18884d9c625SLionel Sambuc puffs_gop_markupdate(struct vnode *vp, int flags)
18984d9c625SLionel Sambuc {
19084d9c625SLionel Sambuc 	int uflags = 0;
19184d9c625SLionel Sambuc 
19284d9c625SLionel Sambuc 	if (flags & GOP_UPDATE_ACCESSED)
19384d9c625SLionel Sambuc 		uflags |= PUFFS_UPDATEATIME;
19484d9c625SLionel Sambuc 	if (flags & GOP_UPDATE_MODIFIED)
19584d9c625SLionel Sambuc 		uflags |= PUFFS_UPDATEMTIME;
19684d9c625SLionel Sambuc 
19784d9c625SLionel Sambuc 	puffs_updatenode(VPTOPP(vp), uflags, 0);
19884d9c625SLionel Sambuc }
19984d9c625SLionel Sambuc 
20084d9c625SLionel Sambuc void
puffs_senderr(struct puffs_mount * pmp,int type,int error,const char * str,puffs_cookie_t ck)20184d9c625SLionel Sambuc puffs_senderr(struct puffs_mount *pmp, int type, int error,
20284d9c625SLionel Sambuc 	const char *str, puffs_cookie_t ck)
20384d9c625SLionel Sambuc {
20484d9c625SLionel Sambuc 	struct puffs_msgpark *park;
20584d9c625SLionel Sambuc 	struct puffs_error *perr;
20684d9c625SLionel Sambuc 
20784d9c625SLionel Sambuc 	puffs_msgmem_alloc(sizeof(struct puffs_error), &park, (void *)&perr, 1);
20884d9c625SLionel Sambuc 	puffs_msg_setfaf(park);
20984d9c625SLionel Sambuc 	puffs_msg_setinfo(park, PUFFSOP_ERROR, type, ck);
21084d9c625SLionel Sambuc 
21184d9c625SLionel Sambuc 	perr->perr_error = error;
21284d9c625SLionel Sambuc 	strlcpy(perr->perr_str, str, sizeof(perr->perr_str));
21384d9c625SLionel Sambuc 
21484d9c625SLionel Sambuc 	puffs_msg_enqueue(pmp, park);
21584d9c625SLionel Sambuc 	puffs_msgmem_release(park);
21684d9c625SLionel Sambuc }
217