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 <sys/lockf.h> 58 #include <machine/atomic.h> 59 60 #include "fuse_debug.h" 61 #include "fuse_mount.h" 62 #include "fuse_abi.h" 63 64 #define VFSTOFUSE(mp) ((struct fuse_mount*)((mp)->mnt_data)) 65 #define VTOI(vp) ((struct fuse_node*)((vp)->v_data)) 66 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)) 71 72 SYSCTL_DECL(_vfs_fuse); 73 74 extern int fuse_debug; 75 extern struct vop_ops fuse_vnode_vops; 76 extern struct vop_ops fuse_spec_vops; 77 78 struct fuse_node; 79 80 RB_HEAD(fuse_node_tree, fuse_node); 81 82 struct fuse_mount { 83 struct mount *mp; 84 struct vnode *devvp; 85 struct ucred *cred; 86 struct kqinfo kq; 87 struct fuse_node *rfnp; 88 struct mtx mnt_lock; 89 struct mtx ipc_lock; 90 struct mtx ino_lock; 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 97 98 unsigned int refcnt; 99 unsigned long unique; 100 int dead; 101 uint64_t nosys; 102 uint32_t abi_major; 103 uint32_t abi_minor; 104 uint32_t max_write; 105 }; 106 107 struct fuse_node { 108 RB_ENTRY(fuse_node) node_entry; // inode index entry 109 struct vnode *vp; 110 struct vattr attr; 111 struct fuse_mount *fmp; 112 struct fuse_node *pfnp; 113 struct mtx node_lock; 114 struct lockf advlock; 115 116 uint64_t ino; 117 enum vtype type; 118 size_t size; 119 uint64_t nlookup; 120 uint64_t fh; 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 */ 127 }; 128 129 struct fuse_buf { 130 void *buf; 131 size_t len; 132 }; 133 134 struct fuse_ipc { 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; 140 141 unsigned int refcnt; 142 uint64_t unique; 143 int sent; 144 int done; 145 }; 146 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*); 150 151 int fuse_device_init(void); 152 void fuse_device_cleanup(void); 153 154 void fuse_node_new(struct fuse_mount*, uint64_t, enum vtype, 155 struct fuse_node**); 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); 163 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); 173 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*); 177 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); 185 186 static __inline int 187 fuse_test_dead(struct fuse_mount *fmp) 188 { 189 return atomic_load_acq_int(&fmp->dead); 190 } 191 192 static __inline void 193 fuse_set_dead(struct fuse_mount *fmp) 194 { 195 atomic_store_rel_int(&fmp->dead, 1); 196 } 197 198 static __inline int 199 fuse_test_nosys(struct fuse_mount *fmp, int op) 200 { 201 return atomic_load_acq_64(&fmp->nosys) & (1 << op); 202 } 203 204 static __inline void 205 fuse_set_nosys(struct fuse_mount *fmp, int op) 206 { 207 atomic_set_64(&fmp->nosys, 1 << op); 208 } 209 210 static __inline int 211 fuse_ipc_test_replied(struct fuse_ipc *fip) 212 { 213 return atomic_load_acq_int(&fip->done); 214 } 215 216 static __inline void 217 fuse_ipc_set_replied(struct fuse_ipc *fip) 218 { 219 atomic_store_rel_int(&fip->done, 1); 220 } 221 222 static __inline int 223 fuse_ipc_test_and_set_replied(struct fuse_ipc *fip) 224 { 225 return atomic_cmpset_int(&fip->done, 0, 1); 226 } 227 228 static __inline void* 229 fuse_in(struct fuse_ipc *fip) 230 { 231 return fip->request.buf; 232 } 233 234 static __inline size_t 235 fuse_in_size(struct fuse_ipc *fip) 236 { 237 return fip->request.len; 238 } 239 240 static __inline void* 241 fuse_in_data(struct fuse_ipc *fip) 242 { 243 return (struct fuse_in_header*)fuse_in(fip) + 1; 244 } 245 246 static __inline size_t 247 fuse_in_data_size(struct fuse_ipc *fip) 248 { 249 return fuse_in_size(fip) - sizeof(struct fuse_in_header); 250 } 251 252 static __inline void* 253 fuse_out(struct fuse_ipc *fip) 254 { 255 return fip->reply.buf; 256 } 257 258 static __inline size_t 259 fuse_out_size(struct fuse_ipc *fip) 260 { 261 return fip->reply.len; 262 } 263 264 static __inline void* 265 fuse_out_data(struct fuse_ipc *fip) 266 { 267 return (struct fuse_out_header*)fuse_out(fip) + 1; 268 } 269 270 static __inline size_t 271 fuse_out_data_size(struct fuse_ipc *fip) 272 { 273 return fuse_out_size(fip) - sizeof(struct fuse_out_header); 274 } 275 276 static __inline void 277 fuse_knote(struct vnode *vp, int flags) 278 { 279 if (flags) 280 KNOTE(&vp->v_pollinfo.vpi_kqinfo.ki_note, flags); 281 } 282 283 #endif /* FUSE_FUSE_H */ 284