| .. | .. |
|---|
| 9 | 9 | #ifndef _FS_FUSE_I_H |
|---|
| 10 | 10 | #define _FS_FUSE_I_H |
|---|
| 11 | 11 | |
|---|
| 12 | +#ifndef pr_fmt |
|---|
| 13 | +# define pr_fmt(fmt) "fuse: " fmt |
|---|
| 14 | +#endif |
|---|
| 15 | + |
|---|
| 12 | 16 | #include <linux/fuse.h> |
|---|
| 13 | 17 | #include <linux/fs.h> |
|---|
| 14 | 18 | #include <linux/mount.h> |
|---|
| .. | .. |
|---|
| 28 | 32 | #include <linux/refcount.h> |
|---|
| 29 | 33 | #include <linux/user_namespace.h> |
|---|
| 30 | 34 | |
|---|
| 31 | | -/** Max number of pages that can be used in a single read request */ |
|---|
| 32 | | -#define FUSE_MAX_PAGES_PER_REQ 32 |
|---|
| 35 | +/** Default max number of pages that can be used in a single read request */ |
|---|
| 36 | +#define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32 |
|---|
| 37 | + |
|---|
| 38 | +/** Maximum of max_pages received in init_out */ |
|---|
| 39 | +#define FUSE_MAX_MAX_PAGES 256 |
|---|
| 33 | 40 | |
|---|
| 34 | 41 | /** Bias for fi->writectr, meaning new writepages must not be sent */ |
|---|
| 35 | 42 | #define FUSE_NOWRITE INT_MIN |
|---|
| .. | .. |
|---|
| 39 | 46 | |
|---|
| 40 | 47 | /** Number of dentries for each connection in the control filesystem */ |
|---|
| 41 | 48 | #define FUSE_CTL_NUM_DENTRIES 5 |
|---|
| 42 | | - |
|---|
| 43 | | -/** Number of page pointers embedded in fuse_req */ |
|---|
| 44 | | -#define FUSE_REQ_INLINE_PAGES 1 |
|---|
| 45 | 49 | |
|---|
| 46 | 50 | /** List of active connections */ |
|---|
| 47 | 51 | extern struct list_head fuse_conn_list; |
|---|
| .. | .. |
|---|
| 77 | 81 | /** Time in jiffies until the file attributes are valid */ |
|---|
| 78 | 82 | u64 i_time; |
|---|
| 79 | 83 | |
|---|
| 84 | + /* Which attributes are invalid */ |
|---|
| 85 | + u32 inval_mask; |
|---|
| 86 | + |
|---|
| 80 | 87 | /** The sticky bit in inode->i_mode may have been removed, so |
|---|
| 81 | 88 | preserve the original mode */ |
|---|
| 82 | 89 | umode_t orig_i_mode; |
|---|
| .. | .. |
|---|
| 87 | 94 | /** Version of last attribute change */ |
|---|
| 88 | 95 | u64 attr_version; |
|---|
| 89 | 96 | |
|---|
| 90 | | - /** Files usable in writepage. Protected by fc->lock */ |
|---|
| 91 | | - struct list_head write_files; |
|---|
| 97 | + union { |
|---|
| 98 | + /* Write related fields (regular file only) */ |
|---|
| 99 | + struct { |
|---|
| 100 | + /* Files usable in writepage. Protected by fi->lock */ |
|---|
| 101 | + struct list_head write_files; |
|---|
| 92 | 102 | |
|---|
| 93 | | - /** Writepages pending on truncate or fsync */ |
|---|
| 94 | | - struct list_head queued_writes; |
|---|
| 103 | + /* Writepages pending on truncate or fsync */ |
|---|
| 104 | + struct list_head queued_writes; |
|---|
| 95 | 105 | |
|---|
| 96 | | - /** Number of sent writes, a negative bias (FUSE_NOWRITE) |
|---|
| 97 | | - * means more writes are blocked */ |
|---|
| 98 | | - int writectr; |
|---|
| 106 | + /* Number of sent writes, a negative bias |
|---|
| 107 | + * (FUSE_NOWRITE) means more writes are blocked */ |
|---|
| 108 | + int writectr; |
|---|
| 99 | 109 | |
|---|
| 100 | | - /** Waitq for writepage completion */ |
|---|
| 101 | | - wait_queue_head_t page_waitq; |
|---|
| 110 | + /* Waitq for writepage completion */ |
|---|
| 111 | + wait_queue_head_t page_waitq; |
|---|
| 102 | 112 | |
|---|
| 103 | | - /** List of writepage requestst (pending or sent) */ |
|---|
| 104 | | - struct list_head writepages; |
|---|
| 113 | + /* List of writepage requestst (pending or sent) */ |
|---|
| 114 | + struct rb_root writepages; |
|---|
| 115 | + }; |
|---|
| 116 | + |
|---|
| 117 | + /* readdir cache (directory only) */ |
|---|
| 118 | + struct { |
|---|
| 119 | + /* true if fully cached */ |
|---|
| 120 | + bool cached; |
|---|
| 121 | + |
|---|
| 122 | + /* size of cache */ |
|---|
| 123 | + loff_t size; |
|---|
| 124 | + |
|---|
| 125 | + /* position at end of cache (position of next entry) */ |
|---|
| 126 | + loff_t pos; |
|---|
| 127 | + |
|---|
| 128 | + /* version of the cache */ |
|---|
| 129 | + u64 version; |
|---|
| 130 | + |
|---|
| 131 | + /* modification time of directory when cache was |
|---|
| 132 | + * started */ |
|---|
| 133 | + struct timespec64 mtime; |
|---|
| 134 | + |
|---|
| 135 | + /* iversion of directory when cache was started */ |
|---|
| 136 | + u64 iversion; |
|---|
| 137 | + |
|---|
| 138 | + /* protects above fields */ |
|---|
| 139 | + spinlock_t lock; |
|---|
| 140 | + } rdc; |
|---|
| 141 | + }; |
|---|
| 105 | 142 | |
|---|
| 106 | 143 | /** Miscellaneous bits describing inode state */ |
|---|
| 107 | 144 | unsigned long state; |
|---|
| 108 | 145 | |
|---|
| 109 | 146 | /** Lock for serializing lookup and readdir for back compatibility*/ |
|---|
| 110 | 147 | struct mutex mutex; |
|---|
| 148 | + |
|---|
| 149 | + /** Lock to protect write related fields */ |
|---|
| 150 | + spinlock_t lock; |
|---|
| 151 | + |
|---|
| 152 | + /** |
|---|
| 153 | + * Can't take inode lock in fault path (leads to circular dependency). |
|---|
| 154 | + * Introduce another semaphore which can be taken in fault path and |
|---|
| 155 | + * then other filesystem paths can take this to block faults. |
|---|
| 156 | + */ |
|---|
| 157 | + struct rw_semaphore i_mmap_sem; |
|---|
| 158 | + |
|---|
| 159 | +#ifdef CONFIG_FUSE_DAX |
|---|
| 160 | + /* |
|---|
| 161 | + * Dax specific inode data |
|---|
| 162 | + */ |
|---|
| 163 | + struct fuse_inode_dax *dax; |
|---|
| 164 | +#endif |
|---|
| 111 | 165 | }; |
|---|
| 112 | 166 | |
|---|
| 113 | 167 | /** FUSE inode state bits */ |
|---|
| .. | .. |
|---|
| 123 | 177 | }; |
|---|
| 124 | 178 | |
|---|
| 125 | 179 | struct fuse_conn; |
|---|
| 180 | +struct fuse_mount; |
|---|
| 181 | +struct fuse_release_args; |
|---|
| 182 | + |
|---|
| 183 | +/** |
|---|
| 184 | + * Reference to lower filesystem file for read/write operations handled in |
|---|
| 185 | + * passthrough mode. |
|---|
| 186 | + * This struct also tracks the credentials to be used for handling read/write |
|---|
| 187 | + * operations. |
|---|
| 188 | + */ |
|---|
| 189 | +struct fuse_passthrough { |
|---|
| 190 | + struct file *filp; |
|---|
| 191 | + struct cred *cred; |
|---|
| 192 | +}; |
|---|
| 126 | 193 | |
|---|
| 127 | 194 | /** FUSE specific file data */ |
|---|
| 128 | 195 | struct fuse_file { |
|---|
| 129 | 196 | /** Fuse connection for this file */ |
|---|
| 130 | | - struct fuse_conn *fc; |
|---|
| 197 | + struct fuse_mount *fm; |
|---|
| 131 | 198 | |
|---|
| 132 | | - /** Request reserved for flush and release */ |
|---|
| 133 | | - struct fuse_req *reserved_req; |
|---|
| 199 | + /* Argument space reserved for release */ |
|---|
| 200 | + struct fuse_release_args *release_args; |
|---|
| 134 | 201 | |
|---|
| 135 | 202 | /** Kernel file handle guaranteed to be unique */ |
|---|
| 136 | 203 | u64 kh; |
|---|
| .. | .. |
|---|
| 150 | 217 | /** Entry on inode's write_files list */ |
|---|
| 151 | 218 | struct list_head write_entry; |
|---|
| 152 | 219 | |
|---|
| 220 | + /* Readdir related */ |
|---|
| 221 | + struct { |
|---|
| 222 | + /* |
|---|
| 223 | + * Protects below fields against (crazy) parallel readdir on |
|---|
| 224 | + * same open file. Uncontended in the normal case. |
|---|
| 225 | + */ |
|---|
| 226 | + struct mutex lock; |
|---|
| 227 | + |
|---|
| 228 | + /* Dir stream position */ |
|---|
| 229 | + loff_t pos; |
|---|
| 230 | + |
|---|
| 231 | + /* Offset in cache */ |
|---|
| 232 | + loff_t cache_off; |
|---|
| 233 | + |
|---|
| 234 | + /* Version of cache we are reading */ |
|---|
| 235 | + u64 version; |
|---|
| 236 | + |
|---|
| 237 | + } readdir; |
|---|
| 238 | + |
|---|
| 239 | + /** Container for data related to the passthrough functionality */ |
|---|
| 240 | + struct fuse_passthrough passthrough; |
|---|
| 241 | + |
|---|
| 153 | 242 | /** RB node to be linked on fuse_conn->polled_files */ |
|---|
| 154 | 243 | struct rb_node polled_node; |
|---|
| 155 | 244 | |
|---|
| .. | .. |
|---|
| 166 | 255 | const void *value; |
|---|
| 167 | 256 | }; |
|---|
| 168 | 257 | |
|---|
| 169 | | -/** The request input */ |
|---|
| 170 | | -struct fuse_in { |
|---|
| 171 | | - /** The request header */ |
|---|
| 172 | | - struct fuse_in_header h; |
|---|
| 173 | | - |
|---|
| 174 | | - /** True if the data for the last argument is in req->pages */ |
|---|
| 175 | | - unsigned argpages:1; |
|---|
| 176 | | - |
|---|
| 177 | | - /** Number of arguments */ |
|---|
| 178 | | - unsigned numargs; |
|---|
| 179 | | - |
|---|
| 180 | | - /** Array of arguments */ |
|---|
| 181 | | - struct fuse_in_arg args[3]; |
|---|
| 182 | | -}; |
|---|
| 183 | | - |
|---|
| 184 | 258 | /** One output argument of a request */ |
|---|
| 185 | 259 | struct fuse_arg { |
|---|
| 186 | 260 | unsigned size; |
|---|
| 187 | 261 | void *value; |
|---|
| 188 | | -}; |
|---|
| 189 | | - |
|---|
| 190 | | -/** The request output */ |
|---|
| 191 | | -struct fuse_out { |
|---|
| 192 | | - /** Header returned from userspace */ |
|---|
| 193 | | - struct fuse_out_header h; |
|---|
| 194 | | - |
|---|
| 195 | | - /* |
|---|
| 196 | | - * The following bitfields are not changed during the request |
|---|
| 197 | | - * processing |
|---|
| 198 | | - */ |
|---|
| 199 | | - |
|---|
| 200 | | - /** Last argument is variable length (can be shorter than |
|---|
| 201 | | - arg->size) */ |
|---|
| 202 | | - unsigned argvar:1; |
|---|
| 203 | | - |
|---|
| 204 | | - /** Last argument is a list of pages to copy data to */ |
|---|
| 205 | | - unsigned argpages:1; |
|---|
| 206 | | - |
|---|
| 207 | | - /** Zero partially or not copied pages */ |
|---|
| 208 | | - unsigned page_zeroing:1; |
|---|
| 209 | | - |
|---|
| 210 | | - /** Pages may be replaced with new ones */ |
|---|
| 211 | | - unsigned page_replace:1; |
|---|
| 212 | | - |
|---|
| 213 | | - /** Number or arguments */ |
|---|
| 214 | | - unsigned numargs; |
|---|
| 215 | | - |
|---|
| 216 | | - /** Array of arguments */ |
|---|
| 217 | | - struct fuse_arg args[2]; |
|---|
| 218 | | - |
|---|
| 219 | | - /* Path used for completing d_canonical_path */ |
|---|
| 220 | | - struct path *canonical_path; |
|---|
| 221 | 262 | }; |
|---|
| 222 | 263 | |
|---|
| 223 | 264 | /** FUSE page descriptor */ |
|---|
| .. | .. |
|---|
| 227 | 268 | }; |
|---|
| 228 | 269 | |
|---|
| 229 | 270 | struct fuse_args { |
|---|
| 230 | | - struct { |
|---|
| 231 | | - struct { |
|---|
| 232 | | - uint32_t opcode; |
|---|
| 233 | | - uint64_t nodeid; |
|---|
| 234 | | - } h; |
|---|
| 235 | | - unsigned numargs; |
|---|
| 236 | | - struct fuse_in_arg args[3]; |
|---|
| 271 | + uint64_t nodeid; |
|---|
| 272 | + uint32_t opcode; |
|---|
| 273 | + unsigned short in_numargs; |
|---|
| 274 | + unsigned short out_numargs; |
|---|
| 275 | + bool force:1; |
|---|
| 276 | + bool noreply:1; |
|---|
| 277 | + bool nocreds:1; |
|---|
| 278 | + bool in_pages:1; |
|---|
| 279 | + bool out_pages:1; |
|---|
| 280 | + bool user_pages:1; |
|---|
| 281 | + bool out_argvar:1; |
|---|
| 282 | + bool page_zeroing:1; |
|---|
| 283 | + bool page_replace:1; |
|---|
| 284 | + bool may_block:1; |
|---|
| 285 | + struct fuse_in_arg in_args[3]; |
|---|
| 286 | + struct fuse_arg out_args[2]; |
|---|
| 287 | + void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error); |
|---|
| 237 | 288 | |
|---|
| 238 | | - } in; |
|---|
| 239 | | - struct { |
|---|
| 240 | | - unsigned argvar:1; |
|---|
| 241 | | - unsigned numargs; |
|---|
| 242 | | - struct fuse_arg args[2]; |
|---|
| 289 | + /* Path used for completing d_canonical_path */ |
|---|
| 290 | + struct path *canonical_path; |
|---|
| 291 | +}; |
|---|
| 243 | 292 | |
|---|
| 244 | | - /* Path used for completing d_canonical_path */ |
|---|
| 245 | | - struct path *canonical_path; |
|---|
| 246 | | - } out; |
|---|
| 293 | +struct fuse_args_pages { |
|---|
| 294 | + struct fuse_args args; |
|---|
| 295 | + struct page **pages; |
|---|
| 296 | + struct fuse_page_desc *descs; |
|---|
| 297 | + unsigned int num_pages; |
|---|
| 247 | 298 | }; |
|---|
| 248 | 299 | |
|---|
| 249 | 300 | #define FUSE_ARGS(args) struct fuse_args args = {} |
|---|
| .. | .. |
|---|
| 286 | 337 | * FR_SENT: request is in userspace, waiting for an answer |
|---|
| 287 | 338 | * FR_FINISHED: request is finished |
|---|
| 288 | 339 | * FR_PRIVATE: request is on private list |
|---|
| 340 | + * FR_ASYNC: request is asynchronous |
|---|
| 289 | 341 | */ |
|---|
| 290 | 342 | enum fuse_req_flag { |
|---|
| 291 | 343 | FR_ISREPLY, |
|---|
| .. | .. |
|---|
| 299 | 351 | FR_SENT, |
|---|
| 300 | 352 | FR_FINISHED, |
|---|
| 301 | 353 | FR_PRIVATE, |
|---|
| 354 | + FR_ASYNC, |
|---|
| 302 | 355 | }; |
|---|
| 303 | 356 | |
|---|
| 304 | 357 | /** |
|---|
| .. | .. |
|---|
| 316 | 369 | /** Entry on the interrupts list */ |
|---|
| 317 | 370 | struct list_head intr_entry; |
|---|
| 318 | 371 | |
|---|
| 372 | + /* Input/output arguments */ |
|---|
| 373 | + struct fuse_args *args; |
|---|
| 374 | + |
|---|
| 319 | 375 | /** refcount */ |
|---|
| 320 | 376 | refcount_t count; |
|---|
| 321 | | - |
|---|
| 322 | | - /** Unique ID for the interrupt request */ |
|---|
| 323 | | - u64 intr_unique; |
|---|
| 324 | 377 | |
|---|
| 325 | 378 | /* Request flags, updated with test/set/clear_bit() */ |
|---|
| 326 | 379 | unsigned long flags; |
|---|
| 327 | 380 | |
|---|
| 328 | | - /** The request input */ |
|---|
| 329 | | - struct fuse_in in; |
|---|
| 381 | + /* The request input header */ |
|---|
| 382 | + struct { |
|---|
| 383 | + struct fuse_in_header h; |
|---|
| 384 | + } in; |
|---|
| 330 | 385 | |
|---|
| 331 | | - /** The request output */ |
|---|
| 332 | | - struct fuse_out out; |
|---|
| 386 | + /* The request output header */ |
|---|
| 387 | + struct { |
|---|
| 388 | + struct fuse_out_header h; |
|---|
| 389 | + } out; |
|---|
| 333 | 390 | |
|---|
| 334 | 391 | /** Used to wake up the task waiting for completion of request*/ |
|---|
| 335 | 392 | wait_queue_head_t waitq; |
|---|
| 336 | 393 | |
|---|
| 337 | | - /** Data for asynchronous requests */ |
|---|
| 338 | | - union { |
|---|
| 339 | | - struct { |
|---|
| 340 | | - struct fuse_release_in in; |
|---|
| 341 | | - struct inode *inode; |
|---|
| 342 | | - } release; |
|---|
| 343 | | - struct fuse_init_in init_in; |
|---|
| 344 | | - struct fuse_init_out init_out; |
|---|
| 345 | | - struct cuse_init_in cuse_init_in; |
|---|
| 346 | | - struct { |
|---|
| 347 | | - struct fuse_read_in in; |
|---|
| 348 | | - u64 attr_ver; |
|---|
| 349 | | - } read; |
|---|
| 350 | | - struct { |
|---|
| 351 | | - struct fuse_write_in in; |
|---|
| 352 | | - struct fuse_write_out out; |
|---|
| 353 | | - struct fuse_req *next; |
|---|
| 354 | | - } write; |
|---|
| 355 | | - struct fuse_notify_retrieve_in retrieve_in; |
|---|
| 356 | | - } misc; |
|---|
| 394 | + /** virtio-fs's physically contiguous buffer for in and out args */ |
|---|
| 395 | + void *argbuf; |
|---|
| 357 | 396 | |
|---|
| 358 | | - /** page vector */ |
|---|
| 359 | | - struct page **pages; |
|---|
| 360 | | - |
|---|
| 361 | | - /** page-descriptor vector */ |
|---|
| 362 | | - struct fuse_page_desc *page_descs; |
|---|
| 363 | | - |
|---|
| 364 | | - /** size of the 'pages' array */ |
|---|
| 365 | | - unsigned max_pages; |
|---|
| 366 | | - |
|---|
| 367 | | - /** inline page vector */ |
|---|
| 368 | | - struct page *inline_pages[FUSE_REQ_INLINE_PAGES]; |
|---|
| 369 | | - |
|---|
| 370 | | - /** inline page-descriptor vector */ |
|---|
| 371 | | - struct fuse_page_desc inline_page_descs[FUSE_REQ_INLINE_PAGES]; |
|---|
| 372 | | - |
|---|
| 373 | | - /** number of pages in vector */ |
|---|
| 374 | | - unsigned num_pages; |
|---|
| 375 | | - |
|---|
| 376 | | - /** File used in the request (or NULL) */ |
|---|
| 377 | | - struct fuse_file *ff; |
|---|
| 378 | | - |
|---|
| 379 | | - /** Inode used in the request or NULL */ |
|---|
| 380 | | - struct inode *inode; |
|---|
| 381 | | - |
|---|
| 382 | | - /** AIO control block */ |
|---|
| 383 | | - struct fuse_io_priv *io; |
|---|
| 384 | | - |
|---|
| 385 | | - /** Link on fi->writepages */ |
|---|
| 386 | | - struct list_head writepages_entry; |
|---|
| 387 | | - |
|---|
| 388 | | - /** Request completion callback */ |
|---|
| 389 | | - void (*end)(struct fuse_conn *, struct fuse_req *); |
|---|
| 390 | | - |
|---|
| 391 | | - /** Request is stolen from fuse_file->reserved_req */ |
|---|
| 392 | | - struct file *stolen_file; |
|---|
| 397 | + /** fuse_mount this request belongs to */ |
|---|
| 398 | + struct fuse_mount *fm; |
|---|
| 393 | 399 | }; |
|---|
| 400 | + |
|---|
| 401 | +struct fuse_iqueue; |
|---|
| 402 | + |
|---|
| 403 | +/** |
|---|
| 404 | + * Input queue callbacks |
|---|
| 405 | + * |
|---|
| 406 | + * Input queue signalling is device-specific. For example, the /dev/fuse file |
|---|
| 407 | + * uses fiq->waitq and fasync to wake processes that are waiting on queue |
|---|
| 408 | + * readiness. These callbacks allow other device types to respond to input |
|---|
| 409 | + * queue activity. |
|---|
| 410 | + */ |
|---|
| 411 | +struct fuse_iqueue_ops { |
|---|
| 412 | + /** |
|---|
| 413 | + * Signal that a forget has been queued |
|---|
| 414 | + */ |
|---|
| 415 | + void (*wake_forget_and_unlock)(struct fuse_iqueue *fiq, bool sync) |
|---|
| 416 | + __releases(fiq->lock); |
|---|
| 417 | + |
|---|
| 418 | + /** |
|---|
| 419 | + * Signal that an INTERRUPT request has been queued |
|---|
| 420 | + */ |
|---|
| 421 | + void (*wake_interrupt_and_unlock)(struct fuse_iqueue *fiq, bool sync) |
|---|
| 422 | + __releases(fiq->lock); |
|---|
| 423 | + |
|---|
| 424 | + /** |
|---|
| 425 | + * Signal that a request has been queued |
|---|
| 426 | + */ |
|---|
| 427 | + void (*wake_pending_and_unlock)(struct fuse_iqueue *fiq, bool sync) |
|---|
| 428 | + __releases(fiq->lock); |
|---|
| 429 | + |
|---|
| 430 | + /** |
|---|
| 431 | + * Clean up when fuse_iqueue is destroyed |
|---|
| 432 | + */ |
|---|
| 433 | + void (*release)(struct fuse_iqueue *fiq); |
|---|
| 434 | +}; |
|---|
| 435 | + |
|---|
| 436 | +/** /dev/fuse input queue operations */ |
|---|
| 437 | +extern const struct fuse_iqueue_ops fuse_dev_fiq_ops; |
|---|
| 394 | 438 | |
|---|
| 395 | 439 | struct fuse_iqueue { |
|---|
| 396 | 440 | /** Connection established */ |
|---|
| .. | .. |
|---|
| 420 | 464 | |
|---|
| 421 | 465 | /** O_ASYNC requests */ |
|---|
| 422 | 466 | struct fasync_struct *fasync; |
|---|
| 467 | + |
|---|
| 468 | + /** Device-specific callbacks */ |
|---|
| 469 | + const struct fuse_iqueue_ops *ops; |
|---|
| 470 | + |
|---|
| 471 | + /** Device-specific state */ |
|---|
| 472 | + void *priv; |
|---|
| 423 | 473 | }; |
|---|
| 474 | + |
|---|
| 475 | +#define FUSE_PQ_HASH_BITS 8 |
|---|
| 476 | +#define FUSE_PQ_HASH_SIZE (1 << FUSE_PQ_HASH_BITS) |
|---|
| 424 | 477 | |
|---|
| 425 | 478 | struct fuse_pqueue { |
|---|
| 426 | 479 | /** Connection established */ |
|---|
| .. | .. |
|---|
| 429 | 482 | /** Lock protecting accessess to members of this structure */ |
|---|
| 430 | 483 | spinlock_t lock; |
|---|
| 431 | 484 | |
|---|
| 432 | | - /** The list of requests being processed */ |
|---|
| 433 | | - struct list_head processing; |
|---|
| 485 | + /** Hash table of requests being processed */ |
|---|
| 486 | + struct list_head *processing; |
|---|
| 434 | 487 | |
|---|
| 435 | 488 | /** The list of requests under I/O */ |
|---|
| 436 | 489 | struct list_head io; |
|---|
| .. | .. |
|---|
| 450 | 503 | struct list_head entry; |
|---|
| 451 | 504 | }; |
|---|
| 452 | 505 | |
|---|
| 506 | +struct fuse_fs_context { |
|---|
| 507 | + int fd; |
|---|
| 508 | + unsigned int rootmode; |
|---|
| 509 | + kuid_t user_id; |
|---|
| 510 | + kgid_t group_id; |
|---|
| 511 | + bool is_bdev:1; |
|---|
| 512 | + bool fd_present:1; |
|---|
| 513 | + bool rootmode_present:1; |
|---|
| 514 | + bool user_id_present:1; |
|---|
| 515 | + bool group_id_present:1; |
|---|
| 516 | + bool default_permissions:1; |
|---|
| 517 | + bool allow_other:1; |
|---|
| 518 | + bool destroy:1; |
|---|
| 519 | + bool no_control:1; |
|---|
| 520 | + bool no_force_umount:1; |
|---|
| 521 | + bool legacy_opts_show:1; |
|---|
| 522 | + bool dax:1; |
|---|
| 523 | + unsigned int max_read; |
|---|
| 524 | + unsigned int blksize; |
|---|
| 525 | + const char *subtype; |
|---|
| 526 | + |
|---|
| 527 | + /* DAX device, may be NULL */ |
|---|
| 528 | + struct dax_device *dax_dev; |
|---|
| 529 | + |
|---|
| 530 | + /* fuse_dev pointer to fill in, should contain NULL on entry */ |
|---|
| 531 | + void **fudptr; |
|---|
| 532 | +}; |
|---|
| 533 | + |
|---|
| 453 | 534 | /** |
|---|
| 454 | 535 | * A Fuse connection. |
|---|
| 455 | 536 | * |
|---|
| 456 | | - * This structure is created, when the filesystem is mounted, and is |
|---|
| 457 | | - * destroyed, when the client device is closed and the filesystem is |
|---|
| 458 | | - * unmounted. |
|---|
| 537 | + * This structure is created, when the root filesystem is mounted, and |
|---|
| 538 | + * is destroyed, when the client device is closed and the last |
|---|
| 539 | + * fuse_mount is destroyed. |
|---|
| 459 | 540 | */ |
|---|
| 460 | 541 | struct fuse_conn { |
|---|
| 461 | 542 | /** Lock protecting accessess to members of this structure */ |
|---|
| .. | .. |
|---|
| 487 | 568 | /** Maximum write size */ |
|---|
| 488 | 569 | unsigned max_write; |
|---|
| 489 | 570 | |
|---|
| 571 | + /** Maxmum number of pages that can be used in a single request */ |
|---|
| 572 | + unsigned int max_pages; |
|---|
| 573 | + |
|---|
| 574 | + /** Constrain ->max_pages to this value during feature negotiation */ |
|---|
| 575 | + unsigned int max_pages_limit; |
|---|
| 576 | + |
|---|
| 490 | 577 | /** Input queue */ |
|---|
| 491 | 578 | struct fuse_iqueue iq; |
|---|
| 492 | 579 | |
|---|
| 493 | 580 | /** The next unique kernel file handle */ |
|---|
| 494 | | - u64 khctr; |
|---|
| 581 | + atomic64_t khctr; |
|---|
| 495 | 582 | |
|---|
| 496 | 583 | /** rbtree of fuse_files waiting for poll events indexed by ph */ |
|---|
| 497 | 584 | struct rb_root polled_files; |
|---|
| .. | .. |
|---|
| 511 | 598 | /** The list of background requests set aside for later queuing */ |
|---|
| 512 | 599 | struct list_head bg_queue; |
|---|
| 513 | 600 | |
|---|
| 601 | + /** Protects: max_background, congestion_threshold, num_background, |
|---|
| 602 | + * active_background, bg_queue, blocked */ |
|---|
| 603 | + spinlock_t bg_lock; |
|---|
| 604 | + |
|---|
| 514 | 605 | /** Flag indicating that INIT reply has been received. Allocating |
|---|
| 515 | 606 | * any fuse request will be suspended until the flag is set */ |
|---|
| 516 | 607 | int initialized; |
|---|
| .. | .. |
|---|
| 522 | 613 | |
|---|
| 523 | 614 | /** waitq for blocked connection */ |
|---|
| 524 | 615 | wait_queue_head_t blocked_waitq; |
|---|
| 525 | | - |
|---|
| 526 | | - /** waitq for reserved requests */ |
|---|
| 527 | | - wait_queue_head_t reserved_req_waitq; |
|---|
| 528 | 616 | |
|---|
| 529 | 617 | /** Connection established, cleared on umount, connection |
|---|
| 530 | 618 | abort and device release */ |
|---|
| .. | .. |
|---|
| 562 | 650 | /** handle fs handles killing suid/sgid/cap on write/chown/trunc */ |
|---|
| 563 | 651 | unsigned handle_killpriv:1; |
|---|
| 564 | 652 | |
|---|
| 653 | + /** cache READLINK responses in page cache */ |
|---|
| 654 | + unsigned cache_symlinks:1; |
|---|
| 655 | + |
|---|
| 656 | + /* show legacy mount options */ |
|---|
| 657 | + unsigned int legacy_opts_show:1; |
|---|
| 658 | + |
|---|
| 565 | 659 | /* |
|---|
| 566 | 660 | * The following bitfields are only for optimization purposes |
|---|
| 567 | 661 | * and hence races in setting them will not cause malfunction |
|---|
| .. | .. |
|---|
| 569 | 663 | |
|---|
| 570 | 664 | /** Is open/release not implemented by fs? */ |
|---|
| 571 | 665 | unsigned no_open:1; |
|---|
| 666 | + |
|---|
| 667 | + /** Is opendir/releasedir not implemented by fs? */ |
|---|
| 668 | + unsigned no_opendir:1; |
|---|
| 572 | 669 | |
|---|
| 573 | 670 | /** Is fsync not implemented by fs? */ |
|---|
| 574 | 671 | unsigned no_fsync:1; |
|---|
| .. | .. |
|---|
| 627 | 724 | /** Use enhanced/automatic page cache invalidation. */ |
|---|
| 628 | 725 | unsigned auto_inval_data:1; |
|---|
| 629 | 726 | |
|---|
| 727 | + /** Filesystem is fully reponsible for page cache invalidation. */ |
|---|
| 728 | + unsigned explicit_inval_data:1; |
|---|
| 729 | + |
|---|
| 630 | 730 | /** Does the filesystem support readdirplus? */ |
|---|
| 631 | 731 | unsigned do_readdirplus:1; |
|---|
| 632 | 732 | |
|---|
| .. | .. |
|---|
| 648 | 748 | /** Allow other than the mounter user to access the filesystem ? */ |
|---|
| 649 | 749 | unsigned allow_other:1; |
|---|
| 650 | 750 | |
|---|
| 751 | + /** Does the filesystem support copy_file_range? */ |
|---|
| 752 | + unsigned no_copy_file_range:1; |
|---|
| 753 | + |
|---|
| 754 | + /* Send DESTROY request */ |
|---|
| 755 | + unsigned int destroy:1; |
|---|
| 756 | + |
|---|
| 757 | + /* Delete dentries that have gone stale */ |
|---|
| 758 | + unsigned int delete_stale:1; |
|---|
| 759 | + |
|---|
| 760 | + /** Do not create entry in fusectl fs */ |
|---|
| 761 | + unsigned int no_control:1; |
|---|
| 762 | + |
|---|
| 763 | + /** Do not allow MNT_FORCE umount */ |
|---|
| 764 | + unsigned int no_force_umount:1; |
|---|
| 765 | + |
|---|
| 766 | + /* Auto-mount submounts announced by the server */ |
|---|
| 767 | + unsigned int auto_submounts:1; |
|---|
| 768 | + |
|---|
| 769 | + /** Passthrough mode for read/write IO */ |
|---|
| 770 | + unsigned int passthrough:1; |
|---|
| 771 | + |
|---|
| 651 | 772 | /** The number of requests waiting for completion */ |
|---|
| 652 | 773 | atomic_t num_waiting; |
|---|
| 653 | 774 | |
|---|
| 654 | 775 | /** Negotiated minor version */ |
|---|
| 655 | 776 | unsigned minor; |
|---|
| 656 | 777 | |
|---|
| 657 | | - /** Entry on the fuse_conn_list */ |
|---|
| 778 | + /** Entry on the fuse_mount_list */ |
|---|
| 658 | 779 | struct list_head entry; |
|---|
| 659 | 780 | |
|---|
| 660 | | - /** Device ID from super block */ |
|---|
| 781 | + /** Device ID from the root super block */ |
|---|
| 661 | 782 | dev_t dev; |
|---|
| 662 | 783 | |
|---|
| 663 | 784 | /** Dentries in the control filesystem */ |
|---|
| .. | .. |
|---|
| 669 | 790 | /** Key for lock owner ID scrambling */ |
|---|
| 670 | 791 | u32 scramble_key[4]; |
|---|
| 671 | 792 | |
|---|
| 672 | | - /** Reserved request for the DESTROY message */ |
|---|
| 673 | | - struct fuse_req *destroy_req; |
|---|
| 674 | | - |
|---|
| 675 | 793 | /** Version counter for attribute changes */ |
|---|
| 676 | | - u64 attr_version; |
|---|
| 794 | + atomic64_t attr_version; |
|---|
| 677 | 795 | |
|---|
| 678 | 796 | /** Called on final put */ |
|---|
| 679 | 797 | void (*release)(struct fuse_conn *); |
|---|
| 680 | 798 | |
|---|
| 681 | | - /** Super block for this connection. */ |
|---|
| 682 | | - struct super_block *sb; |
|---|
| 683 | | - |
|---|
| 684 | | - /** Read/write semaphore to hold when accessing sb. */ |
|---|
| 799 | + /** |
|---|
| 800 | + * Read/write semaphore to hold when accessing the sb of any |
|---|
| 801 | + * fuse_mount belonging to this connection |
|---|
| 802 | + */ |
|---|
| 685 | 803 | struct rw_semaphore killsb; |
|---|
| 686 | 804 | |
|---|
| 687 | 805 | /** List of device instances belonging to this connection */ |
|---|
| 688 | 806 | struct list_head devices; |
|---|
| 807 | + |
|---|
| 808 | +#ifdef CONFIG_FUSE_DAX |
|---|
| 809 | + /* Dax specific conn data, non-NULL if DAX is enabled */ |
|---|
| 810 | + struct fuse_conn_dax *dax; |
|---|
| 811 | +#endif |
|---|
| 812 | + |
|---|
| 813 | + /** List of filesystems using this connection */ |
|---|
| 814 | + struct list_head mounts; |
|---|
| 815 | + |
|---|
| 816 | + /** IDR for passthrough requests */ |
|---|
| 817 | + struct idr passthrough_req; |
|---|
| 818 | + |
|---|
| 819 | + /** Protects passthrough_req */ |
|---|
| 820 | + spinlock_t passthrough_req_lock; |
|---|
| 689 | 821 | }; |
|---|
| 690 | 822 | |
|---|
| 691 | | -static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) |
|---|
| 823 | +/* |
|---|
| 824 | + * Represents a mounted filesystem, potentially a submount. |
|---|
| 825 | + * |
|---|
| 826 | + * This object allows sharing a fuse_conn between separate mounts to |
|---|
| 827 | + * allow submounts with dedicated superblocks and thus separate device |
|---|
| 828 | + * IDs. |
|---|
| 829 | + */ |
|---|
| 830 | +struct fuse_mount { |
|---|
| 831 | + /* Underlying (potentially shared) connection to the FUSE server */ |
|---|
| 832 | + struct fuse_conn *fc; |
|---|
| 833 | + |
|---|
| 834 | + /* Refcount */ |
|---|
| 835 | + refcount_t count; |
|---|
| 836 | + |
|---|
| 837 | + /* |
|---|
| 838 | + * Super block for this connection (fc->killsb must be held when |
|---|
| 839 | + * accessing this). |
|---|
| 840 | + */ |
|---|
| 841 | + struct super_block *sb; |
|---|
| 842 | + |
|---|
| 843 | + /* Entry on fc->mounts */ |
|---|
| 844 | + struct list_head fc_entry; |
|---|
| 845 | +}; |
|---|
| 846 | + |
|---|
| 847 | +static inline struct fuse_mount *get_fuse_mount_super(struct super_block *sb) |
|---|
| 692 | 848 | { |
|---|
| 693 | 849 | return sb->s_fs_info; |
|---|
| 694 | 850 | } |
|---|
| 695 | 851 | |
|---|
| 852 | +static inline struct fuse_conn *get_fuse_conn_super(struct super_block *sb) |
|---|
| 853 | +{ |
|---|
| 854 | + struct fuse_mount *fm = get_fuse_mount_super(sb); |
|---|
| 855 | + |
|---|
| 856 | + return fm ? fm->fc : NULL; |
|---|
| 857 | +} |
|---|
| 858 | + |
|---|
| 859 | +static inline struct fuse_mount *get_fuse_mount(struct inode *inode) |
|---|
| 860 | +{ |
|---|
| 861 | + return get_fuse_mount_super(inode->i_sb); |
|---|
| 862 | +} |
|---|
| 863 | + |
|---|
| 696 | 864 | static inline struct fuse_conn *get_fuse_conn(struct inode *inode) |
|---|
| 697 | 865 | { |
|---|
| 698 | | - return get_fuse_conn_super(inode->i_sb); |
|---|
| 866 | + struct fuse_mount *fm = get_fuse_mount(inode); |
|---|
| 867 | + |
|---|
| 868 | + return fm ? fm->fc : NULL; |
|---|
| 699 | 869 | } |
|---|
| 700 | 870 | |
|---|
| 701 | 871 | static inline struct fuse_inode *get_fuse_inode(struct inode *inode) |
|---|
| .. | .. |
|---|
| 706 | 876 | static inline u64 get_node_id(struct inode *inode) |
|---|
| 707 | 877 | { |
|---|
| 708 | 878 | return get_fuse_inode(inode)->nodeid; |
|---|
| 879 | +} |
|---|
| 880 | + |
|---|
| 881 | +static inline int invalid_nodeid(u64 nodeid) |
|---|
| 882 | +{ |
|---|
| 883 | + return !nodeid || nodeid == FUSE_ROOT_ID; |
|---|
| 884 | +} |
|---|
| 885 | + |
|---|
| 886 | +static inline u64 fuse_get_attr_version(struct fuse_conn *fc) |
|---|
| 887 | +{ |
|---|
| 888 | + return atomic64_read(&fc->attr_version); |
|---|
| 889 | +} |
|---|
| 890 | + |
|---|
| 891 | +static inline bool fuse_stale_inode(const struct inode *inode, int generation, |
|---|
| 892 | + struct fuse_attr *attr) |
|---|
| 893 | +{ |
|---|
| 894 | + return inode->i_generation != generation || |
|---|
| 895 | + inode_wrong_type(inode, attr->mode); |
|---|
| 709 | 896 | } |
|---|
| 710 | 897 | |
|---|
| 711 | 898 | static inline void fuse_make_bad(struct inode *inode) |
|---|
| .. | .. |
|---|
| 726 | 913 | extern const struct dentry_operations fuse_root_dentry_operations; |
|---|
| 727 | 914 | |
|---|
| 728 | 915 | /** |
|---|
| 729 | | - * Inode to nodeid comparison. |
|---|
| 730 | | - */ |
|---|
| 731 | | -int fuse_inode_eq(struct inode *inode, void *_nodeidp); |
|---|
| 732 | | - |
|---|
| 733 | | -/** |
|---|
| 734 | 916 | * Get a filled in inode |
|---|
| 735 | 917 | */ |
|---|
| 736 | 918 | struct inode *fuse_iget(struct super_block *sb, u64 nodeid, |
|---|
| .. | .. |
|---|
| 748 | 930 | |
|---|
| 749 | 931 | struct fuse_forget_link *fuse_alloc_forget(void); |
|---|
| 750 | 932 | |
|---|
| 751 | | -/* Used by READDIRPLUS */ |
|---|
| 752 | | -void fuse_force_forget(struct file *file, u64 nodeid); |
|---|
| 933 | +struct fuse_forget_link *fuse_dequeue_forget(struct fuse_iqueue *fiq, |
|---|
| 934 | + unsigned int max, |
|---|
| 935 | + unsigned int *countp); |
|---|
| 753 | 936 | |
|---|
| 754 | | -/** |
|---|
| 937 | +/* |
|---|
| 755 | 938 | * Initialize READ or READDIR request |
|---|
| 756 | 939 | */ |
|---|
| 757 | | -void fuse_read_fill(struct fuse_req *req, struct file *file, |
|---|
| 758 | | - loff_t pos, size_t count, int opcode); |
|---|
| 940 | +struct fuse_io_args { |
|---|
| 941 | + union { |
|---|
| 942 | + struct { |
|---|
| 943 | + struct fuse_read_in in; |
|---|
| 944 | + u64 attr_ver; |
|---|
| 945 | + } read; |
|---|
| 946 | + struct { |
|---|
| 947 | + struct fuse_write_in in; |
|---|
| 948 | + struct fuse_write_out out; |
|---|
| 949 | + bool page_locked; |
|---|
| 950 | + } write; |
|---|
| 951 | + }; |
|---|
| 952 | + struct fuse_args_pages ap; |
|---|
| 953 | + struct fuse_io_priv *io; |
|---|
| 954 | + struct fuse_file *ff; |
|---|
| 955 | +}; |
|---|
| 956 | + |
|---|
| 957 | +void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos, |
|---|
| 958 | + size_t count, int opcode); |
|---|
| 959 | + |
|---|
| 759 | 960 | |
|---|
| 760 | 961 | /** |
|---|
| 761 | 962 | * Send OPEN or OPENDIR request |
|---|
| 762 | 963 | */ |
|---|
| 763 | 964 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir); |
|---|
| 764 | 965 | |
|---|
| 765 | | -struct fuse_file *fuse_file_alloc(struct fuse_conn *fc); |
|---|
| 966 | +struct fuse_file *fuse_file_alloc(struct fuse_mount *fm); |
|---|
| 766 | 967 | void fuse_file_free(struct fuse_file *ff); |
|---|
| 767 | 968 | void fuse_finish_open(struct inode *inode, struct file *file); |
|---|
| 768 | 969 | |
|---|
| 769 | | -void fuse_sync_release(struct fuse_file *ff, int flags); |
|---|
| 970 | +void fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff, int flags); |
|---|
| 770 | 971 | |
|---|
| 771 | 972 | /** |
|---|
| 772 | 973 | * Send RELEASE or RELEASEDIR request |
|---|
| .. | .. |
|---|
| 777 | 978 | * Send FSYNC or FSYNCDIR request |
|---|
| 778 | 979 | */ |
|---|
| 779 | 980 | int fuse_fsync_common(struct file *file, loff_t start, loff_t end, |
|---|
| 780 | | - int datasync, int isdir); |
|---|
| 981 | + int datasync, int opcode); |
|---|
| 781 | 982 | |
|---|
| 782 | 983 | /** |
|---|
| 783 | 984 | * Notify poll wakeup |
|---|
| .. | .. |
|---|
| 828 | 1029 | void __exit fuse_ctl_cleanup(void); |
|---|
| 829 | 1030 | |
|---|
| 830 | 1031 | /** |
|---|
| 831 | | - * Allocate a request |
|---|
| 832 | | - */ |
|---|
| 833 | | -struct fuse_req *fuse_request_alloc(unsigned npages); |
|---|
| 834 | | - |
|---|
| 835 | | -struct fuse_req *fuse_request_alloc_nofs(unsigned npages); |
|---|
| 836 | | - |
|---|
| 837 | | -/** |
|---|
| 838 | | - * Free a request |
|---|
| 839 | | - */ |
|---|
| 840 | | -void fuse_request_free(struct fuse_req *req); |
|---|
| 841 | | - |
|---|
| 842 | | -/** |
|---|
| 843 | | - * Get a request, may fail with -ENOMEM, |
|---|
| 844 | | - * caller should specify # elements in req->pages[] explicitly |
|---|
| 845 | | - */ |
|---|
| 846 | | -struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages); |
|---|
| 847 | | -struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc, |
|---|
| 848 | | - unsigned npages); |
|---|
| 849 | | - |
|---|
| 850 | | -/* |
|---|
| 851 | | - * Increment reference count on request |
|---|
| 852 | | - */ |
|---|
| 853 | | -void __fuse_get_request(struct fuse_req *req); |
|---|
| 854 | | - |
|---|
| 855 | | -/** |
|---|
| 856 | | - * Gets a requests for a file operation, always succeeds |
|---|
| 857 | | - */ |
|---|
| 858 | | -struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, |
|---|
| 859 | | - struct file *file); |
|---|
| 860 | | - |
|---|
| 861 | | -/** |
|---|
| 862 | | - * Decrement reference count of a request. If count goes to zero free |
|---|
| 863 | | - * the request. |
|---|
| 864 | | - */ |
|---|
| 865 | | -void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req); |
|---|
| 866 | | - |
|---|
| 867 | | -/** |
|---|
| 868 | | - * Send a request (synchronous) |
|---|
| 869 | | - */ |
|---|
| 870 | | -void fuse_request_send(struct fuse_conn *fc, struct fuse_req *req); |
|---|
| 871 | | - |
|---|
| 872 | | -/** |
|---|
| 873 | 1032 | * Simple request sending that does request allocation and freeing |
|---|
| 874 | 1033 | */ |
|---|
| 875 | | -ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args); |
|---|
| 1034 | +ssize_t fuse_simple_request(struct fuse_mount *fm, struct fuse_args *args); |
|---|
| 1035 | +int fuse_simple_background(struct fuse_mount *fm, struct fuse_args *args, |
|---|
| 1036 | + gfp_t gfp_flags); |
|---|
| 876 | 1037 | |
|---|
| 877 | 1038 | /** |
|---|
| 878 | | - * Send a request in the background |
|---|
| 1039 | + * End a finished request |
|---|
| 879 | 1040 | */ |
|---|
| 880 | | -void fuse_request_send_background(struct fuse_conn *fc, struct fuse_req *req); |
|---|
| 881 | | - |
|---|
| 882 | | -void fuse_request_send_background_locked(struct fuse_conn *fc, |
|---|
| 883 | | - struct fuse_req *req); |
|---|
| 1041 | +void fuse_request_end(struct fuse_req *req); |
|---|
| 884 | 1042 | |
|---|
| 885 | 1043 | /* Abort all requests */ |
|---|
| 886 | | -void fuse_abort_conn(struct fuse_conn *fc, bool is_abort); |
|---|
| 1044 | +void fuse_abort_conn(struct fuse_conn *fc); |
|---|
| 887 | 1045 | void fuse_wait_aborted(struct fuse_conn *fc); |
|---|
| 888 | 1046 | |
|---|
| 889 | 1047 | /** |
|---|
| .. | .. |
|---|
| 895 | 1053 | |
|---|
| 896 | 1054 | void fuse_invalidate_atime(struct inode *inode); |
|---|
| 897 | 1055 | |
|---|
| 1056 | +u64 entry_attr_timeout(struct fuse_entry_out *o); |
|---|
| 1057 | +void fuse_change_entry_timeout(struct dentry *entry, struct fuse_entry_out *o); |
|---|
| 1058 | + |
|---|
| 898 | 1059 | /** |
|---|
| 899 | 1060 | * Acquire reference to fuse_conn |
|---|
| 900 | 1061 | */ |
|---|
| .. | .. |
|---|
| 903 | 1064 | /** |
|---|
| 904 | 1065 | * Initialize fuse_conn |
|---|
| 905 | 1066 | */ |
|---|
| 906 | | -void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns); |
|---|
| 1067 | +void fuse_conn_init(struct fuse_conn *fc, struct fuse_mount *fm, |
|---|
| 1068 | + struct user_namespace *user_ns, |
|---|
| 1069 | + const struct fuse_iqueue_ops *fiq_ops, void *fiq_priv); |
|---|
| 907 | 1070 | |
|---|
| 908 | 1071 | /** |
|---|
| 909 | 1072 | * Release reference to fuse_conn |
|---|
| 910 | 1073 | */ |
|---|
| 911 | 1074 | void fuse_conn_put(struct fuse_conn *fc); |
|---|
| 912 | 1075 | |
|---|
| 913 | | -struct fuse_dev *fuse_dev_alloc(struct fuse_conn *fc); |
|---|
| 1076 | +/** |
|---|
| 1077 | + * Acquire reference to fuse_mount |
|---|
| 1078 | + */ |
|---|
| 1079 | +struct fuse_mount *fuse_mount_get(struct fuse_mount *fm); |
|---|
| 1080 | + |
|---|
| 1081 | +/** |
|---|
| 1082 | + * Release reference to fuse_mount |
|---|
| 1083 | + */ |
|---|
| 1084 | +void fuse_mount_put(struct fuse_mount *fm); |
|---|
| 1085 | + |
|---|
| 1086 | +struct fuse_dev *fuse_dev_alloc_install(struct fuse_conn *fc); |
|---|
| 1087 | +struct fuse_dev *fuse_dev_alloc(void); |
|---|
| 1088 | +void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc); |
|---|
| 914 | 1089 | void fuse_dev_free(struct fuse_dev *fud); |
|---|
| 1090 | +void fuse_send_init(struct fuse_mount *fm); |
|---|
| 1091 | + |
|---|
| 1092 | +/** |
|---|
| 1093 | + * Fill in superblock and initialize fuse connection |
|---|
| 1094 | + * @sb: partially-initialized superblock to fill in |
|---|
| 1095 | + * @ctx: mount context |
|---|
| 1096 | + */ |
|---|
| 1097 | +int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx); |
|---|
| 1098 | + |
|---|
| 1099 | +/* |
|---|
| 1100 | + * Fill in superblock for submounts |
|---|
| 1101 | + * @sb: partially-initialized superblock to fill in |
|---|
| 1102 | + * @parent_fi: The fuse_inode of the parent filesystem where this submount is |
|---|
| 1103 | + * mounted |
|---|
| 1104 | + */ |
|---|
| 1105 | +int fuse_fill_super_submount(struct super_block *sb, |
|---|
| 1106 | + struct fuse_inode *parent_fi); |
|---|
| 1107 | + |
|---|
| 1108 | +/* |
|---|
| 1109 | + * Remove the mount from the connection |
|---|
| 1110 | + * |
|---|
| 1111 | + * Returns whether this was the last mount |
|---|
| 1112 | + */ |
|---|
| 1113 | +bool fuse_mount_remove(struct fuse_mount *fm); |
|---|
| 1114 | + |
|---|
| 1115 | +/* |
|---|
| 1116 | + * Shut down the connection (possibly sending DESTROY request). |
|---|
| 1117 | + */ |
|---|
| 1118 | +void fuse_conn_destroy(struct fuse_mount *fm); |
|---|
| 915 | 1119 | |
|---|
| 916 | 1120 | /** |
|---|
| 917 | 1121 | * Add connection to control filesystem |
|---|
| .. | .. |
|---|
| 937 | 1141 | |
|---|
| 938 | 1142 | u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id); |
|---|
| 939 | 1143 | |
|---|
| 1144 | +void fuse_flush_time_update(struct inode *inode); |
|---|
| 940 | 1145 | void fuse_update_ctime(struct inode *inode); |
|---|
| 941 | 1146 | |
|---|
| 942 | 1147 | int fuse_update_attributes(struct inode *inode, struct file *file); |
|---|
| .. | .. |
|---|
| 946 | 1151 | void fuse_set_nowrite(struct inode *inode); |
|---|
| 947 | 1152 | void fuse_release_nowrite(struct inode *inode); |
|---|
| 948 | 1153 | |
|---|
| 949 | | -u64 fuse_get_attr_version(struct fuse_conn *fc); |
|---|
| 1154 | +/** |
|---|
| 1155 | + * Scan all fuse_mounts belonging to fc to find the first where |
|---|
| 1156 | + * ilookup5() returns a result. Return that result and the |
|---|
| 1157 | + * respective fuse_mount in *fm (unless fm is NULL). |
|---|
| 1158 | + * |
|---|
| 1159 | + * The caller must hold fc->killsb. |
|---|
| 1160 | + */ |
|---|
| 1161 | +struct inode *fuse_ilookup(struct fuse_conn *fc, u64 nodeid, |
|---|
| 1162 | + struct fuse_mount **fm); |
|---|
| 950 | 1163 | |
|---|
| 951 | 1164 | /** |
|---|
| 952 | 1165 | * File-system tells the kernel to invalidate cache for the given node id. |
|---|
| 953 | 1166 | */ |
|---|
| 954 | | -int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, |
|---|
| 1167 | +int fuse_reverse_inval_inode(struct fuse_conn *fc, u64 nodeid, |
|---|
| 955 | 1168 | loff_t offset, loff_t len); |
|---|
| 956 | 1169 | |
|---|
| 957 | 1170 | /** |
|---|
| .. | .. |
|---|
| 964 | 1177 | * - is a file or oan empty directory |
|---|
| 965 | 1178 | * then the dentry is unhashed (d_delete()). |
|---|
| 966 | 1179 | */ |
|---|
| 967 | | -int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, |
|---|
| 1180 | +int fuse_reverse_inval_entry(struct fuse_conn *fc, u64 parent_nodeid, |
|---|
| 968 | 1181 | u64 child_nodeid, struct qstr *name); |
|---|
| 969 | 1182 | |
|---|
| 970 | | -int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
|---|
| 1183 | +int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file, |
|---|
| 971 | 1184 | bool isdir); |
|---|
| 972 | 1185 | |
|---|
| 973 | 1186 | /** |
|---|
| .. | .. |
|---|
| 1016 | 1229 | struct posix_acl *fuse_get_acl(struct inode *inode, int type); |
|---|
| 1017 | 1230 | int fuse_set_acl(struct inode *inode, struct posix_acl *acl, int type); |
|---|
| 1018 | 1231 | |
|---|
| 1232 | + |
|---|
| 1233 | +/* readdir.c */ |
|---|
| 1234 | +int fuse_readdir(struct file *file, struct dir_context *ctx); |
|---|
| 1235 | + |
|---|
| 1236 | +/** |
|---|
| 1237 | + * Return the number of bytes in an arguments list |
|---|
| 1238 | + */ |
|---|
| 1239 | +unsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args); |
|---|
| 1240 | + |
|---|
| 1241 | +/** |
|---|
| 1242 | + * Get the next unique ID for a request |
|---|
| 1243 | + */ |
|---|
| 1244 | +u64 fuse_get_unique(struct fuse_iqueue *fiq); |
|---|
| 1245 | +void fuse_free_conn(struct fuse_conn *fc); |
|---|
| 1246 | + |
|---|
| 1247 | +/* dax.c */ |
|---|
| 1248 | + |
|---|
| 1249 | +#define FUSE_IS_DAX(inode) (IS_ENABLED(CONFIG_FUSE_DAX) && IS_DAX(inode)) |
|---|
| 1250 | + |
|---|
| 1251 | +ssize_t fuse_dax_read_iter(struct kiocb *iocb, struct iov_iter *to); |
|---|
| 1252 | +ssize_t fuse_dax_write_iter(struct kiocb *iocb, struct iov_iter *from); |
|---|
| 1253 | +int fuse_dax_mmap(struct file *file, struct vm_area_struct *vma); |
|---|
| 1254 | +int fuse_dax_break_layouts(struct inode *inode, u64 dmap_start, u64 dmap_end); |
|---|
| 1255 | +int fuse_dax_conn_alloc(struct fuse_conn *fc, struct dax_device *dax_dev); |
|---|
| 1256 | +void fuse_dax_conn_free(struct fuse_conn *fc); |
|---|
| 1257 | +bool fuse_dax_inode_alloc(struct super_block *sb, struct fuse_inode *fi); |
|---|
| 1258 | +void fuse_dax_inode_init(struct inode *inode); |
|---|
| 1259 | +void fuse_dax_inode_cleanup(struct inode *inode); |
|---|
| 1260 | +bool fuse_dax_check_alignment(struct fuse_conn *fc, unsigned int map_alignment); |
|---|
| 1261 | +void fuse_dax_cancel_work(struct fuse_conn *fc); |
|---|
| 1262 | + |
|---|
| 1263 | +/* passthrough.c */ |
|---|
| 1264 | +int fuse_passthrough_open(struct fuse_dev *fud, u32 lower_fd); |
|---|
| 1265 | +int fuse_passthrough_setup(struct fuse_conn *fc, struct fuse_file *ff, |
|---|
| 1266 | + struct fuse_open_out *openarg); |
|---|
| 1267 | +void fuse_passthrough_release(struct fuse_passthrough *passthrough); |
|---|
| 1268 | +ssize_t fuse_passthrough_read_iter(struct kiocb *iocb, struct iov_iter *to); |
|---|
| 1269 | +ssize_t fuse_passthrough_write_iter(struct kiocb *iocb, struct iov_iter *from); |
|---|
| 1270 | +ssize_t fuse_passthrough_mmap(struct file *file, struct vm_area_struct *vma); |
|---|
| 1271 | + |
|---|
| 1019 | 1272 | #endif /* _FS_FUSE_I_H */ |
|---|