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