/core/10.5/fusefs/fuse_ipc.h
C++ Header | 376 lines | 304 code | 64 blank | 8 comment | 4 complexity | a0799478e7c9b43b2b177441815ff22b MD5 | raw file
1/* 2 * Copyright (C) 2006-2008 Google. All Rights Reserved. 3 * Amit Singh <singh@> 4 */ 5 6#ifndef _FUSE_IPC_H_ 7#define _FUSE_IPC_H_ 8 9#include <mach/mach_types.h> 10#include <sys/errno.h> 11#include <sys/mount.h> 12#include <sys/vnode.h> 13#include <sys/vnode_if.h> 14#include <sys/kernel_types.h> 15#include <sys/stat.h> 16#include <sys/dirent.h> 17#include <sys/uio.h> 18#include <sys/proc.h> 19#include <sys/vm.h> 20#include <sys/fcntl.h> 21#include <sys/select.h> 22#include <kern/assert.h> 23#include <libkern/libkern.h> 24#include <libkern/OSMalloc.h> 25#include <libkern/locks.h> 26 27#include "fuse.h" 28#include "fuse_device.h" 29#include "fuse_kludges.h" 30#include "fuse_locking.h" 31 32struct fuse_iov { 33 void *base; 34 size_t len; 35 size_t allocated_size; 36 ssize_t credit; 37}; 38 39#define FUSE_DATA_LOCK_SHARED(d) fuse_lck_rw_lock_shared((d)->rwlock) 40#define FUSE_DATA_LOCK_EXCLUSIVE(d) fuse_lck_rw_lock_exclusive((d)->rwlock) 41#define FUSE_DATA_UNLOCK_SHARED(d) fuse_lck_rw_unlock_shared((d)->rwlock) 42#define FUSE_DATA_UNLOCK_EXCLUSIVE(d) fuse_lck_rw_unlock_exclusive((d)->rwlock) 43 44void fiov_init(struct fuse_iov *fiov, size_t size); 45void fiov_teardown(struct fuse_iov *fiov); 46void fiov_refresh(struct fuse_iov *fiov); 47void fiov_adjust(struct fuse_iov *fiov, size_t size); 48int fiov_adjust_canfail(struct fuse_iov *fiov, size_t size); 49 50#define FUSE_DIMALLOC(fiov, spc1, spc2, amnt) \ 51do { \ 52 fiov_adjust(fiov, (sizeof(*(spc1)) + (amnt))); \ 53 (spc1) = (fiov)->base; \ 54 (spc2) = (char *)(fiov)->base + (sizeof(*(spc1))); \ 55} while (0) 56 57#define FU_AT_LEAST(siz) max((size_t)(siz), (size_t)160) 58 59struct fuse_ticket; 60struct fuse_data; 61 62typedef int fuse_handler_t(struct fuse_ticket *ftick, uio_t uio); 63 64struct fuse_ticket { 65 uint64_t tk_unique; 66 struct fuse_data *tk_data; 67 int tk_flag; 68 uint32_t tk_age; 69 70 STAILQ_ENTRY(fuse_ticket) tk_freetickets_link; 71 TAILQ_ENTRY(fuse_ticket) tk_alltickets_link; 72 73 struct fuse_iov tk_ms_fiov; 74 void *tk_ms_bufdata; 75 size_t tk_ms_bufsize; 76 enum { FT_M_FIOV, FT_M_BUF } tk_ms_type; 77 STAILQ_ENTRY(fuse_ticket) tk_ms_link; 78 79 struct fuse_iov tk_aw_fiov; 80 void *tk_aw_bufdata; 81 size_t tk_aw_bufsize; 82 enum { FT_A_FIOV, FT_A_BUF } tk_aw_type; 83 84 struct fuse_out_header tk_aw_ohead; 85 int tk_aw_errno; 86 lck_mtx_t *tk_aw_mtx; 87 fuse_handler_t *tk_aw_handler; 88 TAILQ_ENTRY(fuse_ticket) tk_aw_link; 89}; 90 91#define FT_ANSW 0x01 // request of ticket has already been answered 92#define FT_INVAL 0x02 // ticket is invalidated 93#define FT_DIRTY 0x04 // ticket has been used 94#define FT_KILLL 0x08 // ticket has been marked for death (KILLL => KILL_LATER) 95 96static __inline__ 97struct fuse_iov * 98fticket_resp(struct fuse_ticket *ftick) 99{ 100 return &ftick->tk_aw_fiov; 101} 102 103static __inline__ 104int 105fticket_answered(struct fuse_ticket *ftick) 106{ 107 return (ftick->tk_flag & FT_ANSW); 108} 109 110static __inline__ 111void 112fticket_set_answered(struct fuse_ticket *ftick) 113{ 114 ftick->tk_flag |= FT_ANSW; 115} 116 117static __inline__ 118void 119fticket_set_killl(struct fuse_ticket *ftick) 120{ 121 ftick->tk_flag |= FT_KILLL; 122} 123 124static __inline__ 125enum fuse_opcode 126fticket_opcode(struct fuse_ticket *ftick) 127{ 128 return (((struct fuse_in_header *)(ftick->tk_ms_fiov.base))->opcode); 129} 130 131static __inline__ 132void 133fticket_invalidate(struct fuse_ticket *ftick) 134{ 135 ftick->tk_flag |= FT_INVAL; 136} 137 138int fticket_pull(struct fuse_ticket *ftick, uio_t uio); 139 140enum mount_state { FM_NOTMOUNTED, FM_MOUNTED }; 141 142struct fuse_data { 143 fuse_device_t fdev; 144 mount_t mp; 145 vnode_t rootvp; 146 enum mount_state mount_state; 147 kauth_cred_t daemoncred; 148 pid_t daemonpid; 149 uint32_t dataflags; /* effective fuse_data flags */ 150 uint64_t mountaltflags; /* as-is copy of altflags */ 151 uint64_t noimplflags; /* not-implemented flags */ 152 153#if M_MACFUSE_ENABLE_DSELECT 154 struct fuse_selinfo d_rsel; 155#endif /* M_MACFUSE_ENABLE_DSELECT */ 156 157 lck_rw_t *rwlock; 158 159 lck_mtx_t *ms_mtx; 160 STAILQ_HEAD(, fuse_ticket) ms_head; 161 162 lck_mtx_t *aw_mtx; 163 TAILQ_HEAD(, fuse_ticket) aw_head; 164 165 lck_mtx_t *ticket_mtx; 166 STAILQ_HEAD(, fuse_ticket) freetickets_head; 167 TAILQ_HEAD(, fuse_ticket) alltickets_head; 168 uint32_t freeticket_counter; 169 uint32_t deadticket_counter; 170 uint64_t ticketer; 171 172#if M_MACFUSE_EXPLICIT_RENAME_LOCK 173 lck_rw_t *rename_lock; 174#endif /* M_MACFUSE_EXPLICIT_RENAME_LOCK */ 175 176 uint32_t fuse_libabi_major; 177 uint32_t fuse_libabi_minor; 178 179 uint32_t max_write; 180 uint32_t max_read; 181 uint32_t blocksize; 182 uint32_t iosize; 183 uint32_t userkernel_bufsize; 184 uint32_t fssubtype; 185 char volname[MAXPATHLEN]; 186 187 uint32_t timeout_status; 188 lck_mtx_t *timeout_mtx; 189 struct timespec daemon_timeout; 190 struct timespec *daemon_timeout_p; 191 struct timespec init_timeout; 192}; 193 194enum { 195 FUSE_DAEMON_TIMEOUT_NONE = 0, 196 FUSE_DAEMON_TIMEOUT_PROCESSING = 1, 197 FUSE_DAEMON_TIMEOUT_DEAD = 2, 198}; 199 200/* Not-Implemented Bits */ 201#define FSESS_NOIMPLBIT(MSG) (1ULL << FUSE_##MSG) 202 203#define FSESS_DEAD 0x00000001 // session is to be closed 204#define FSESS_OPENED 0x00000002 // session device has been opened 205#define FSESS_INITED 0x00000004 // session has been inited 206#define FSESS_UNCONSCIOUS 0x00000008 // session is temporarily gone 207 208#define FSESS_ALLOW_OTHER 0x00000010 209#define FSESS_ALLOW_ROOT 0x00000020 210#define FSESS_AUTO_XATTR 0x00000040 211#define FSESS_DEFAULT_PERMISSIONS 0x00000080 212#define FSESS_DEFER_PERMISSIONS 0x00000100 213#define FSESS_DIRECT_IO 0x00000200 214#define FSESS_EXTENDED_SECURITY 0x00000400 215#define FSESS_JAIL_SYMLINKS 0x00000800 216#define FSESS_KILL_ON_UNMOUNT 0x00001000 217#define FSESS_LOCALVOL 0x00002000 218#define FSESS_NEGATIVE_VNCACHE 0x00004000 219#define FSESS_NO_ALERTS 0x00008000 220#define FSESS_NO_APPLEDOUBLE 0x00010000 221#define FSESS_NO_APPLEXATTR 0x00020000 222#define FSESS_NO_ATTRCACHE 0x00040000 223#define FSESS_NO_READAHEAD 0x00080000 224#define FSESS_NO_SYNCONCLOSE 0x00100000 225#define FSESS_NO_SYNCWRITES 0x00200000 226#define FSESS_NO_UBC 0x00400000 227#define FSESS_NO_VNCACHE 0x00800000 228#define FSESS_CASE_INSENSITIVE 0x01000000 229#define FSESS_VOL_RENAME 0x02000000 230#define FSESS_XTIMES 0x04000000 231#define FSESS_AUTO_CACHE 0x08000000 232#define FSESS_NATIVE_XATTR 0x10000000 233#define FSESS_SPARSE 0x20000000 234 235static __inline__ 236struct fuse_data * 237fuse_get_mpdata(mount_t mp) 238{ 239 /* 240 * data->mount_state should be FM_MOUNTED for it to be valid 241 */ 242 return (struct fuse_data *)vfs_fsprivate(mp); 243} 244 245static __inline__ 246void 247fuse_ms_push(struct fuse_ticket *ftick) 248{ 249 STAILQ_INSERT_TAIL(&ftick->tk_data->ms_head, ftick, tk_ms_link); 250} 251 252static __inline__ 253void 254fuse_ms_push_head(struct fuse_ticket *ftick) 255{ 256 STAILQ_INSERT_HEAD(&ftick->tk_data->ms_head, ftick, tk_ms_link); 257} 258 259static __inline__ 260struct fuse_ticket * 261fuse_ms_pop(struct fuse_data *data) 262{ 263 struct fuse_ticket *ftick = NULL; 264 265 if ((ftick = STAILQ_FIRST(&data->ms_head))) { 266 STAILQ_REMOVE_HEAD(&data->ms_head, tk_ms_link); 267 } 268 269 return ftick; 270} 271 272static __inline__ 273void 274fuse_aw_push(struct fuse_ticket *ftick) 275{ 276 TAILQ_INSERT_TAIL(&ftick->tk_data->aw_head, ftick, tk_aw_link); 277} 278 279static __inline__ 280void 281fuse_aw_remove(struct fuse_ticket *ftick) 282{ 283 TAILQ_REMOVE(&ftick->tk_data->aw_head, ftick, tk_aw_link); 284} 285 286static __inline__ 287struct fuse_ticket * 288fuse_aw_pop(struct fuse_data *data) 289{ 290 struct fuse_ticket *ftick = NULL; 291 292 if ((ftick = TAILQ_FIRST(&data->aw_head))) { 293 fuse_aw_remove(ftick); 294 } 295 296 return ftick; 297} 298 299struct fuse_ticket *fuse_ticket_fetch(struct fuse_data *data); 300void fuse_ticket_drop(struct fuse_ticket *ftick); 301void fuse_ticket_drop_invalid(struct fuse_ticket *ftick); 302void fuse_ticket_kill(struct fuse_ticket *ftick); 303void fuse_insert_callback(struct fuse_ticket *ftick, fuse_handler_t *handler); 304void fuse_insert_message(struct fuse_ticket *ftick); 305void fuse_insert_message_head(struct fuse_ticket *ftick); 306 307static __inline__ 308int 309fuse_libabi_geq(struct fuse_data *data, uint32_t abi_maj, uint32_t abi_min) 310{ 311 return (data->fuse_libabi_major > abi_maj || 312 (data->fuse_libabi_major == abi_maj && 313 data->fuse_libabi_minor >= abi_min)); 314} 315 316struct fuse_data *fdata_alloc(struct proc *p); 317void fdata_destroy(struct fuse_data *data); 318int fdata_dead_get(struct fuse_data *data); 319void fdata_set_dead(struct fuse_data *data); 320 321struct fuse_dispatcher { 322 323 struct fuse_ticket *tick; 324 struct fuse_in_header *finh; 325 326 void *indata; 327 size_t iosize; 328 uint64_t nodeid; 329 int answ_stat; 330 void *answ; 331}; 332 333static __inline__ 334void 335fdisp_init(struct fuse_dispatcher *fdisp, size_t iosize) 336{ 337 fdisp->iosize = iosize; 338 fdisp->tick = NULL; 339} 340 341void fdisp_make(struct fuse_dispatcher *fdip, enum fuse_opcode op, 342 mount_t mp, uint64_t nid, vfs_context_t context); 343 344int fdisp_make_canfail(struct fuse_dispatcher *fdip, enum fuse_opcode op, 345 mount_t mp, uint64_t nid, vfs_context_t context); 346 347void fdisp_make_vp(struct fuse_dispatcher *fdip, enum fuse_opcode op, 348 vnode_t vp, vfs_context_t context); 349 350int fdisp_make_vp_canfail(struct fuse_dispatcher *fdip, enum fuse_opcode op, 351 vnode_t vp, vfs_context_t context); 352 353int fdisp_wait_answ(struct fuse_dispatcher *fdip); 354 355static __inline__ 356int 357fdisp_simple_putget_vp(struct fuse_dispatcher *fdip, enum fuse_opcode op, 358 vnode_t vp, vfs_context_t context) 359{ 360 fdisp_init(fdip, 0); 361 fdisp_make_vp(fdip, op, vp, context); 362 return fdisp_wait_answ(fdip); 363} 364 365static __inline__ 366int 367fdisp_simple_vfs_getattr(struct fuse_dispatcher *fdip, 368 mount_t mp, 369 vfs_context_t context) 370{ 371 fdisp_init(fdip, 0); 372 fdisp_make(fdip, FUSE_STATFS, mp, FUSE_ROOT_ID, context); 373 return fdisp_wait_answ(fdip); 374} 375 376#endif /* _FUSE_IPC_H_ */