xref: /netbsd/sys/fs/puffs/puffs_sys.h (revision 6550d01e)
1 /*	$NetBSD: puffs_sys.h,v 1.77 2011/01/11 14:04:54 kefren 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 
57 #ifdef DEBUG
58 #ifndef PUFFSDEBUG
59 #define PUFFSDEBUG
60 #endif
61 #endif
62 
63 #ifdef PUFFSDEBUG
64 extern int puffsdebug; /* puffs_subr.c */
65 #define DPRINTF(x) if (puffsdebug > 0) printf x
66 #define DPRINTF_VERBOSE(x) if (puffsdebug > 1) printf x
67 #else
68 #define DPRINTF(x)
69 #define DPRINTF_VERBOSE(x)
70 #endif
71 
72 #define MPTOPUFFSMP(mp) ((struct puffs_mount *)((mp)->mnt_data))
73 #define PMPTOMP(pmp) (pmp->pmp_mp)
74 #define VPTOPP(vp) ((struct puffs_node *)(vp)->v_data)
75 #define VPTOPNC(vp) (((struct puffs_node *)(vp)->v_data)->pn_cookie)
76 #define VPTOPUFFSMP(vp) ((struct puffs_mount*)((struct puffs_node*)vp->v_data))
77 
78 /* we don't pass the kernel overlay to userspace */
79 #define PUFFS_TOFHSIZE(s) ((s)==0 ? (s) : (s)+4)
80 #define PUFFS_FROMFHSIZE(s) ((s)==0 ? (s) : (s)-4)
81 
82 #define ALLOPS(pmp) (pmp->pmp_flags & PUFFS_KFLAG_ALLOPS)
83 #define EXISTSOP(pmp, op) \
84  (ALLOPS(pmp) || ((pmp)->pmp_vnopmask[PUFFS_VN_##op]))
85 
86 #define PUFFS_USE_NAMECACHE(pmp)	\
87     (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_NAME) == 0)
88 #define PUFFS_USE_PAGECACHE(pmp)	\
89     (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_PAGE) == 0)
90 #define PUFFS_USE_FULLPNBUF(pmp)	\
91     ((pmp)->pmp_flags & PUFFS_KFLAG_LOOKUP_FULLPNBUF)
92 
93 #define PUFFS_WCACHEINFO(pmp)	0
94 
95 struct puffs_newcookie {
96 	puffs_cookie_t	pnc_cookie;
97 
98 	LIST_ENTRY(puffs_newcookie) pnc_entries;
99 };
100 
101 enum puffs_sopreqtype {
102 	PUFFS_SOPREQSYS_EXIT,
103 	PUFFS_SOPREQ_FLUSH,
104 	PUFFS_SOPREQ_UNMOUNT,
105 };
106 
107 struct puffs_sopreq {
108 	union {
109 		struct puffs_req preq;
110 		struct puffs_flush pf;
111 	} psopr_u;
112 
113 	enum puffs_sopreqtype psopr_sopreq;
114 	TAILQ_ENTRY(puffs_sopreq) psopr_entries;
115 };
116 #define psopr_preq psopr_u.preq
117 #define psopr_pf psopr_u.pf
118 
119 TAILQ_HEAD(puffs_wq, puffs_msgpark);
120 LIST_HEAD(puffs_node_hashlist, puffs_node);
121 struct puffs_mount {
122 	kmutex_t	 		pmp_lock;
123 
124 	struct puffs_kargs		pmp_args;
125 #define pmp_flags pmp_args.pa_flags
126 #define pmp_vnopmask pmp_args.pa_vnopmask
127 
128 	struct puffs_wq			pmp_msg_touser;
129 	int				pmp_msg_touser_count;
130 	kcondvar_t			pmp_msg_waiter_cv;
131 	size_t				pmp_msg_maxsize;
132 
133 	struct puffs_wq			pmp_msg_replywait;
134 
135 	struct puffs_node_hashlist	*pmp_pnodehash;
136 	int				pmp_npnodehash;
137 
138 	LIST_HEAD(, puffs_newcookie)	pmp_newcookie;
139 
140 	struct mount			*pmp_mp;
141 
142 	struct vnode			*pmp_root;
143 	puffs_cookie_t			pmp_root_cookie;
144 	enum vtype			pmp_root_vtype;
145 	vsize_t				pmp_root_vsize;
146 	dev_t				pmp_root_rdev;
147 
148 	struct putter_instance		*pmp_pi;
149 
150 	unsigned int			pmp_refcount;
151 	kcondvar_t			pmp_refcount_cv;
152 
153 	kcondvar_t			pmp_unmounting_cv;
154 	uint8_t				pmp_unmounting;
155 
156 	uint8_t				pmp_status;
157 	uint8_t				pmp_suspend;
158 
159 	uint8_t				*pmp_curput;
160 	size_t				pmp_curres;
161 	void				*pmp_curopaq;
162 
163 	uint64_t			pmp_nextmsgid;
164 
165 	kmutex_t			pmp_sopmtx;
166 	kcondvar_t			pmp_sopcv;
167 	int				pmp_sopthrcount;
168 	TAILQ_HEAD(, puffs_sopreq)	pmp_sopreqs;
169 	bool				pmp_docompat;
170 };
171 
172 #define PUFFSTAT_BEFOREINIT	0
173 #define PUFFSTAT_MOUNTING	1
174 #define PUFFSTAT_RUNNING	2
175 #define PUFFSTAT_DYING		3 /* Do you want your possessions identified? */
176 
177 
178 #define PNODE_NOREFS	0x01	/* no backend reference			*/
179 #define PNODE_DYING	0x02	/* NOREFS + inactive			*/
180 #define PNODE_FAF	0x04	/* issue all operations as FAF		*/
181 #define PNODE_DOINACT	0x08	/* if inactive-on-demand, call inactive */
182 
183 #define PNODE_METACACHE_ATIME	0x10	/* cache atime metadata */
184 #define PNODE_METACACHE_CTIME	0x20	/* cache atime metadata */
185 #define PNODE_METACACHE_MTIME	0x40	/* cache atime metadata */
186 #define PNODE_METACACHE_SIZE	0x80	/* cache atime metadata */
187 #define PNODE_METACACHE_MASK	0xf0
188 
189 struct puffs_node {
190 	struct genfs_node pn_gnode;	/* genfs glue			*/
191 
192 	kmutex_t	pn_mtx;
193 	int		pn_refcount;
194 
195 	puffs_cookie_t	pn_cookie;	/* userspace pnode cookie	*/
196 	struct vnode	*pn_vp;		/* backpointer to vnode		*/
197 	uint32_t	pn_stat;	/* node status			*/
198 
199 	struct selinfo	pn_sel;		/* for selecting on the node	*/
200 	short		pn_revents;	/* available events		*/
201 
202 	/* metacache */
203 	struct timespec	pn_mc_atime;
204 	struct timespec	pn_mc_ctime;
205 	struct timespec	pn_mc_mtime;
206 	u_quad_t	pn_mc_size;
207 
208 	voff_t		pn_serversize;
209 
210 	struct lockf *	pn_lockf;
211 
212 	LIST_ENTRY(puffs_node) pn_hashent;
213 };
214 
215 typedef void (*parkdone_fn)(struct puffs_mount *, struct puffs_req *, void *);
216 
217 struct puffs_msgpark;
218 void	puffs_msgif_init(void);
219 void	puffs_msgif_destroy(void);
220 int	puffs_msgmem_alloc(size_t, struct puffs_msgpark **, void **, int);
221 void	puffs_msgmem_release(struct puffs_msgpark *);
222 
223 void	puffs_sop_thread(void *);
224 
225 void	puffs_msg_setfaf(struct puffs_msgpark *);
226 void	puffs_msg_setdelta(struct puffs_msgpark *, size_t);
227 void	puffs_msg_setinfo(struct puffs_msgpark *, int, int, puffs_cookie_t);
228 void	puffs_msg_setcall(struct puffs_msgpark *, parkdone_fn, void *);
229 
230 void	puffs_msg_enqueue(struct puffs_mount *, struct puffs_msgpark *);
231 int	puffs_msg_wait(struct puffs_mount *, struct puffs_msgpark *);
232 int	puffs_msg_wait2(struct puffs_mount *, struct puffs_msgpark *,
233 			struct puffs_node *, struct puffs_node *);
234 
235 void	puffs_msg_sendresp(struct puffs_mount *, struct puffs_req *, int);
236 
237 int	puffs_getvnode(struct mount *, puffs_cookie_t, enum vtype,
238 		       voff_t, dev_t, struct vnode **);
239 int	puffs_newnode(struct mount *, struct vnode *, struct vnode **,
240 		      puffs_cookie_t, struct componentname *,
241 		      enum vtype, dev_t);
242 void	puffs_putvnode(struct vnode *);
243 
244 void	puffs_releasenode(struct puffs_node *);
245 void	puffs_referencenode(struct puffs_node *);
246 
247 #define PUFFS_NOSUCHCOOKIE (-1)
248 int	puffs_cookie2vnode(struct puffs_mount *, puffs_cookie_t, int, int,
249 			   struct vnode **);
250 void	puffs_makecn(struct puffs_kcn *, struct puffs_kcred *,
251 		     const struct componentname *, int);
252 void	puffs_credcvt(struct puffs_kcred *, kauth_cred_t);
253 
254 void	puffs_parkdone_asyncbioread(struct puffs_mount *,
255 				    struct puffs_req *, void *);
256 void	puffs_parkdone_asyncbiowrite(struct puffs_mount *,
257 				     struct puffs_req *, void *);
258 void	puffs_parkdone_poll(struct puffs_mount *, struct puffs_req *, void *);
259 
260 void	puffs_mp_reference(struct puffs_mount *);
261 void	puffs_mp_release(struct puffs_mount *);
262 
263 void	puffs_gop_size(struct vnode *, off_t, off_t *, int);
264 void	puffs_gop_markupdate(struct vnode *, int);
265 
266 void	puffs_senderr(struct puffs_mount *, int, int, const char *,
267 		      puffs_cookie_t);
268 
269 bool	puffs_compat_outgoing(struct puffs_req *, struct puffs_req**, ssize_t*);
270 void	puffs_compat_incoming(struct puffs_req *, struct puffs_req *);
271 
272 void	puffs_updatenode(struct puffs_node *, int, voff_t);
273 #define PUFFS_UPDATEATIME	0x01
274 #define PUFFS_UPDATECTIME	0x02
275 #define PUFFS_UPDATEMTIME	0x04
276 #define PUFFS_UPDATESIZE	0x08
277 
278 void	puffs_userdead(struct puffs_mount *);
279 
280 extern int (**puffs_vnodeop_p)(void *);
281 
282 /* for putter */
283 int	puffs_msgif_getout(void *, size_t, int, uint8_t **, size_t *, void **);
284 void	puffs_msgif_releaseout(void *, void *, int);
285 int	puffs_msgif_dispatch(void *, struct putter_hdr *);
286 size_t	puffs_msgif_waitcount(void *);
287 int	puffs_msgif_close(void *);
288 
289 static __inline int
290 checkerr(struct puffs_mount *pmp, int error, const char *str)
291 {
292 
293 	if (error < 0 || error > ELAST) {
294 		puffs_senderr(pmp, PUFFS_ERR_ERROR, error, str, NULL);
295 		error = EPROTO;
296 	}
297 
298 	return error;
299 }
300 
301 #define PUFFS_MSG_VARS(type, a)						\
302 	struct puffs_##type##msg_##a *a##_msg;				\
303 	struct puffs_msgpark *park_##a = NULL
304 
305 #define PUFFS_MSG_ALLOC(type, a)					\
306 	puffs_msgmem_alloc(sizeof(struct puffs_##type##msg_##a),	\
307 	    &park_##a, (void *)& a##_msg, 1)
308 
309 #define PUFFS_MSG_RELEASE(a) 						\
310 do {									\
311 	if (park_##a) puffs_msgmem_release(park_##a);			\
312 } while (/*CONSTCOND*/0)
313 
314 #define PUFFS_MSG_ENQUEUEWAIT(pmp, park, var)				\
315 do {									\
316 	puffs_msg_enqueue(pmp, park);					\
317 	var = puffs_msg_wait(pmp, park);				\
318 } while (/*CONSTCOND*/0)
319 
320 #define PUFFS_MSG_ENQUEUEWAIT2(pmp, park, vp1, vp2, var)		\
321 do {									\
322 	puffs_msg_enqueue(pmp, park);					\
323 	var = puffs_msg_wait2(pmp, park, vp1, vp2);			\
324 } while (/*CONSTCOND*/0)
325 
326 #endif /* _PUFFS_SYS_H_ */
327