1 | /* $NetBSD: puffs_sys.h,v 1.90 2016/07/07 06:55:42 msaitoh Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. |
5 | * |
6 | * Development of this software was supported by the |
7 | * Google Summer of Code program and the Ulla Tuominen Foundation. |
8 | * The Google SoC project was mentored by Bill Studenmund. |
9 | * |
10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions |
12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. |
18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
20 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
22 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
25 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | * SUCH DAMAGE. |
30 | */ |
31 | |
32 | #ifndef _PUFFS_SYS_H_ |
33 | #define _PUFFS_SYS_H_ |
34 | |
35 | #include <sys/param.h> |
36 | #include <sys/select.h> |
37 | #include <sys/kauth.h> |
38 | #include <sys/mutex.h> |
39 | #include <sys/queue.h> |
40 | #include <sys/pool.h> |
41 | |
42 | #include <fs/puffs/puffs_msgif.h> |
43 | |
44 | #include <miscfs/genfs/genfs_node.h> |
45 | |
46 | extern int (**puffs_vnodeop_p)(void *); |
47 | extern int (**puffs_specop_p)(void *); |
48 | extern int (**puffs_fifoop_p)(void *); |
49 | |
50 | extern const struct vnodeopv_desc puffs_vnodeop_opv_desc; |
51 | extern const struct vnodeopv_desc puffs_specop_opv_desc; |
52 | extern const struct vnodeopv_desc puffs_fifoop_opv_desc; |
53 | extern const struct vnodeopv_desc puffs_msgop_opv_desc; |
54 | |
55 | extern struct pool puffs_pnpool; |
56 | extern struct pool puffs_vapool; |
57 | |
58 | #ifdef DEBUG |
59 | #ifndef PUFFSDEBUG |
60 | #define PUFFSDEBUG |
61 | #endif |
62 | #endif |
63 | |
64 | #ifdef PUFFSDEBUG |
65 | extern int puffsdebug; /* puffs_subr.c */ |
66 | #define DPRINTF(x) do { \ |
67 | if (puffsdebug > 0) printf x; \ |
68 | } while (/*CONSTCOND*/0) |
69 | #define DPRINTF_VERBOSE(x) do { \ |
70 | if (puffsdebug > 1) printf x; \ |
71 | } while (/*CONSTCOND*/0) |
72 | #else |
73 | #define DPRINTF(x) ((void)0) |
74 | #define DPRINTF_VERBOSE(x) ((void)0) |
75 | #endif |
76 | |
77 | #define MPTOPUFFSMP(mp) ((struct puffs_mount *)((mp)->mnt_data)) |
78 | #define PMPTOMP(pmp) (pmp->pmp_mp) |
79 | #define VPTOPP(vp) ((struct puffs_node *)(vp)->v_data) |
80 | #define VPTOPNC(vp) (((struct puffs_node *)(vp)->v_data)->pn_cookie) |
81 | #define VPTOPUFFSMP(vp) ((struct puffs_mount*)((struct puffs_node*)vp->v_data)) |
82 | |
83 | /* we don't pass the kernel overlay to userspace */ |
84 | #define PUFFS_TOFHSIZE(s) ((s)==0 ? (s) : (s)+4) |
85 | #define PUFFS_FROMFHSIZE(s) ((s)==0 ? (s) : (s)-4) |
86 | |
87 | #define ALLOPS(pmp) (pmp->pmp_flags & PUFFS_KFLAG_ALLOPS) |
88 | #define EXISTSOP(pmp, op) \ |
89 | (ALLOPS(pmp) || ((pmp)->pmp_vnopmask[PUFFS_VN_##op])) |
90 | |
91 | #define PUFFS_USE_NAMECACHE(pmp) \ |
92 | (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_NAME) == 0) |
93 | #define PUFFS_USE_PAGECACHE(pmp) \ |
94 | (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_PAGE) == 0) |
95 | #define PUFFS_USE_FULLPNBUF(pmp) \ |
96 | ((pmp)->pmp_flags & PUFFS_KFLAG_LOOKUP_FULLPNBUF) |
97 | #define PUFFS_USE_FS_TTL(pmp) \ |
98 | ((pmp)->pmp_flags & PUFFS_KFLAG_CACHE_FS_TTL) |
99 | #define PUFFS_USE_DOTDOTCACHE(pmp) \ |
100 | ((pmp)->pmp_flags & PUFFS_KFLAG_CACHE_DOTDOT) |
101 | #define PUFFS_USE_METAFLUSH(pmp) \ |
102 | (((pmp)->pmp_flags & PUFFS_KFLAG_NOFLUSH_META) == 0) |
103 | |
104 | #define PUFFS_WCACHEINFO(pmp) (__USE(pmp), 0) |
105 | |
106 | struct puffs_newcookie { |
107 | puffs_cookie_t pnc_cookie; |
108 | |
109 | LIST_ENTRY(puffs_newcookie) pnc_entries; |
110 | }; |
111 | |
112 | #define PUFFS_SOPREQ_EXPIRE_TIMEOUT 1000 |
113 | extern int puffs_sopreq_expire_timeout; |
114 | |
115 | enum puffs_sopreqtype { |
116 | PUFFS_SOPREQSYS_EXIT, |
117 | PUFFS_SOPREQ_FLUSH, |
118 | PUFFS_SOPREQ_UNMOUNT, |
119 | PUFFS_SOPREQ_EXPIRE, |
120 | }; |
121 | |
122 | struct puffs_sopreq { |
123 | union { |
124 | struct puffs_req preq; |
125 | struct puffs_flush pf; |
126 | puffs_cookie_t ck; |
127 | } psopr_u; |
128 | |
129 | enum puffs_sopreqtype psopr_sopreq; |
130 | TAILQ_ENTRY(puffs_sopreq) psopr_entries; |
131 | int psopr_at; |
132 | }; |
133 | #define psopr_preq psopr_u.preq |
134 | #define psopr_pf psopr_u.pf |
135 | #define psopr_ck psopr_u.ck |
136 | |
137 | TAILQ_HEAD(puffs_wq, puffs_msgpark); |
138 | LIST_HEAD(puffs_node_hashlist, puffs_node); |
139 | struct puffs_mount { |
140 | kmutex_t pmp_lock; |
141 | |
142 | struct puffs_kargs pmp_args; |
143 | #define pmp_flags pmp_args.pa_flags |
144 | #define pmp_vnopmask pmp_args.pa_vnopmask |
145 | |
146 | struct puffs_wq pmp_msg_touser; |
147 | int pmp_msg_touser_count; |
148 | kcondvar_t pmp_msg_waiter_cv; |
149 | size_t pmp_msg_maxsize; |
150 | |
151 | struct puffs_wq pmp_msg_replywait; |
152 | |
153 | struct mount *pmp_mp; |
154 | |
155 | struct vnode *pmp_root; |
156 | puffs_cookie_t pmp_root_cookie; |
157 | enum vtype pmp_root_vtype; |
158 | vsize_t pmp_root_vsize; |
159 | dev_t pmp_root_rdev; |
160 | |
161 | struct putter_instance *pmp_pi; |
162 | |
163 | unsigned int pmp_refcount; |
164 | kcondvar_t pmp_refcount_cv; |
165 | |
166 | kcondvar_t pmp_unmounting_cv; |
167 | uint8_t pmp_unmounting; |
168 | |
169 | uint8_t pmp_status; |
170 | uint8_t pmp_suspend; |
171 | |
172 | uint8_t *pmp_curput; |
173 | size_t pmp_curres; |
174 | void *pmp_curopaq; |
175 | |
176 | uint64_t pmp_nextmsgid; |
177 | |
178 | kmutex_t pmp_sopmtx; |
179 | kcondvar_t pmp_sopcv; |
180 | int pmp_sopthrcount; |
181 | TAILQ_HEAD(, puffs_sopreq) pmp_sopfastreqs; |
182 | TAILQ_HEAD(, puffs_sopreq) pmp_sopnodereqs; |
183 | bool pmp_docompat; |
184 | }; |
185 | |
186 | #define PUFFSTAT_BEFOREINIT 0 |
187 | #define PUFFSTAT_MOUNTING 1 |
188 | #define PUFFSTAT_RUNNING 2 |
189 | #define PUFFSTAT_DYING 3 /* Do you want your possessions identified? */ |
190 | |
191 | |
192 | #define PNODE_NOREFS 0x001 /* no backend reference */ |
193 | #define PNODE_DYING 0x002 /* NOREFS + inactive */ |
194 | #define PNODE_FAF 0x004 /* issue all operations as FAF */ |
195 | #define PNODE_DOINACT 0x008 /* if inactive-on-demand, call inactive */ |
196 | #define PNODE_SOPEXP 0x100 /* Node reclaim postponed in sop thread */ |
197 | #define PNODE_RDIRECT 0x200 /* bypass page cache on read */ |
198 | #define PNODE_WDIRECT 0x400 /* bypass page cache on write */ |
199 | |
200 | #define PNODE_METACACHE_ATIME 0x10 /* cache atime metadata */ |
201 | #define PNODE_METACACHE_CTIME 0x20 /* cache atime metadata */ |
202 | #define PNODE_METACACHE_MTIME 0x40 /* cache atime metadata */ |
203 | #define PNODE_METACACHE_SIZE 0x80 /* cache atime metadata */ |
204 | #define PNODE_METACACHE_MASK 0xf0 |
205 | |
206 | struct puffs_node { |
207 | struct genfs_node pn_gnode; /* genfs glue */ |
208 | |
209 | kmutex_t pn_mtx; |
210 | int pn_refcount; |
211 | int pn_nlookup; |
212 | |
213 | puffs_cookie_t pn_cookie; /* userspace pnode cookie */ |
214 | struct vnode *pn_vp; /* backpointer to vnode */ |
215 | uint32_t pn_stat; /* node status */ |
216 | |
217 | struct selinfo pn_sel; /* for selecting on the node */ |
218 | short pn_revents; /* available events */ |
219 | |
220 | /* metacache */ |
221 | struct timespec pn_mc_atime; |
222 | struct timespec pn_mc_ctime; |
223 | struct timespec pn_mc_mtime; |
224 | u_quad_t pn_mc_size; |
225 | |
226 | voff_t pn_serversize; |
227 | |
228 | struct lockf * pn_lockf; |
229 | |
230 | kmutex_t pn_sizemtx; /* size modification mutex */ |
231 | |
232 | int pn_cn_timeout; /* path cache */ |
233 | int pn_cn_grace; /* grace time before reclaim */ |
234 | int pn_va_timeout; /* attribute cache */ |
235 | struct vattr * pn_va_cache; /* attribute cache */ |
236 | struct vnode * pn_parent; /* parent cache */ |
237 | }; |
238 | |
239 | typedef void (*parkdone_fn)(struct puffs_mount *, struct puffs_req *, void *); |
240 | |
241 | struct puffs_msgpark; |
242 | void puffs_msgif_init(void); |
243 | void puffs_msgif_destroy(void); |
244 | int puffs_msgmem_alloc(size_t, struct puffs_msgpark **, void **, int); |
245 | void puffs_msgmem_release(struct puffs_msgpark *); |
246 | |
247 | void puffs_sop_thread(void *); |
248 | |
249 | void puffs_msg_setfaf(struct puffs_msgpark *); |
250 | void puffs_msg_setdelta(struct puffs_msgpark *, size_t); |
251 | void puffs_msg_setinfo(struct puffs_msgpark *, int, int, puffs_cookie_t); |
252 | void puffs_msg_setcall(struct puffs_msgpark *, parkdone_fn, void *); |
253 | |
254 | void puffs_msg_enqueue(struct puffs_mount *, struct puffs_msgpark *); |
255 | int puffs_msg_wait(struct puffs_mount *, struct puffs_msgpark *); |
256 | int puffs_msg_wait2(struct puffs_mount *, struct puffs_msgpark *, |
257 | struct puffs_node *, struct puffs_node *); |
258 | |
259 | void puffs_msg_sendresp(struct puffs_mount *, struct puffs_req *, int); |
260 | |
261 | int puffs_getvnode(struct mount *, puffs_cookie_t, enum vtype, |
262 | voff_t, dev_t, struct vnode **); |
263 | int puffs_newnode(struct mount *, struct vnode *, struct vnode **, |
264 | puffs_cookie_t, struct componentname *, |
265 | enum vtype, dev_t); |
266 | void puffs_putvnode(struct vnode *); |
267 | |
268 | void puffs_releasenode(struct puffs_node *); |
269 | void puffs_referencenode(struct puffs_node *); |
270 | |
271 | #define PUFFS_NOSUCHCOOKIE (-1) |
272 | int puffs_cookie2vnode(struct puffs_mount *, puffs_cookie_t, |
273 | struct vnode **); |
274 | void puffs_makecn(struct puffs_kcn *, struct puffs_kcred *, |
275 | const struct componentname *, int); |
276 | void puffs_credcvt(struct puffs_kcred *, kauth_cred_t); |
277 | |
278 | void puffs_parkdone_asyncbioread(struct puffs_mount *, |
279 | struct puffs_req *, void *); |
280 | void puffs_parkdone_asyncbiowrite(struct puffs_mount *, |
281 | struct puffs_req *, void *); |
282 | void puffs_parkdone_poll(struct puffs_mount *, struct puffs_req *, void *); |
283 | |
284 | void puffs_mp_reference(struct puffs_mount *); |
285 | void puffs_mp_release(struct puffs_mount *); |
286 | |
287 | void puffs_gop_size(struct vnode *, off_t, off_t *, int); |
288 | void puffs_gop_markupdate(struct vnode *, int); |
289 | |
290 | void puffs_senderr(struct puffs_mount *, int, int, const char *, |
291 | puffs_cookie_t); |
292 | |
293 | bool puffs_compat_outgoing(struct puffs_req *, struct puffs_req**, ssize_t*); |
294 | void puffs_compat_incoming(struct puffs_req *, struct puffs_req *); |
295 | |
296 | void puffs_updatenode(struct puffs_node *, int, voff_t); |
297 | #define PUFFS_UPDATEATIME 0x01 |
298 | #define PUFFS_UPDATECTIME 0x02 |
299 | #define PUFFS_UPDATEMTIME 0x04 |
300 | #define PUFFS_UPDATESIZE 0x08 |
301 | |
302 | void puffs_userdead(struct puffs_mount *); |
303 | |
304 | extern int (**puffs_vnodeop_p)(void *); |
305 | |
306 | /* for putter */ |
307 | int puffs_msgif_getout(void *, size_t, int, uint8_t **, size_t *, void **); |
308 | void puffs_msgif_releaseout(void *, void *, int); |
309 | int puffs_msgif_dispatch(void *, struct putter_hdr *); |
310 | size_t puffs_msgif_waitcount(void *); |
311 | int puffs_msgif_close(void *); |
312 | |
313 | static __inline int |
314 | checkerr(struct puffs_mount *pmp, int error, const char *str) |
315 | { |
316 | |
317 | if (error < 0 || error > ELAST) { |
318 | puffs_senderr(pmp, PUFFS_ERR_ERROR, error, str, NULL); |
319 | error = EPROTO; |
320 | } |
321 | |
322 | return error; |
323 | } |
324 | |
325 | #define PUFFS_MSG_VARS(type, a) \ |
326 | struct puffs_##type##msg_##a *a##_msg; \ |
327 | struct puffs_msgpark *park_##a = NULL |
328 | |
329 | #define PUFFS_MSG_ALLOC(type, a) \ |
330 | puffs_msgmem_alloc(sizeof(struct puffs_##type##msg_##a), \ |
331 | &park_##a, (void *)& a##_msg, 1) |
332 | |
333 | #define PUFFS_MSG_RELEASE(a) \ |
334 | do { \ |
335 | if (park_##a) puffs_msgmem_release(park_##a); \ |
336 | } while (/*CONSTCOND*/0) |
337 | |
338 | #define PUFFS_MSG_ENQUEUEWAIT_NOERROR(pmp, park) \ |
339 | do { \ |
340 | puffs_msg_enqueue(pmp, park); \ |
341 | puffs_msg_wait(pmp, park); \ |
342 | } while (/*CONSTCOND*/0) |
343 | |
344 | #define PUFFS_MSG_ENQUEUEWAIT2_NOERROR(pmp, park, vp1, vp2) \ |
345 | do { \ |
346 | puffs_msg_enqueue(pmp, park); \ |
347 | puffs_msg_wait2(pmp, park, vp1, vp2); \ |
348 | } while (/*CONSTCOND*/0) |
349 | |
350 | #define PUFFS_MSG_ENQUEUEWAIT(pmp, park, var) \ |
351 | do { \ |
352 | puffs_msg_enqueue(pmp, park); \ |
353 | var = puffs_msg_wait(pmp, park); \ |
354 | } while (/*CONSTCOND*/0) |
355 | |
356 | #define PUFFS_MSG_ENQUEUEWAIT2(pmp, park, vp1, vp2, var) \ |
357 | do { \ |
358 | puffs_msg_enqueue(pmp, park); \ |
359 | var = puffs_msg_wait2(pmp, park, vp1, vp2); \ |
360 | } while (/*CONSTCOND*/0) |
361 | |
362 | #endif /* _PUFFS_SYS_H_ */ |
363 | |