xref: /minix/sys/fs/puffs/puffs_subr.c (revision 0a6a1f1d)
1 /*	$NetBSD: puffs_subr.c,v 1.67 2014/11/10 18:46:33 maxv Exp $	*/
2 
3 /*
4  * Copyright (c) 2006, 2007  Antti Kantee.  All Rights Reserved.
5  *
6  * Development of this software was supported by the
7  * Ulla Tuominen Foundation and the Finnish Cultural Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: puffs_subr.c,v 1.67 2014/11/10 18:46:33 maxv Exp $");
33 
34 #include <sys/param.h>
35 #include <sys/buf.h>
36 #include <sys/mount.h>
37 #include <sys/namei.h>
38 #include <sys/poll.h>
39 #include <sys/proc.h>
40 
41 #include <fs/puffs/puffs_msgif.h>
42 #include <fs/puffs/puffs_sys.h>
43 
44 #ifdef PUFFSDEBUG
45 int puffsdebug;
46 #endif
47 
48 void
puffs_makecn(struct puffs_kcn * pkcn,struct puffs_kcred * pkcr,const struct componentname * cn,int full)49 puffs_makecn(struct puffs_kcn *pkcn, struct puffs_kcred *pkcr,
50 	const struct componentname *cn, int full)
51 {
52 
53 	pkcn->pkcn_nameiop = cn->cn_nameiop;
54 	pkcn->pkcn_flags = cn->cn_flags;
55 
56 	if (full) {
57 		(void)strcpy(pkcn->pkcn_name, cn->cn_nameptr);
58 	} else {
59 		(void)memcpy(pkcn->pkcn_name, cn->cn_nameptr, cn->cn_namelen);
60 		pkcn->pkcn_name[cn->cn_namelen] = '\0';
61 	}
62 	pkcn->pkcn_namelen = cn->cn_namelen;
63 	pkcn->pkcn_consume = 0;
64 
65 	puffs_credcvt(pkcr, cn->cn_cred);
66 }
67 
68 /*
69  * Convert given credentials to struct puffs_kcred for userspace.
70  */
71 void
puffs_credcvt(struct puffs_kcred * pkcr,const kauth_cred_t cred)72 puffs_credcvt(struct puffs_kcred *pkcr, const kauth_cred_t cred)
73 {
74 
75 	memset(pkcr, 0, sizeof(struct puffs_kcred));
76 
77 	if (cred == NOCRED || cred == FSCRED) {
78 		pkcr->pkcr_type = PUFFCRED_TYPE_INTERNAL;
79 		if (cred == NOCRED)
80 			pkcr->pkcr_internal = PUFFCRED_CRED_NOCRED;
81 		if (cred == FSCRED)
82 			pkcr->pkcr_internal = PUFFCRED_CRED_FSCRED;
83  	} else {
84 		pkcr->pkcr_type = PUFFCRED_TYPE_UUC;
85 		kauth_cred_to_uucred(&pkcr->pkcr_uuc, cred);
86 	}
87 }
88 
89 void
puffs_parkdone_asyncbioread(struct puffs_mount * pmp,struct puffs_req * preq,void * arg)90 puffs_parkdone_asyncbioread(struct puffs_mount *pmp,
91 	struct puffs_req *preq, void *arg)
92 {
93 	struct puffs_vnmsg_read *read_msg = (void *)preq;
94 	struct buf *bp = arg;
95 	size_t moved;
96 
97 	DPRINTF(("%s\n", __func__));
98 
99 	bp->b_error = checkerr(pmp, preq->preq_rv, __func__);
100 	if (bp->b_error == 0) {
101 		if (read_msg->pvnr_resid > bp->b_bcount) {
102 			puffs_senderr(pmp, PUFFS_ERR_READ, E2BIG,
103 			    "resid grew", preq->preq_cookie);
104 			bp->b_error = E2BIG;
105 		} else {
106 			moved = bp->b_bcount - read_msg->pvnr_resid;
107 			bp->b_resid = read_msg->pvnr_resid;
108 
109 			memcpy(bp->b_data, read_msg->pvnr_data, moved);
110 		}
111 	}
112 
113 	biodone(bp);
114 }
115 
116 void
puffs_parkdone_asyncbiowrite(struct puffs_mount * pmp,struct puffs_req * preq,void * arg)117 puffs_parkdone_asyncbiowrite(struct puffs_mount *pmp,
118 	struct puffs_req *preq, void *arg)
119 {
120 	struct puffs_vnmsg_write *write_msg = (void *)preq;
121 	struct buf *bp = arg;
122 
123 	DPRINTF(("%s\n", __func__));
124 
125 	bp->b_error = checkerr(pmp, preq->preq_rv, __func__);
126 	if (bp->b_error == 0) {
127 		if (write_msg->pvnr_resid > bp->b_bcount) {
128 			puffs_senderr(pmp, PUFFS_ERR_WRITE, E2BIG,
129 			    "resid grew", preq->preq_cookie);
130 			bp->b_error = E2BIG;
131 		} else {
132 			bp->b_resid = write_msg->pvnr_resid;
133 		}
134 	}
135 
136 	biodone(bp);
137 }
138 
139 /* XXX: userspace can leak kernel resources */
140 void
puffs_parkdone_poll(struct puffs_mount * pmp,struct puffs_req * preq,void * arg)141 puffs_parkdone_poll(struct puffs_mount *pmp, struct puffs_req *preq, void *arg)
142 {
143 	struct puffs_vnmsg_poll *poll_msg = (void *)preq;
144 	struct puffs_node *pn = arg;
145 	int revents, error;
146 
147 	error = checkerr(pmp, preq->preq_rv, __func__);
148 	if (error)
149 		revents = poll_msg->pvnr_events;
150 	else
151 		revents = POLLERR;
152 
153 	mutex_enter(&pn->pn_mtx);
154 	pn->pn_revents |= revents;
155 	mutex_exit(&pn->pn_mtx);
156 
157 	selnotify(&pn->pn_sel, revents, 0);
158 
159 	puffs_releasenode(pn);
160 }
161 
162 void
puffs_mp_reference(struct puffs_mount * pmp)163 puffs_mp_reference(struct puffs_mount *pmp)
164 {
165 
166 	KASSERT(mutex_owned(&pmp->pmp_lock));
167 	pmp->pmp_refcount++;
168 }
169 
170 void
puffs_mp_release(struct puffs_mount * pmp)171 puffs_mp_release(struct puffs_mount *pmp)
172 {
173 
174 	KASSERT(mutex_owned(&pmp->pmp_lock));
175 	if (--pmp->pmp_refcount == 0)
176 		cv_broadcast(&pmp->pmp_refcount_cv);
177 }
178 
179 void
puffs_gop_size(struct vnode * vp,off_t size,off_t * eobp,int flags)180 puffs_gop_size(struct vnode *vp, off_t size, off_t *eobp,
181 	int flags)
182 {
183 
184 	*eobp = size;
185 }
186 
187 void
puffs_gop_markupdate(struct vnode * vp,int flags)188 puffs_gop_markupdate(struct vnode *vp, int flags)
189 {
190 	int uflags = 0;
191 
192 	if (flags & GOP_UPDATE_ACCESSED)
193 		uflags |= PUFFS_UPDATEATIME;
194 	if (flags & GOP_UPDATE_MODIFIED)
195 		uflags |= PUFFS_UPDATEMTIME;
196 
197 	puffs_updatenode(VPTOPP(vp), uflags, 0);
198 }
199 
200 void
puffs_senderr(struct puffs_mount * pmp,int type,int error,const char * str,puffs_cookie_t ck)201 puffs_senderr(struct puffs_mount *pmp, int type, int error,
202 	const char *str, puffs_cookie_t ck)
203 {
204 	struct puffs_msgpark *park;
205 	struct puffs_error *perr;
206 
207 	puffs_msgmem_alloc(sizeof(struct puffs_error), &park, (void *)&perr, 1);
208 	puffs_msg_setfaf(park);
209 	puffs_msg_setinfo(park, PUFFSOP_ERROR, type, ck);
210 
211 	perr->perr_error = error;
212 	strlcpy(perr->perr_str, str, sizeof(perr->perr_str));
213 
214 	puffs_msg_enqueue(pmp, park);
215 	puffs_msgmem_release(park);
216 }
217