| 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 | |
| 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 | bool 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 |
| 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 | #endif /* _PUFFS_SYS_H_ */ |
| 363 | |