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 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 293int 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/* 363 * compat50 init/fini 364 */ 365 366void puffs_50_init(void); 367void puffs_50_fini(void); 368 369#endif /* _PUFFS_SYS_H_ */ 370