/* $NetBSD: puffs_sys.h,v 1.82 2012/08/11 01:10:11 manu Exp $ */ /* * Copyright (c) 2005, 2006 Antti Kantee. All Rights Reserved. * * Development of this software was supported by the * Google Summer of Code program and the Ulla Tuominen Foundation. * The Google SoC project was mentored by Bill Studenmund. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _PUFFS_SYS_H_ #define _PUFFS_SYS_H_ #include #include #include #include #include #include #include #include extern int (**puffs_vnodeop_p)(void *); extern int (**puffs_specop_p)(void *); extern int (**puffs_fifoop_p)(void *); extern const struct vnodeopv_desc puffs_vnodeop_opv_desc; extern const struct vnodeopv_desc puffs_specop_opv_desc; extern const struct vnodeopv_desc puffs_fifoop_opv_desc; extern const struct vnodeopv_desc puffs_msgop_opv_desc; extern struct pool puffs_pnpool; extern struct pool puffs_vapool; #ifdef DEBUG #ifndef PUFFSDEBUG #define PUFFSDEBUG #endif #endif #ifdef PUFFSDEBUG extern int puffsdebug; /* puffs_subr.c */ #define DPRINTF(x) if (puffsdebug > 0) printf x #define DPRINTF_VERBOSE(x) if (puffsdebug > 1) printf x #else #define DPRINTF(x) #define DPRINTF_VERBOSE(x) #endif #define MPTOPUFFSMP(mp) ((struct puffs_mount *)((mp)->mnt_data)) #define PMPTOMP(pmp) (pmp->pmp_mp) #define VPTOPP(vp) ((struct puffs_node *)(vp)->v_data) #define VPTOPNC(vp) (((struct puffs_node *)(vp)->v_data)->pn_cookie) #define VPTOPUFFSMP(vp) ((struct puffs_mount*)((struct puffs_node*)vp->v_data)) /* we don't pass the kernel overlay to userspace */ #define PUFFS_TOFHSIZE(s) ((s)==0 ? (s) : (s)+4) #define PUFFS_FROMFHSIZE(s) ((s)==0 ? (s) : (s)-4) #define ALLOPS(pmp) (pmp->pmp_flags & PUFFS_KFLAG_ALLOPS) #define EXISTSOP(pmp, op) \ (ALLOPS(pmp) || ((pmp)->pmp_vnopmask[PUFFS_VN_##op])) #define PUFFS_USE_NAMECACHE(pmp) \ (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_NAME) == 0) #define PUFFS_USE_PAGECACHE(pmp) \ (((pmp)->pmp_flags & PUFFS_KFLAG_NOCACHE_PAGE) == 0) #define PUFFS_USE_FULLPNBUF(pmp) \ ((pmp)->pmp_flags & PUFFS_KFLAG_LOOKUP_FULLPNBUF) #define PUFFS_USE_FS_TTL(pmp) \ ((pmp)->pmp_flags & PUFFS_KFLAG_CACHE_FS_TTL) #define PUFFS_USE_DOTDOTCACHE(pmp) \ ((pmp)->pmp_flags & PUFFS_KFLAG_CACHE_DOTDOT) #define PUFFS_WCACHEINFO(pmp) 0 struct puffs_newcookie { puffs_cookie_t pnc_cookie; LIST_ENTRY(puffs_newcookie) pnc_entries; }; #define PUFFS_SOPREQ_EXPIRE_TIMEOUT 1000 extern int puffs_sopreq_expire_timeout; enum puffs_sopreqtype { PUFFS_SOPREQSYS_EXIT, PUFFS_SOPREQ_FLUSH, PUFFS_SOPREQ_UNMOUNT, PUFFS_SOPREQ_EXPIRE, }; struct puffs_sopreq { union { struct puffs_req preq; struct puffs_flush pf; puffs_cookie_t ck; } psopr_u; enum puffs_sopreqtype psopr_sopreq; TAILQ_ENTRY(puffs_sopreq) psopr_entries; int psopr_at; }; #define psopr_preq psopr_u.preq #define psopr_pf psopr_u.pf #define psopr_ck psopr_u.ck TAILQ_HEAD(puffs_wq, puffs_msgpark); LIST_HEAD(puffs_node_hashlist, puffs_node); struct puffs_mount { kmutex_t pmp_lock; struct puffs_kargs pmp_args; #define pmp_flags pmp_args.pa_flags #define pmp_vnopmask pmp_args.pa_vnopmask struct puffs_wq pmp_msg_touser; int pmp_msg_touser_count; kcondvar_t pmp_msg_waiter_cv; size_t pmp_msg_maxsize; struct puffs_wq pmp_msg_replywait; struct puffs_node_hashlist *pmp_pnodehash; int pmp_npnodehash; LIST_HEAD(, puffs_newcookie) pmp_newcookie; struct mount *pmp_mp; struct vnode *pmp_root; puffs_cookie_t pmp_root_cookie; enum vtype pmp_root_vtype; vsize_t pmp_root_vsize; dev_t pmp_root_rdev; struct putter_instance *pmp_pi; unsigned int pmp_refcount; kcondvar_t pmp_refcount_cv; kcondvar_t pmp_unmounting_cv; uint8_t pmp_unmounting; uint8_t pmp_status; uint8_t pmp_suspend; uint8_t *pmp_curput; size_t pmp_curres; void *pmp_curopaq; uint64_t pmp_nextmsgid; kmutex_t pmp_sopmtx; kcondvar_t pmp_sopcv; int pmp_sopthrcount; TAILQ_HEAD(, puffs_sopreq) pmp_sopfastreqs; TAILQ_HEAD(, puffs_sopreq) pmp_sopnodereqs; bool pmp_docompat; }; #define PUFFSTAT_BEFOREINIT 0 #define PUFFSTAT_MOUNTING 1 #define PUFFSTAT_RUNNING 2 #define PUFFSTAT_DYING 3 /* Do you want your possessions identified? */ #define PNODE_NOREFS 0x001 /* no backend reference */ #define PNODE_DYING 0x002 /* NOREFS + inactive */ #define PNODE_FAF 0x004 /* issue all operations as FAF */ #define PNODE_DOINACT 0x008 /* if inactive-on-demand, call inactive */ #define PNODE_SOPEXP 0x100 /* Node reclaim postponed in sop thread */ #define PNODE_METACACHE_ATIME 0x10 /* cache atime metadata */ #define PNODE_METACACHE_CTIME 0x20 /* cache atime metadata */ #define PNODE_METACACHE_MTIME 0x40 /* cache atime metadata */ #define PNODE_METACACHE_SIZE 0x80 /* cache atime metadata */ #define PNODE_METACACHE_MASK 0xf0 struct puffs_node { struct genfs_node pn_gnode; /* genfs glue */ kmutex_t pn_mtx; int pn_refcount; int pn_nlookup; puffs_cookie_t pn_cookie; /* userspace pnode cookie */ struct vnode *pn_vp; /* backpointer to vnode */ uint32_t pn_stat; /* node status */ struct selinfo pn_sel; /* for selecting on the node */ short pn_revents; /* available events */ /* metacache */ struct timespec pn_mc_atime; struct timespec pn_mc_ctime; struct timespec pn_mc_mtime; u_quad_t pn_mc_size; voff_t pn_serversize; struct lockf * pn_lockf; kmutex_t pn_sizemtx; /* size modification mutex */ int pn_cn_timeout; /* path cache */ int pn_cn_grace; /* grace time before reclaim */ int pn_va_timeout; /* attribute cache */ struct vattr * pn_va_cache; /* attribute cache */ struct vnode * pn_parent; /* parent cache */ LIST_ENTRY(puffs_node) pn_hashent; }; typedef void (*parkdone_fn)(struct puffs_mount *, struct puffs_req *, void *); struct puffs_msgpark; void puffs_msgif_init(void); void puffs_msgif_destroy(void); int puffs_msgmem_alloc(size_t, struct puffs_msgpark **, void **, int); void puffs_msgmem_release(struct puffs_msgpark *); void puffs_sop_thread(void *); void puffs_msg_setfaf(struct puffs_msgpark *); void puffs_msg_setdelta(struct puffs_msgpark *, size_t); void puffs_msg_setinfo(struct puffs_msgpark *, int, int, puffs_cookie_t); void puffs_msg_setcall(struct puffs_msgpark *, parkdone_fn, void *); void puffs_msg_enqueue(struct puffs_mount *, struct puffs_msgpark *); int puffs_msg_wait(struct puffs_mount *, struct puffs_msgpark *); int puffs_msg_wait2(struct puffs_mount *, struct puffs_msgpark *, struct puffs_node *, struct puffs_node *); void puffs_msg_sendresp(struct puffs_mount *, struct puffs_req *, int); int puffs_getvnode(struct mount *, puffs_cookie_t, enum vtype, voff_t, dev_t, struct vnode **); int puffs_newnode(struct mount *, struct vnode *, struct vnode **, puffs_cookie_t, struct componentname *, enum vtype, dev_t); void puffs_putvnode(struct vnode *); void puffs_releasenode(struct puffs_node *); void puffs_referencenode(struct puffs_node *); #define PUFFS_NOSUCHCOOKIE (-1) int puffs_cookie2vnode(struct puffs_mount *, puffs_cookie_t, int, int, struct vnode **); void puffs_makecn(struct puffs_kcn *, struct puffs_kcred *, const struct componentname *, int); void puffs_credcvt(struct puffs_kcred *, kauth_cred_t); void puffs_parkdone_asyncbioread(struct puffs_mount *, struct puffs_req *, void *); void puffs_parkdone_asyncbiowrite(struct puffs_mount *, struct puffs_req *, void *); void puffs_parkdone_poll(struct puffs_mount *, struct puffs_req *, void *); void puffs_mp_reference(struct puffs_mount *); void puffs_mp_release(struct puffs_mount *); void puffs_gop_size(struct vnode *, off_t, off_t *, int); void puffs_gop_markupdate(struct vnode *, int); void puffs_senderr(struct puffs_mount *, int, int, const char *, puffs_cookie_t); bool puffs_compat_outgoing(struct puffs_req *, struct puffs_req**, ssize_t*); void puffs_compat_incoming(struct puffs_req *, struct puffs_req *); void puffs_updatenode(struct puffs_node *, int, voff_t); #define PUFFS_UPDATEATIME 0x01 #define PUFFS_UPDATECTIME 0x02 #define PUFFS_UPDATEMTIME 0x04 #define PUFFS_UPDATESIZE 0x08 void puffs_userdead(struct puffs_mount *); extern int (**puffs_vnodeop_p)(void *); /* for putter */ int puffs_msgif_getout(void *, size_t, int, uint8_t **, size_t *, void **); void puffs_msgif_releaseout(void *, void *, int); int puffs_msgif_dispatch(void *, struct putter_hdr *); size_t puffs_msgif_waitcount(void *); int puffs_msgif_close(void *); static __inline int checkerr(struct puffs_mount *pmp, int error, const char *str) { if (error < 0 || error > ELAST) { puffs_senderr(pmp, PUFFS_ERR_ERROR, error, str, NULL); error = EPROTO; } return error; } #define PUFFS_MSG_VARS(type, a) \ struct puffs_##type##msg_##a *a##_msg; \ struct puffs_msgpark *park_##a = NULL #define PUFFS_MSG_ALLOC(type, a) \ puffs_msgmem_alloc(sizeof(struct puffs_##type##msg_##a), \ &park_##a, (void *)& a##_msg, 1) #define PUFFS_MSG_RELEASE(a) \ do { \ if (park_##a) puffs_msgmem_release(park_##a); \ } while (/*CONSTCOND*/0) #define PUFFS_MSG_ENQUEUEWAIT(pmp, park, var) \ do { \ puffs_msg_enqueue(pmp, park); \ var = puffs_msg_wait(pmp, park); \ } while (/*CONSTCOND*/0) #define PUFFS_MSG_ENQUEUEWAIT2(pmp, park, vp1, vp2, var) \ do { \ puffs_msg_enqueue(pmp, park); \ var = puffs_msg_wait2(pmp, park, vp1, vp2); \ } while (/*CONSTCOND*/0) #endif /* _PUFFS_SYS_H_ */