PageRenderTime 41ms CodeModel.GetById 16ms app.highlight 20ms RepoModel.GetById 1ms app.codeStats 0ms

/core/10.5/fusefs/fuse_ipc.h

http://macfuse.googlecode.com/
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_ */