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