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 */ 288