2 * Copyright (c) 2019 Tomohiro Kusumi <tkusumi@netbsd.org>
3 * Copyright (c) 2019 The DragonFly Project
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
35 #include <sys/types.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>
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>
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>
57 #include <sys/lockf.h>
58 #include <machine/atomic.h>
60 #include "fuse_debug.h"
61 #include "fuse_mount.h"
64 #define VFSTOFUSE(mp) ((struct fuse_mount*)((mp)->mnt_data))
65 #define VTOI(vp) ((struct fuse_node*)((vp)->v_data))
67 #define FUSE_MAXFILESIZE 0x7FFFFFFFFFFFFFFFLL
68 #define FUSE_BLKSIZE PAGE_SIZE
69 #define FUSE_BLKMASK (FUSE_BLKSIZE - 1)
70 #define FUSE_BLKMASK64 ((off_t)(FUSE_BLKSIZE - 1))
72 SYSCTL_DECL(_vfs_fuse
);
74 extern int fuse_debug
;
75 extern struct vop_ops fuse_vnode_vops
;
76 extern struct vop_ops fuse_spec_vops
;
80 RB_HEAD(fuse_node_tree
, fuse_node
);
87 struct fuse_node
*rfnp
;
91 struct thread
*helper_td
; // helper thread
92 struct spinlock helper_spin
; // protect bioq
93 TAILQ_HEAD(, bio
) bioq
; // bioq for strategy I/Os
94 TAILQ_HEAD(,fuse_ipc
) request_head
;
95 TAILQ_HEAD(,fuse_ipc
) reply_head
;
96 struct fuse_node_tree node_head
; // inode index
108 RB_ENTRY(fuse_node
) node_entry
; // inode index entry
111 struct fuse_mount
*fmp
;
112 struct fuse_node
*pfnp
;
113 struct mtx node_lock
;
114 struct lockf advlock
;
121 bool closed
; /* XXX associated with closed fh */
122 int modified
: 1; /* file modified */
123 int changed
: 1; /* file inode changed */
124 int accessed
: 1; /* file accessed */
125 int attrgood
: 1; /* have valid attributes */
126 int sizeoverride
: 1; /* override attr size with fnp->size */
135 struct fuse_mount
*fmp
;
136 struct fuse_buf request
;
137 struct fuse_buf reply
;
138 TAILQ_ENTRY(fuse_ipc
) request_entry
;
139 TAILQ_ENTRY(fuse_ipc
) reply_entry
;
147 int fuse_cmp_version(struct fuse_mount
*, uint32_t, uint32_t);
148 int fuse_mount_kill(struct fuse_mount
*);
149 int fuse_mount_free(struct fuse_mount
*);
151 int fuse_device_init(void);
152 void fuse_device_cleanup(void);
154 void fuse_node_new(struct fuse_mount
*, uint64_t, enum vtype
,
156 void fuse_node_free(struct fuse_mount
*, struct fuse_node
*);
157 int fuse_alloc_node(struct fuse_mount
*, struct fuse_node
*,
158 uint64_t, enum vtype
, struct vnode
**);
159 int fuse_node_vn(struct fuse_node
*, struct vnode
**);
160 int fuse_node_truncate(struct fuse_node
*, size_t, size_t);
161 void fuse_node_init(void);
162 void fuse_node_cleanup(void);
164 void fuse_buf_alloc(struct fuse_buf
*, size_t);
165 void fuse_buf_free(struct fuse_buf
*);
166 struct fuse_ipc
*fuse_ipc_get(struct fuse_mount
*, size_t);
167 void fuse_ipc_put(struct fuse_ipc
*);
168 void *fuse_ipc_fill(struct fuse_ipc
*, int, uint64_t, struct ucred
*);
169 int fuse_ipc_tx(struct fuse_ipc
*);
170 int fuse_ipc_tx_noreply(struct fuse_ipc
*);
171 void fuse_ipc_init(void);
172 void fuse_ipc_cleanup(void);
174 int fuse_read(struct vop_read_args
*);
175 int fuse_write(struct vop_write_args
*);
176 int fuse_dio_write(struct vop_write_args
*);
178 void fuse_hexdump(const char*, size_t);
179 void fuse_fill_in_header(struct fuse_in_header
*, uint32_t, uint32_t, uint64_t,
180 uint64_t, uint32_t, uint32_t, uint32_t);
181 int fuse_forget_node(struct fuse_mount
*, uint64_t, uint64_t, struct ucred
*);
182 int fuse_audit_length(struct fuse_in_header
*, struct fuse_out_header
*);
183 const char *fuse_get_ops(int);
184 void fuse_io_thread(void *arg
);
187 fuse_test_dead(struct fuse_mount
*fmp
)
189 return atomic_load_acq_int(&fmp
->dead
);
193 fuse_set_dead(struct fuse_mount
*fmp
)
195 atomic_store_rel_int(&fmp
->dead
, 1);
199 fuse_test_nosys(struct fuse_mount
*fmp
, int op
)
201 return atomic_load_acq_64(&fmp
->nosys
) & (1 << op
);
205 fuse_set_nosys(struct fuse_mount
*fmp
, int op
)
207 atomic_set_64(&fmp
->nosys
, 1 << op
);
211 fuse_ipc_test_replied(struct fuse_ipc
*fip
)
213 return atomic_load_acq_int(&fip
->done
);
217 fuse_ipc_set_replied(struct fuse_ipc
*fip
)
219 atomic_store_rel_int(&fip
->done
, 1);
223 fuse_ipc_test_and_set_replied(struct fuse_ipc
*fip
)
225 return atomic_cmpset_int(&fip
->done
, 0, 1);
228 static __inline
void*
229 fuse_in(struct fuse_ipc
*fip
)
231 return fip
->request
.buf
;
234 static __inline
size_t
235 fuse_in_size(struct fuse_ipc
*fip
)
237 return fip
->request
.len
;
240 static __inline
void*
241 fuse_in_data(struct fuse_ipc
*fip
)
243 return (struct fuse_in_header
*)fuse_in(fip
) + 1;
246 static __inline
size_t
247 fuse_in_data_size(struct fuse_ipc
*fip
)
249 return fuse_in_size(fip
) - sizeof(struct fuse_in_header
);
252 static __inline
void*
253 fuse_out(struct fuse_ipc
*fip
)
255 return fip
->reply
.buf
;
258 static __inline
size_t
259 fuse_out_size(struct fuse_ipc
*fip
)
261 return fip
->reply
.len
;
264 static __inline
void*
265 fuse_out_data(struct fuse_ipc
*fip
)
267 return (struct fuse_out_header
*)fuse_out(fip
) + 1;
270 static __inline
size_t
271 fuse_out_data_size(struct fuse_ipc
*fip
)
273 return fuse_out_size(fip
) - sizeof(struct fuse_out_header
);
277 fuse_knote(struct vnode
*vp
, int flags
)
280 KNOTE(&vp
->v_pollinfo
.vpi_kqinfo
.ki_note
, flags
);
283 #endif /* FUSE_FUSE_H */