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
46extern int (**puffs_vnodeop_p)(void *);
47extern int (**puffs_specop_p)(void *);
48extern int (**puffs_fifoop_p)(void *);
49
50extern const struct vnodeopv_desc puffs_vnodeop_opv_desc;
51extern const struct vnodeopv_desc puffs_specop_opv_desc;
52extern const struct vnodeopv_desc puffs_fifoop_opv_desc;
53extern const struct vnodeopv_desc puffs_msgop_opv_desc;
54
55extern struct pool puffs_pnpool;
56extern struct pool puffs_vapool;
57
58#ifdef DEBUG
59#ifndef PUFFSDEBUG
60#define PUFFSDEBUG
61#endif
62#endif
63
64#ifdef PUFFSDEBUG
65extern 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
106struct 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
113extern int puffs_sopreq_expire_timeout;
114
115enum puffs_sopreqtype {
116 PUFFS_SOPREQSYS_EXIT,
117 PUFFS_SOPREQ_FLUSH,
118 PUFFS_SOPREQ_UNMOUNT,
119 PUFFS_SOPREQ_EXPIRE,
120};
121
122struct 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
137TAILQ_HEAD(puffs_wq, puffs_msgpark);
138LIST_HEAD(puffs_node_hashlist, puffs_node);
139struct 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
206struct 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
239typedef void (*parkdone_fn)(struct puffs_mount *, struct puffs_req *, void *);
240
241struct puffs_msgpark;
242void puffs_msgif_init(void);
243void puffs_msgif_destroy(void);
244int puffs_msgmem_alloc(size_t, struct puffs_msgpark **, void **, int);
245void puffs_msgmem_release(struct puffs_msgpark *);
246
247void puffs_sop_thread(void *);
248
249void puffs_msg_setfaf(struct puffs_msgpark *);
250void puffs_msg_setdelta(struct puffs_msgpark *, size_t);
251void puffs_msg_setinfo(struct puffs_msgpark *, int, int, puffs_cookie_t);
252void puffs_msg_setcall(struct puffs_msgpark *, parkdone_fn, void *);
253
254void puffs_msg_enqueue(struct puffs_mount *, struct puffs_msgpark *);
255int puffs_msg_wait(struct puffs_mount *, struct puffs_msgpark *);
256int puffs_msg_wait2(struct puffs_mount *, struct puffs_msgpark *,
257 struct puffs_node *, struct puffs_node *);
258
259void puffs_msg_sendresp(struct puffs_mount *, struct puffs_req *, int);
260
261int puffs_getvnode(struct mount *, puffs_cookie_t, enum vtype,
262 voff_t, dev_t, struct vnode **);
263int puffs_newnode(struct mount *, struct vnode *, struct vnode **,
264 puffs_cookie_t, struct componentname *,
265 enum vtype, dev_t);
266void puffs_putvnode(struct vnode *);
267
268void puffs_releasenode(struct puffs_node *);
269void puffs_referencenode(struct puffs_node *);
270
271#define PUFFS_NOSUCHCOOKIE (-1)
272int puffs_cookie2vnode(struct puffs_mount *, puffs_cookie_t,
273 struct vnode **);
274void puffs_makecn(struct puffs_kcn *, struct puffs_kcred *,
275 const struct componentname *, int);
276void puffs_credcvt(struct puffs_kcred *, kauth_cred_t);
277
278void puffs_parkdone_asyncbioread(struct puffs_mount *,
279 struct puffs_req *, void *);
280void puffs_parkdone_asyncbiowrite(struct puffs_mount *,
281 struct puffs_req *, void *);
282void puffs_parkdone_poll(struct puffs_mount *, struct puffs_req *, void *);
283
284void puffs_mp_reference(struct puffs_mount *);
285void puffs_mp_release(struct puffs_mount *);
286
287void puffs_gop_size(struct vnode *, off_t, off_t *, int);
288void puffs_gop_markupdate(struct vnode *, int);
289
290void puffs_senderr(struct puffs_mount *, int, int, const char *,
291 puffs_cookie_t);
292
293bool puffs_compat_outgoing(struct puffs_req *, struct puffs_req**, ssize_t*);
294void puffs_compat_incoming(struct puffs_req *, struct puffs_req *);
295
296void 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
302void puffs_userdead(struct puffs_mount *);
303
304extern int (**puffs_vnodeop_p)(void *);
305
306/* for putter */
307int puffs_msgif_getout(void *, size_t, int, uint8_t **, size_t *, void **);
308void puffs_msgif_releaseout(void *, void *, int);
309int puffs_msgif_dispatch(void *, struct putter_hdr *);
310size_t puffs_msgif_waitcount(void *);
311int puffs_msgif_close(void *);
312
313static __inline int
314checkerr(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) \
334do { \
335 if (park_##a) puffs_msgmem_release(park_##a); \
336} while (/*CONSTCOND*/0)
337
338#define PUFFS_MSG_ENQUEUEWAIT_NOERROR(pmp, park) \
339do { \
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) \
345do { \
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) \
351do { \
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) \
357do { \
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