1 /*        $NetBSD: puffs_sys.h,v 1.91 2019/01/27 02:08:43 pgoyette 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 int       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
checkerr(struct puffs_mount * pmp,int error,const char * str)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 /*
363  * compat50 init/fini
364  */
365 
366 void puffs_50_init(void);
367 void puffs_50_fini(void);
368 
369 #endif /* _PUFFS_SYS_H_ */
370