sys/vfs/fuse: Add initial FUSE support
[dragonfly.git] / sys / vfs / fuse / fuse.h
1 /*-
2  * Copyright (c) 2019 Tomohiro Kusumi <tkusumi@netbsd.org>
3  * Copyright (c) 2019 The DragonFly Project
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #ifndef FUSE_FUSE_H
29 #define FUSE_FUSE_H
30
31 #ifndef INVARIANTS
32 #define INVARIANTS
33 #endif
34
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
39 #include <sys/module.h>
40 #include <sys/malloc.h>
41 #include <sys/objcache.h>
42 #include <sys/proc.h>
43 #include <sys/thread.h>
44 #include <sys/mutex.h>
45 #include <sys/mutex2.h>
46 #include <sys/refcount.h>
47 #include <sys/event.h>
48 #include <sys/mount.h>
49 #include <sys/vnode.h>
50 #include <sys/file.h>
51 #include <sys/ucred.h>
52 #include <sys/unistd.h>
53 #include <sys/sysctl.h>
54 #include <sys/errno.h>
55 #include <sys/queue.h>
56 #include <sys/tree.h>
57 #include <machine/atomic.h>
58
59 #include "fuse_debug.h"
60 #include "fuse_mount.h"
61 #include "fuse_abi.h"
62
63 #define VFSTOFUSE(mp) ((struct fuse_mount*)((mp)->mnt_data))
64 #define VTOI(vp) ((struct fuse_node*)((vp)->v_data))
65
66 #define FUSE_BLKSIZE PAGE_SIZE
67 #define FUSE_BLKMASK (FUSE_BLKSIZE - 1)
68 #define FUSE_BLKMASK64 ((off_t)(FUSE_BLKSIZE - 1))
69
70 SYSCTL_DECL(_vfs_fuse);
71
72 extern int fuse_debug;
73 extern struct vop_ops fuse_vnode_vops;
74 extern struct vop_ops fuse_spec_vops;
75
76 struct fuse_mount {
77         struct mount *mp;
78         struct vnode *devvp;
79         struct ucred *cred;
80         struct kqinfo kq;
81         struct fuse_node *rfnp;
82         struct mtx mnt_lock;
83         struct mtx ipc_lock;
84         TAILQ_HEAD(,fuse_ipc) request_head;
85         TAILQ_HEAD(,fuse_ipc) reply_head;
86
87         unsigned int refcnt;
88         unsigned long unique;
89         int dead;
90         uint64_t nosys;
91         uint32_t abi_major;
92         uint32_t abi_minor;
93         uint32_t max_write;
94 };
95
96 RB_HEAD(fuse_dent_tree, fuse_dent);
97
98 struct fuse_node {
99         struct vnode *vp;
100         struct vattr attr;
101         struct fuse_mount *fmp;
102         struct fuse_node *pfnp;
103         struct mtx node_lock;
104         struct fuse_dent_tree dent_head;
105
106         uint64_t ino;
107         enum vtype type;
108         int nlink;
109         size_t size;
110         uint64_t nlookup;
111         uint64_t fh;
112         bool closed; /* XXX associated with closed fh */
113 };
114
115 struct fuse_dent {
116         struct fuse_node *fnp;
117         RB_ENTRY(fuse_dent) dent_entry;
118
119         char *name;
120 };
121
122 struct fuse_buf {
123         void *buf;
124         size_t len;
125 };
126
127 struct fuse_ipc {
128         struct fuse_mount *fmp;
129         struct fuse_buf request;
130         struct fuse_buf reply;
131         TAILQ_ENTRY(fuse_ipc) request_entry;
132         TAILQ_ENTRY(fuse_ipc) reply_entry;
133
134         unsigned int refcnt;
135         uint64_t unique;
136         int done;
137 };
138
139 int fuse_cmp_version(struct fuse_mount*, uint32_t, uint32_t);
140 int fuse_mount_kill(struct fuse_mount*);
141 int fuse_mount_free(struct fuse_mount*);
142
143 int fuse_device_init(void);
144 void fuse_device_cleanup(void);
145
146 void fuse_node_new(struct fuse_mount*, uint64_t, enum vtype,
147     struct fuse_node**);
148 void fuse_node_free(struct fuse_node*);
149 void fuse_dent_new(struct fuse_node*, const char*, int, struct fuse_dent**);
150 void fuse_dent_free(struct fuse_dent*);
151 void fuse_dent_attach(struct fuse_node*, struct fuse_dent*);
152 void fuse_dent_detach(struct fuse_node*, struct fuse_dent*);
153 int fuse_dent_find(struct fuse_node*, const char*, int, struct fuse_dent**);
154 int fuse_alloc_node(struct fuse_node*, uint64_t, const char*, int, enum vtype,
155     struct vnode**);
156 int fuse_node_vn(struct fuse_node*, int, struct vnode**);
157 int fuse_node_truncate(struct fuse_node*, size_t, size_t);
158 void fuse_node_init(void);
159 void fuse_node_cleanup(void);
160
161 uint64_t fuse_fh(struct file*);
162 void fuse_get_fh(struct file*, uint64_t);
163 void fuse_put_fh(struct file*);
164 uint64_t fuse_nfh(struct fuse_node*);
165 void fuse_get_nfh(struct fuse_node*, uint64_t);
166 void fuse_put_nfh(struct fuse_node*);
167 void fuse_file_init(void);
168 void fuse_file_cleanup(void);
169
170 void fuse_buf_alloc(struct fuse_buf*, size_t);
171 void fuse_buf_free(struct fuse_buf*);
172 struct fuse_ipc *fuse_ipc_get(struct fuse_mount*, size_t);
173 void fuse_ipc_put(struct fuse_ipc*);
174 void *fuse_ipc_fill(struct fuse_ipc*, int, uint64_t, struct ucred*);
175 int fuse_ipc_tx(struct fuse_ipc*);
176 void fuse_ipc_init(void);
177 void fuse_ipc_cleanup(void);
178
179 int fuse_read(struct vop_read_args*);
180 int fuse_write(struct vop_write_args*);
181 int fuse_dio_write(struct vop_write_args*);
182
183 void fuse_hexdump(const char*, size_t);
184 void fuse_fill_in_header(struct fuse_in_header*, uint32_t, uint32_t, uint64_t,
185     uint64_t, uint32_t, uint32_t, uint32_t);
186 int fuse_forget_node(struct fuse_mount*, uint64_t, uint64_t, struct ucred*);
187 int fuse_audit_length(struct fuse_in_header*, struct fuse_out_header*);
188 const char *fuse_get_ops(int);
189
190 static __inline int
191 fuse_test_dead(struct fuse_mount *fmp)
192 {
193         return atomic_load_acq_int(&fmp->dead);
194 }
195
196 static __inline void
197 fuse_set_dead(struct fuse_mount *fmp)
198 {
199         atomic_store_rel_int(&fmp->dead, 1);
200 }
201
202 static __inline int
203 fuse_test_nosys(struct fuse_mount *fmp, int op)
204 {
205         return atomic_load_acq_64(&fmp->nosys) & (1 << op);
206 }
207
208 static __inline void
209 fuse_set_nosys(struct fuse_mount *fmp, int op)
210 {
211         atomic_set_64(&fmp->nosys, 1 << op);
212 }
213
214 static __inline int
215 fuse_ipc_test_replied(struct fuse_ipc *fip)
216 {
217         return atomic_load_acq_int(&fip->done);
218 }
219
220 static __inline void
221 fuse_ipc_set_replied(struct fuse_ipc *fip)
222 {
223         atomic_store_rel_int(&fip->done, 1);
224 }
225
226 static __inline int
227 fuse_ipc_test_and_set_replied(struct fuse_ipc *fip)
228 {
229         return atomic_cmpset_int(&fip->done, 0, 1);
230 }
231
232 static __inline void*
233 fuse_in(struct fuse_ipc *fip)
234 {
235         return fip->request.buf;
236 }
237
238 static __inline size_t
239 fuse_in_size(struct fuse_ipc *fip)
240 {
241         return fip->request.len;
242 }
243
244 static __inline void*
245 fuse_in_data(struct fuse_ipc *fip)
246 {
247         return (struct fuse_in_header*)fuse_in(fip) + 1;
248 }
249
250 static __inline size_t
251 fuse_in_data_size(struct fuse_ipc *fip)
252 {
253         return fuse_in_size(fip) - sizeof(struct fuse_in_header);
254 }
255
256 static __inline void*
257 fuse_out(struct fuse_ipc *fip)
258 {
259         return fip->reply.buf;
260 }
261
262 static __inline size_t
263 fuse_out_size(struct fuse_ipc *fip)
264 {
265         return fip->reply.len;
266 }
267
268 static __inline void*
269 fuse_out_data(struct fuse_ipc *fip)
270 {
271         return (struct fuse_out_header*)fuse_out(fip) + 1;
272 }
273
274 static __inline size_t
275 fuse_out_data_size(struct fuse_ipc *fip)
276 {
277         return fuse_out_size(fip) - sizeof(struct fuse_out_header);
278 }
279
280 static __inline void
281 fuse_knote(struct vnode *vp, int flags)
282 {
283         if (flags)
284                 KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags);
285 }
286
287 #endif /* FUSE_FUSE_H */