1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk/event.h" 8 #include "spdk/log.h" 9 #include "spdk/string.h" 10 #include "spdk/fsdev.h" 11 #include "spdk/rpc.h" 12 #include "spdk/env.h" 13 #include "spdk/util.h" 14 #include "spdk/thread.h" 15 #include "spdk/likely.h" 16 #include "spdk/fuse_dispatcher.h" 17 #include "linux/fuse_kernel.h" 18 19 #ifndef UNUSED 20 #define UNUSED(x) (void)(x) 21 #endif 22 23 /* TODO: values, see https://libfuse.github.io/doxygen/structfuse__conn__info.html */ 24 #define DEFAULT_TIME_GRAN 1 25 #define DEFAULT_MAX_BACKGROUND 1024 26 #define DEFAULT_CONGESTION_THRESHOLD 1024 27 #define DEFAULT_MAX_READAHEAD 0x00020000 28 #define OFFSET_MAX 0x7fffffffffffffffLL 29 30 /* 31 * NOTE: It appeared that the open flags have different values on the different HW architechtures. 32 * 33 * This code handles the open flags translation in case they're originated from a platform with 34 * a different HW architecture. 35 * 36 * Currently supported: 37 * - X86 38 * - X86_64 39 * - ARM 40 * - ARM64 41 */ 42 /* See https://lxr.missinglinkelectronics.com/linux/arch/arm/include/uapi/asm/fcntl.h */ 43 #define ARM_O_DIRECTORY 040000 /* must be a directory */ 44 #define ARM_O_NOFOLLOW 0100000 /* don't follow links */ 45 #define ARM_O_DIRECT 0200000 /* direct disk access hint - currently ignored */ 46 #define ARM_O_LARGEFILE 0400000 47 48 /* See https://lxr.missinglinkelectronics.com/linux/include/uapi/asm-generic/fcntl.h */ 49 #define X86_O_DIRECT 00040000 /* direct disk access hint */ 50 #define X86_O_LARGEFILE 00100000 51 #define X86_O_DIRECTORY 00200000 /* must be a directory */ 52 #define X86_O_NOFOLLOW 00400000 /* don't follow links */ 53 54 static inline bool 55 fsdev_d2h_open_flags(enum spdk_fuse_arch fuse_arch, uint32_t flags, uint32_t *translated_flags) 56 { 57 bool res = true; 58 59 *translated_flags = flags; 60 61 /* NOTE: we always check the original flags to avoid situation where the arch and the native flags 62 * overlap and previously set native flag could be interpreted as original arch flag. 63 */ 64 #define REPLACE_FLAG(arch_flag, native_flag) \ 65 do { \ 66 if (flags & (arch_flag)) { \ 67 *translated_flags &= ~(arch_flag); \ 68 *translated_flags |= (native_flag); \ 69 } \ 70 } while(0) 71 72 switch (fuse_arch) { 73 case SPDK_FUSE_ARCH_NATIVE: 74 #if defined(__x86_64__) || defined(__i386__) 75 case SPDK_FUSE_ARCH_X86: 76 case SPDK_FUSE_ARCH_X86_64: 77 #endif 78 #if defined(__aarch64__) || defined(__arm__) 79 case SPDK_FUSE_ARCH_ARM: 80 case SPDK_FUSE_ARCH_ARM64: 81 #endif 82 /* No translation required */ 83 break; 84 #if defined(__x86_64__) || defined(__i386__) 85 case SPDK_FUSE_ARCH_ARM: 86 case SPDK_FUSE_ARCH_ARM64: 87 /* Relace the ARM-specific flags with the native ones */ 88 REPLACE_FLAG(ARM_O_DIRECTORY, O_DIRECTORY); 89 REPLACE_FLAG(ARM_O_NOFOLLOW, O_NOFOLLOW); 90 REPLACE_FLAG(ARM_O_DIRECT, O_DIRECT); 91 REPLACE_FLAG(ARM_O_LARGEFILE, O_LARGEFILE); 92 break; 93 #endif 94 #if defined(__aarch64__) || defined(__arm__) 95 case SPDK_FUSE_ARCH_X86: 96 case SPDK_FUSE_ARCH_X86_64: 97 /* Relace the X86-specific flags with the native ones */ 98 REPLACE_FLAG(X86_O_DIRECTORY, O_DIRECTORY); 99 REPLACE_FLAG(X86_O_NOFOLLOW, O_NOFOLLOW); 100 REPLACE_FLAG(X86_O_DIRECT, O_DIRECT); 101 REPLACE_FLAG(X86_O_LARGEFILE, O_LARGEFILE); 102 break; 103 #endif 104 default: 105 SPDK_ERRLOG("Unsupported FUSE arch: %d\n", fuse_arch); 106 assert(0); 107 res = false; 108 break; 109 } 110 111 #undef REPLACE_FLAG 112 113 return res; 114 } 115 116 struct spdk_fuse_mgr { 117 struct spdk_mempool *fuse_io_pool; 118 uint32_t ref_cnt; 119 pthread_mutex_t lock; 120 }; 121 122 static struct spdk_fuse_mgr g_fuse_mgr = { 123 .fuse_io_pool = NULL, 124 .ref_cnt = 0, 125 .lock = PTHREAD_MUTEX_INITIALIZER, 126 }; 127 128 struct fuse_forget_data { 129 uint64_t ino; 130 uint64_t nlookup; 131 }; 132 133 struct iov_offs { 134 size_t iov_offs; 135 size_t buf_offs; 136 }; 137 138 struct fuse_io { 139 /** For SG buffer cases, array of iovecs for input. */ 140 struct iovec *in_iov; 141 142 /** For SG buffer cases, number of iovecs in in_iov array. */ 143 int in_iovcnt; 144 145 /** For SG buffer cases, array of iovecs for output. */ 146 struct iovec *out_iov; 147 148 /** For SG buffer cases, number of iovecs in out_iov array. */ 149 int out_iovcnt; 150 151 struct iov_offs in_offs; 152 struct iov_offs out_offs; 153 154 spdk_fuse_dispatcher_submit_cpl_cb cpl_cb; 155 void *cpl_cb_arg; 156 struct spdk_io_channel *ch; 157 struct spdk_fuse_dispatcher *disp; 158 159 struct fuse_in_header hdr; 160 bool in_hdr_with_data; 161 162 union { 163 struct { 164 struct spdk_thread *thread; 165 struct fuse_init_in *in; 166 bool legacy_in; 167 struct spdk_fsdev_open_opts opts; 168 size_t out_len; 169 } init; 170 struct { 171 bool plus; 172 uint32_t size; 173 char *writep; 174 uint32_t bytes_written; 175 } readdir; 176 struct { 177 uint32_t to_forget; 178 int status; 179 } batch_forget; 180 181 struct { 182 int status; 183 } fsdev_close; 184 } u; 185 }; 186 187 struct spdk_fuse_dispatcher { 188 /** 189 * fsdev descriptor 190 */ 191 struct spdk_fsdev_desc *desc; 192 193 /** 194 * fsdev thread 195 */ 196 struct spdk_thread *fsdev_thread; 197 198 /** 199 * Major version of the protocol (read-only) 200 */ 201 unsigned proto_major; 202 203 /** 204 * Minor version of the protocol (read-only) 205 */ 206 unsigned proto_minor; 207 208 /** 209 * FUSE request source's architecture 210 */ 211 enum spdk_fuse_arch fuse_arch; 212 213 /** 214 * Root file object 215 */ 216 struct spdk_fsdev_file_object *root_fobject; 217 218 /** 219 * Event callback 220 */ 221 spdk_fuse_dispatcher_event_cb event_cb; 222 223 /** 224 * Event callback's context 225 */ 226 void *event_ctx; 227 228 /** 229 * Name of the underlying fsdev 230 * 231 * NOTE: must be last 232 */ 233 char fsdev_name[]; 234 }; 235 236 struct spdk_fuse_dispatcher_channel { 237 struct spdk_io_channel *fsdev_io_ch; 238 }; 239 240 #define __disp_to_io_dev(disp) (((char *)disp) + 1) 241 #define __disp_from_io_dev(io_dev) ((struct spdk_fuse_dispatcher *)(((char *)io_dev) - 1)) 242 #define __disp_ch_from_io_ch(io_ch) ((struct spdk_fuse_dispatcher_channel *)spdk_io_channel_get_ctx(io_ch)) 243 244 static inline const char * 245 fuse_dispatcher_name(struct spdk_fuse_dispatcher *disp) 246 { 247 return disp->fsdev_name; 248 } 249 250 static inline uint64_t 251 file_ino(struct fuse_io *fuse_io, const struct spdk_fsdev_file_object *fobject) 252 { 253 return (fuse_io->disp->root_fobject == fobject) ? FUSE_ROOT_ID : (uint64_t)(uintptr_t)fobject; 254 } 255 256 static struct spdk_fsdev_file_object * 257 ino_to_object(struct fuse_io *fuse_io, uint64_t ino) 258 { 259 return (ino == FUSE_ROOT_ID) ? 260 fuse_io->disp->root_fobject : 261 (struct spdk_fsdev_file_object *)(uintptr_t)ino; 262 } 263 264 static struct spdk_fsdev_file_object * 265 file_object(struct fuse_io *fuse_io) 266 { 267 return ino_to_object(fuse_io, fuse_io->hdr.nodeid); 268 } 269 270 static inline uint64_t 271 file_fh(const struct spdk_fsdev_file_handle *fhandle) 272 { 273 return (uint64_t)(uintptr_t)fhandle; 274 } 275 276 static struct spdk_fsdev_file_handle * 277 file_handle(uint64_t fh) 278 { 279 return (struct spdk_fsdev_file_handle *)(uintptr_t)fh; 280 } 281 282 static inline uint16_t 283 fsdev_io_d2h_u16(struct fuse_io *fuse_io, uint16_t v) 284 { 285 return v; 286 } 287 288 static inline uint16_t 289 fsdev_io_h2d_u16(struct fuse_io *fuse_io, uint16_t v) 290 { 291 return v; 292 } 293 294 static inline uint32_t 295 fsdev_io_d2h_u32(struct fuse_io *fuse_io, uint32_t v) 296 { 297 return v; 298 } 299 300 static inline uint32_t 301 fsdev_io_h2d_u32(struct fuse_io *fuse_io, uint32_t v) 302 { 303 return v; 304 } 305 306 static inline int32_t 307 fsdev_io_h2d_i32(struct fuse_io *fuse_io, int32_t v) 308 { 309 return v; 310 } 311 312 static inline uint64_t 313 fsdev_io_d2h_u64(struct fuse_io *fuse_io, uint64_t v) 314 { 315 return v; 316 } 317 318 static inline uint64_t 319 fsdev_io_h2d_u64(struct fuse_io *fuse_io, uint64_t v) 320 { 321 return v; 322 } 323 324 static inline unsigned 325 fsdev_io_proto_minor(struct fuse_io *fuse_io) 326 { 327 return fuse_io->disp->proto_minor; 328 } 329 330 static inline void * 331 _iov_arr_get_buf_info(struct iovec *iovs, size_t cnt, struct iov_offs *offs, size_t *size) 332 { 333 struct iovec *iov; 334 335 assert(offs->iov_offs <= cnt); 336 337 if (offs->iov_offs == cnt) { 338 assert(!offs->buf_offs); 339 *size = 0; 340 return NULL; 341 } 342 343 iov = &iovs[offs->iov_offs]; 344 345 assert(offs->buf_offs < iov->iov_len); 346 347 *size = iov->iov_len - offs->buf_offs; 348 349 return ((char *)iov->iov_base) + offs->buf_offs; 350 } 351 352 static inline void * 353 _iov_arr_get_buf(struct iovec *iovs, size_t cnt, struct iov_offs *offs, size_t size, 354 const char *direction) 355 { 356 char *arg_buf; 357 size_t arg_size; 358 359 arg_buf = _iov_arr_get_buf_info(iovs, cnt, offs, &arg_size); 360 if (!arg_buf) { 361 SPDK_INFOLOG(fuse_dispatcher, "No %s arg header attached at %zu:%zu\n", direction, offs->iov_offs, 362 offs->buf_offs); 363 return NULL; 364 } 365 366 if (!arg_size) { 367 SPDK_INFOLOG(fuse_dispatcher, "%s arg of zero length attached at %zu:%zu\n", direction, 368 offs->iov_offs, offs->buf_offs); 369 return NULL; 370 } 371 372 if (size > arg_size) { 373 SPDK_INFOLOG(fuse_dispatcher, "%s arg is too small (%zu > %zu) at %zu:%zu\n", direction, size, 374 arg_size, offs->iov_offs, offs->buf_offs); 375 return NULL; 376 } 377 378 if (size == arg_size) { 379 offs->iov_offs++; 380 offs->buf_offs = 0; 381 } else { 382 offs->buf_offs += size; 383 } 384 385 return arg_buf; 386 } 387 388 static inline const char * 389 _fsdev_io_in_arg_get_str(struct fuse_io *fuse_io) 390 { 391 char *arg_buf; 392 size_t arg_size, len; 393 394 arg_buf = _iov_arr_get_buf_info(fuse_io->in_iov, fuse_io->in_iovcnt, &fuse_io->in_offs, 395 &arg_size); 396 if (!arg_buf) { 397 SPDK_ERRLOG("No IN arg header attached at %zu:%zu\n", fuse_io->in_offs.iov_offs, 398 fuse_io->in_offs.buf_offs); 399 return NULL; 400 } 401 402 len = strnlen(arg_buf, arg_size); 403 if (len == arg_size) { 404 SPDK_ERRLOG("no string or bad string attached at %zu:%zu\n", fuse_io->in_offs.iov_offs, 405 fuse_io->in_offs.buf_offs); 406 return NULL; 407 } 408 409 fuse_io->in_offs.buf_offs += len + 1; 410 411 if (len + 1 == arg_size) { 412 fuse_io->in_offs.iov_offs++; 413 fuse_io->in_offs.buf_offs = 0; 414 } 415 416 return arg_buf; 417 } 418 419 static inline void * 420 _fsdev_io_in_arg_get_buf(struct fuse_io *fuse_io, size_t size) 421 { 422 return _iov_arr_get_buf(fuse_io->in_iov, fuse_io->in_iovcnt, &fuse_io->in_offs, size, "IN"); 423 } 424 425 426 static inline void * 427 _fsdev_io_out_arg_get_buf(struct fuse_io *fuse_io, size_t size) 428 { 429 return _iov_arr_get_buf(fuse_io->out_iov, fuse_io->out_iovcnt, &fuse_io->out_offs, size, 430 "OUT"); 431 } 432 433 static bool 434 _fuse_op_requires_reply(uint32_t opcode) 435 { 436 switch (opcode) { 437 case FUSE_FORGET: 438 case FUSE_BATCH_FORGET: 439 return false; 440 default: 441 return true; 442 } 443 } 444 445 static void 446 convert_stat(struct fuse_io *fuse_io, struct spdk_fsdev_file_object *fobject, 447 const struct spdk_fsdev_file_attr *attr, struct fuse_attr *fattr) 448 { 449 fattr->ino = fsdev_io_h2d_u64(fuse_io, attr->ino); 450 fattr->mode = fsdev_io_h2d_u32(fuse_io, attr->mode); 451 fattr->nlink = fsdev_io_h2d_u32(fuse_io, attr->nlink); 452 fattr->uid = fsdev_io_h2d_u32(fuse_io, attr->uid); 453 fattr->gid = fsdev_io_h2d_u32(fuse_io, attr->gid); 454 fattr->rdev = fsdev_io_h2d_u32(fuse_io, attr->rdev); 455 fattr->size = fsdev_io_h2d_u64(fuse_io, attr->size); 456 fattr->blksize = fsdev_io_h2d_u32(fuse_io, attr->blksize); 457 fattr->blocks = fsdev_io_h2d_u64(fuse_io, attr->blocks); 458 fattr->atime = fsdev_io_h2d_u64(fuse_io, attr->atime); 459 fattr->mtime = fsdev_io_h2d_u64(fuse_io, attr->mtime); 460 fattr->ctime = fsdev_io_h2d_u64(fuse_io, attr->ctime); 461 fattr->atimensec = fsdev_io_h2d_u32(fuse_io, attr->atimensec); 462 fattr->mtimensec = fsdev_io_h2d_u32(fuse_io, attr->mtimensec); 463 fattr->ctimensec = fsdev_io_h2d_u32(fuse_io, attr->ctimensec); 464 } 465 466 static uint32_t 467 calc_timeout_sec(uint32_t ms) 468 { 469 return ms / 1000; 470 } 471 472 static uint32_t 473 calc_timeout_nsec(uint32_t ms) 474 { 475 return (ms % 1000) * 1000000; 476 } 477 478 static void 479 fill_entry(struct fuse_io *fuse_io, struct fuse_entry_out *arg, 480 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 481 { 482 arg->nodeid = fsdev_io_h2d_u64(fuse_io, file_ino(fuse_io, fobject)); 483 arg->generation = 0; 484 arg->entry_valid = fsdev_io_h2d_u64(fuse_io, calc_timeout_sec(attr->valid_ms)); 485 arg->entry_valid_nsec = fsdev_io_h2d_u32(fuse_io, calc_timeout_nsec(attr->valid_ms)); 486 arg->attr_valid = fsdev_io_h2d_u64(fuse_io, calc_timeout_sec(attr->valid_ms)); 487 arg->attr_valid_nsec = fsdev_io_h2d_u32(fuse_io, calc_timeout_nsec(attr->valid_ms)); 488 convert_stat(fuse_io, fobject, attr, &arg->attr); 489 } 490 491 static void 492 fill_open(struct fuse_io *fuse_io, struct fuse_open_out *arg, 493 struct spdk_fsdev_file_handle *fhandle) 494 { 495 arg->fh = fsdev_io_h2d_u64(fuse_io, file_fh(fhandle)); 496 arg->open_flags = fsdev_io_h2d_u64(fuse_io, FOPEN_DIRECT_IO); 497 } 498 499 static void 500 convert_statfs(struct fuse_io *fuse_io, const struct spdk_fsdev_file_statfs *statfs, 501 struct fuse_kstatfs *kstatfs) 502 { 503 kstatfs->bsize = fsdev_io_h2d_u32(fuse_io, statfs->bsize); 504 kstatfs->frsize = fsdev_io_h2d_u32(fuse_io, statfs->frsize); 505 kstatfs->blocks = fsdev_io_h2d_u64(fuse_io, statfs->blocks); 506 kstatfs->bfree = fsdev_io_h2d_u64(fuse_io, statfs->bfree); 507 kstatfs->bavail = fsdev_io_h2d_u64(fuse_io, statfs->bavail); 508 kstatfs->files = fsdev_io_h2d_u64(fuse_io, statfs->files); 509 kstatfs->ffree = fsdev_io_h2d_u64(fuse_io, statfs->ffree); 510 kstatfs->namelen = fsdev_io_h2d_u32(fuse_io, statfs->namelen); 511 } 512 513 static struct fuse_out_header * 514 fuse_dispatcher_fill_out_hdr(struct fuse_io *fuse_io, size_t out_len, int error) 515 { 516 struct fuse_out_header *hdr; 517 struct iovec *out; 518 uint32_t len; 519 520 assert(fuse_io->out_iovcnt >= 1); 521 assert(error <= 0); 522 523 out = fuse_io->out_iov; 524 525 if (out->iov_len < sizeof(*hdr)) { 526 SPDK_ERRLOG("Bad out header len: %zu < %zu\n", out->iov_len, sizeof(*hdr)); 527 return NULL; 528 } 529 530 if (error < -1000) { 531 SPDK_ERRLOG("Bad completion error value: %" PRIu32 "\n", error); 532 return NULL; 533 } 534 535 len = sizeof(*hdr) + out_len; 536 537 hdr = out->iov_base; 538 memset(hdr, 0, sizeof(*hdr)); 539 540 hdr->unique = fsdev_io_h2d_u64(fuse_io, fuse_io->hdr.unique); 541 hdr->error = fsdev_io_h2d_i32(fuse_io, error); 542 hdr->len = fsdev_io_h2d_u32(fuse_io, len); 543 544 return hdr; 545 } 546 547 static void 548 fuse_dispatcher_io_complete_final(struct fuse_io *fuse_io, int error) 549 { 550 spdk_fuse_dispatcher_submit_cpl_cb cpl_cb = fuse_io->cpl_cb; 551 void *cpl_cb_arg = fuse_io->cpl_cb_arg; 552 553 /* NOTE: it's important to free fuse_io before the completion callback, 554 * as the callback can destroy the dispatcher 555 */ 556 spdk_mempool_put(g_fuse_mgr.fuse_io_pool, fuse_io); 557 558 cpl_cb(cpl_cb_arg, error); 559 } 560 561 static void 562 fuse_dispatcher_io_complete(struct fuse_io *fuse_io, uint32_t out_len, int error) 563 { 564 struct fuse_out_header *hdr = fuse_dispatcher_fill_out_hdr(fuse_io, out_len, error); 565 566 assert(_fuse_op_requires_reply(fuse_io->hdr.opcode)); 567 568 if (!hdr) { 569 SPDK_ERRLOG("Completion failed: cannot fill out header\n"); 570 return; 571 } 572 573 SPDK_DEBUGLOG(fuse_dispatcher, 574 "Completing IO#%" PRIu64 " (err=%d, out_len=%" PRIu32 ")\n", 575 fuse_io->hdr.unique, error, out_len); 576 577 fuse_dispatcher_io_complete_final(fuse_io, error); 578 } 579 580 static void 581 fuse_dispatcher_io_copy_and_complete(struct fuse_io *fuse_io, const void *out, uint32_t out_len, 582 int error) 583 { 584 if (out && out_len) { 585 void *buf = _fsdev_io_out_arg_get_buf(fuse_io, out_len); 586 if (buf) { 587 memcpy(buf, out, out_len); 588 } else { 589 SPDK_ERRLOG("Completion failed: cannot get buf to copy %" PRIu32 " bytes\n", out_len); 590 error = EINVAL; 591 out_len = 0; 592 } 593 } 594 595 fuse_dispatcher_io_complete(fuse_io, out_len, error); 596 } 597 598 static void 599 fuse_dispatcher_io_complete_none(struct fuse_io *fuse_io, int err) 600 { 601 SPDK_DEBUGLOG(fuse_dispatcher, "Completing IO#%" PRIu64 "(err=%d)\n", 602 fuse_io->hdr.unique, err); 603 fuse_dispatcher_io_complete_final(fuse_io, err); 604 } 605 606 static void 607 fuse_dispatcher_io_complete_ok(struct fuse_io *fuse_io, uint32_t out_len) 608 { 609 fuse_dispatcher_io_complete(fuse_io, out_len, 0); 610 } 611 612 static void 613 fuse_dispatcher_io_complete_err(struct fuse_io *fuse_io, int err) 614 { 615 fuse_dispatcher_io_complete(fuse_io, 0, err); 616 } 617 618 static void 619 fuse_dispatcher_io_complete_entry(struct fuse_io *fuse_io, struct spdk_fsdev_file_object *fobject, 620 const struct spdk_fsdev_file_attr *attr) 621 { 622 struct fuse_entry_out arg; 623 size_t size = fsdev_io_proto_minor(fuse_io) < 9 ? 624 FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(arg); 625 626 memset(&arg, 0, sizeof(arg)); 627 fill_entry(fuse_io, &arg, fobject, attr); 628 629 fuse_dispatcher_io_copy_and_complete(fuse_io, &arg, size, 0); 630 } 631 632 static void 633 fuse_dispatcher_io_complete_open(struct fuse_io *fuse_io, struct spdk_fsdev_file_handle *fhandle) 634 { 635 struct fuse_open_out *arg; 636 637 arg = _fsdev_io_out_arg_get_buf(fuse_io, sizeof(*arg)); 638 if (!arg) { 639 SPDK_ERRLOG("Cannot get fuse_open_out\n"); 640 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 641 return; 642 } 643 644 fill_open(fuse_io, arg, fhandle); 645 646 fuse_dispatcher_io_complete_ok(fuse_io, sizeof(*arg)); 647 } 648 649 static void 650 fuse_dispatcher_io_complete_create(struct fuse_io *fuse_io, struct spdk_fsdev_file_object *fobject, 651 const struct spdk_fsdev_file_attr *attr, 652 struct spdk_fsdev_file_handle *fhandle) 653 { 654 char buf[sizeof(struct fuse_entry_out) + sizeof(struct fuse_open_out)]; 655 size_t entrysize = fsdev_io_proto_minor(fuse_io) < 9 ? 656 FUSE_COMPAT_ENTRY_OUT_SIZE : sizeof(struct fuse_entry_out); 657 struct fuse_entry_out *earg = (struct fuse_entry_out *) buf; 658 struct fuse_open_out *oarg = (struct fuse_open_out *)(buf + entrysize); 659 660 memset(buf, 0, sizeof(buf)); 661 fill_entry(fuse_io, earg, fobject, attr); 662 fill_open(fuse_io, oarg, fhandle); 663 664 fuse_dispatcher_io_copy_and_complete(fuse_io, buf, entrysize + sizeof(struct fuse_open_out), 0); 665 } 666 667 static void 668 fuse_dispatcher_io_complete_xattr(struct fuse_io *fuse_io, uint32_t count) 669 { 670 struct fuse_getxattr_out *arg; 671 672 arg = _fsdev_io_out_arg_get_buf(fuse_io, sizeof(*arg)); 673 if (!arg) { 674 SPDK_ERRLOG("Cannot get fuse_getxattr_out\n"); 675 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 676 return; 677 } 678 679 arg->size = fsdev_io_h2d_i32(fuse_io, count); 680 681 fuse_dispatcher_io_complete_ok(fuse_io, sizeof(*arg)); 682 } 683 684 static void 685 fuse_dispatcher_io_complete_write(struct fuse_io *fuse_io, uint32_t data_size, int error) 686 { 687 struct fuse_write_out *arg; 688 689 arg = _fsdev_io_out_arg_get_buf(fuse_io, sizeof(*arg)); 690 if (!arg) { 691 SPDK_ERRLOG("Cannot get fuse_write_out\n"); 692 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 693 return; 694 } 695 696 arg->size = fsdev_io_d2h_u32(fuse_io, data_size); 697 698 fuse_dispatcher_io_complete(fuse_io, sizeof(*arg), error); 699 } 700 701 static void 702 fuse_dispatcher_io_complete_statfs(struct fuse_io *fuse_io, 703 const struct spdk_fsdev_file_statfs *statfs) 704 { 705 struct fuse_statfs_out arg; 706 size_t size = fsdev_io_proto_minor(fuse_io) < 4 ? 707 FUSE_COMPAT_STATFS_SIZE : sizeof(arg); 708 709 memset(&arg, 0, sizeof(arg)); 710 convert_statfs(fuse_io, statfs, &arg.st); 711 712 return fuse_dispatcher_io_copy_and_complete(fuse_io, &arg, size, 0); 713 } 714 715 static void 716 fuse_dispatcher_io_complete_attr(struct fuse_io *fuse_io, const struct spdk_fsdev_file_attr *attr) 717 { 718 struct fuse_attr_out arg; 719 size_t size = fsdev_io_proto_minor(fuse_io) < 9 ? 720 FUSE_COMPAT_ATTR_OUT_SIZE : sizeof(arg); 721 722 memset(&arg, 0, sizeof(arg)); 723 arg.attr_valid = fsdev_io_h2d_u64(fuse_io, calc_timeout_sec(attr->valid_ms)); 724 arg.attr_valid_nsec = fsdev_io_h2d_u32(fuse_io, calc_timeout_nsec(attr->valid_ms)); 725 convert_stat(fuse_io, file_object(fuse_io), attr, &arg.attr); 726 727 fuse_dispatcher_io_copy_and_complete(fuse_io, &arg, size, 0); 728 } 729 730 /* `buf` is allowed to be empty so that the proper size may be 731 allocated by the caller */ 732 static size_t 733 fuse_dispatcher_add_direntry(struct fuse_io *fuse_io, char *buf, size_t bufsize, 734 const char *name, struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr, 735 off_t off) 736 { 737 size_t namelen; 738 size_t entlen; 739 size_t entlen_padded; 740 struct fuse_dirent *dirent; 741 742 namelen = strlen(name); 743 entlen = FUSE_NAME_OFFSET + namelen; 744 entlen_padded = FUSE_DIRENT_ALIGN(entlen); 745 746 if ((buf == NULL) || (entlen_padded > bufsize)) { 747 return entlen_padded; 748 } 749 750 dirent = (struct fuse_dirent *) buf; 751 dirent->ino = file_ino(fuse_io, fobject); 752 dirent->off = fsdev_io_h2d_u64(fuse_io, off); 753 dirent->namelen = fsdev_io_h2d_u32(fuse_io, namelen); 754 dirent->type = fsdev_io_h2d_u32(fuse_io, (attr->mode & 0170000) >> 12); 755 memcpy(dirent->name, name, namelen); 756 memset(dirent->name + namelen, 0, entlen_padded - entlen); 757 758 return entlen_padded; 759 } 760 761 /* `buf` is allowed to be empty so that the proper size may be 762 allocated by the caller */ 763 static size_t 764 fuse_dispatcher_add_direntry_plus(struct fuse_io *fuse_io, char *buf, size_t bufsize, 765 const char *name, struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr, 766 off_t off) 767 { 768 size_t namelen; 769 size_t entlen; 770 size_t entlen_padded; 771 772 namelen = strlen(name); 773 entlen = FUSE_NAME_OFFSET_DIRENTPLUS + namelen; 774 entlen_padded = FUSE_DIRENT_ALIGN(entlen); 775 if ((buf == NULL) || (entlen_padded > bufsize)) { 776 return entlen_padded; 777 } 778 779 struct fuse_direntplus *dp = (struct fuse_direntplus *) buf; 780 memset(&dp->entry_out, 0, sizeof(dp->entry_out)); 781 fill_entry(fuse_io, &dp->entry_out, fobject, attr); 782 783 struct fuse_dirent *dirent = &dp->dirent; 784 dirent->ino = fsdev_io_h2d_u64(fuse_io, attr->ino); 785 dirent->off = fsdev_io_h2d_u64(fuse_io, off); 786 dirent->namelen = fsdev_io_h2d_u32(fuse_io, namelen); 787 dirent->type = fsdev_io_h2d_u32(fuse_io, (attr->mode & 0170000) >> 12); 788 memcpy(dirent->name, name, namelen); 789 memset(dirent->name + namelen, 0, entlen_padded - entlen); 790 791 return entlen_padded; 792 } 793 794 /* 795 * Static FUSE commands handlers 796 */ 797 static inline struct spdk_fsdev_desc * 798 fuse_io_desc(struct fuse_io *fuse_io) 799 { 800 return fuse_io->disp->desc; 801 } 802 803 static void 804 do_lookup_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 805 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 806 { 807 struct fuse_io *fuse_io = cb_arg; 808 809 if (!status) { 810 fuse_dispatcher_io_complete_entry(fuse_io, fobject, attr); 811 } else { 812 fuse_dispatcher_io_complete_err(fuse_io, status); 813 } 814 } 815 816 static void 817 do_lookup(struct fuse_io *fuse_io) 818 { 819 int err; 820 const char *name = _fsdev_io_in_arg_get_str(fuse_io); 821 if (!name) { 822 SPDK_ERRLOG("No name or bad name attached\n"); 823 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 824 return; 825 } 826 827 err = spdk_fsdev_lookup(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 828 file_object(fuse_io), name, do_lookup_cpl_clb, fuse_io); 829 if (err) { 830 fuse_dispatcher_io_complete_err(fuse_io, err); 831 } 832 } 833 834 static void 835 do_forget_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 836 { 837 struct fuse_io *fuse_io = cb_arg; 838 839 fuse_dispatcher_io_complete_none(fuse_io, status); /* FUSE_FORGET requires no response */ 840 } 841 842 static void 843 do_forget(struct fuse_io *fuse_io) 844 { 845 int err; 846 struct fuse_forget_in *arg; 847 848 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 849 if (!arg) { 850 SPDK_ERRLOG("Cannot get fuse_forget_in\n"); 851 fuse_dispatcher_io_complete_none(fuse_io, EINVAL); /* FUSE_FORGET requires no response */ 852 return; 853 } 854 855 err = spdk_fsdev_forget(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 856 file_object(fuse_io), fsdev_io_d2h_u64(fuse_io, arg->nlookup), 857 do_forget_cpl_clb, fuse_io); 858 if (err) { 859 fuse_dispatcher_io_complete_err(fuse_io, err); 860 } 861 } 862 863 static void 864 do_getattr_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 865 const struct spdk_fsdev_file_attr *attr) 866 { 867 struct fuse_io *fuse_io = cb_arg; 868 869 if (!status) { 870 fuse_dispatcher_io_complete_attr(fuse_io, attr); 871 } else { 872 fuse_dispatcher_io_complete_err(fuse_io, status); 873 } 874 } 875 876 static void 877 do_getattr(struct fuse_io *fuse_io) 878 { 879 int err; 880 uint64_t fh = 0; 881 882 if (fsdev_io_proto_minor(fuse_io) >= 9) { 883 struct fuse_getattr_in *arg; 884 885 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 886 if (!arg) { 887 SPDK_ERRLOG("Cannot get fuse_getattr_in\n"); 888 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 889 return; 890 } 891 892 if (fsdev_io_d2h_u64(fuse_io, arg->getattr_flags) & FUSE_GETATTR_FH) { 893 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 894 } 895 } 896 897 err = spdk_fsdev_getattr(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 898 file_object(fuse_io), file_handle(fh), do_getattr_cpl_clb, fuse_io); 899 if (err) { 900 fuse_dispatcher_io_complete_err(fuse_io, err); 901 } 902 } 903 904 static void 905 do_setattr_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 906 const struct spdk_fsdev_file_attr *attr) 907 { 908 struct fuse_io *fuse_io = cb_arg; 909 910 if (!status) { 911 fuse_dispatcher_io_complete_attr(fuse_io, attr); 912 } else { 913 fuse_dispatcher_io_complete_err(fuse_io, status); 914 } 915 } 916 917 static void 918 do_setattr(struct fuse_io *fuse_io) 919 { 920 int err; 921 struct fuse_setattr_in *arg; 922 uint32_t valid; 923 uint64_t fh = 0; 924 struct spdk_fsdev_file_attr attr; 925 926 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 927 if (!arg) { 928 SPDK_ERRLOG("Cannot get fuse_setattr_in\n"); 929 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 930 return; 931 } 932 933 memset(&attr, 0, sizeof(attr)); 934 attr.mode = fsdev_io_d2h_u32(fuse_io, arg->mode); 935 attr.uid = fsdev_io_d2h_u32(fuse_io, arg->uid); 936 attr.gid = fsdev_io_d2h_u32(fuse_io, arg->gid); 937 attr.size = fsdev_io_d2h_u64(fuse_io, arg->size); 938 attr.atime = fsdev_io_d2h_u64(fuse_io, arg->atime); 939 attr.mtime = fsdev_io_d2h_u64(fuse_io, arg->mtime); 940 attr.ctime = fsdev_io_d2h_u64(fuse_io, arg->ctime); 941 attr.atimensec = fsdev_io_d2h_u32(fuse_io, arg->atimensec); 942 attr.mtimensec = fsdev_io_d2h_u32(fuse_io, arg->mtimensec); 943 attr.ctimensec = fsdev_io_d2h_u32(fuse_io, arg->ctimensec); 944 945 valid = fsdev_io_d2h_u64(fuse_io, arg->valid); 946 if (valid & FATTR_FH) { 947 valid &= ~FATTR_FH; 948 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 949 } 950 951 valid &= 952 FSDEV_SET_ATTR_MODE | 953 FSDEV_SET_ATTR_UID | 954 FSDEV_SET_ATTR_GID | 955 FSDEV_SET_ATTR_SIZE | 956 FSDEV_SET_ATTR_ATIME | 957 FSDEV_SET_ATTR_MTIME | 958 FSDEV_SET_ATTR_ATIME_NOW | 959 FSDEV_SET_ATTR_MTIME_NOW | 960 FSDEV_SET_ATTR_CTIME; 961 962 err = spdk_fsdev_setattr(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 963 file_object(fuse_io), file_handle(fh), &attr, valid, 964 do_setattr_cpl_clb, fuse_io); 965 if (err) { 966 fuse_dispatcher_io_complete_err(fuse_io, err); 967 } 968 } 969 970 static void 971 do_readlink_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, const char *linkname) 972 { 973 struct fuse_io *fuse_io = cb_arg; 974 975 if (!status) { 976 fuse_dispatcher_io_copy_and_complete(fuse_io, linkname, strlen(linkname) + 1, 0); 977 } else { 978 fuse_dispatcher_io_complete_err(fuse_io, status); 979 } 980 } 981 982 static void 983 do_readlink(struct fuse_io *fuse_io) 984 { 985 int err; 986 987 err = spdk_fsdev_readlink(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 988 file_object(fuse_io), do_readlink_cpl_clb, fuse_io); 989 if (err) { 990 fuse_dispatcher_io_complete_err(fuse_io, err); 991 } 992 } 993 994 static void 995 do_symlink_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 996 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 997 { 998 struct fuse_io *fuse_io = cb_arg; 999 1000 if (!status) { 1001 fuse_dispatcher_io_complete_entry(fuse_io, fobject, attr); 1002 } else { 1003 fuse_dispatcher_io_complete_err(fuse_io, status); 1004 } 1005 } 1006 1007 static void 1008 do_symlink(struct fuse_io *fuse_io) 1009 { 1010 int err; 1011 const char *name, *linkname; 1012 1013 name = _fsdev_io_in_arg_get_str(fuse_io); 1014 if (!name) { 1015 SPDK_ERRLOG("Cannot get name\n"); 1016 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1017 return; 1018 } 1019 1020 linkname = _fsdev_io_in_arg_get_str(fuse_io); 1021 if (!linkname) { 1022 SPDK_ERRLOG("Cannot get linkname\n"); 1023 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1024 return; 1025 } 1026 1027 err = spdk_fsdev_symlink(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1028 file_object(fuse_io), name, linkname, fuse_io->hdr.uid, fuse_io->hdr.gid, 1029 do_symlink_cpl_clb, fuse_io); 1030 if (err) { 1031 fuse_dispatcher_io_complete_err(fuse_io, err); 1032 } 1033 } 1034 1035 static void 1036 do_mknod_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 1037 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 1038 { 1039 struct fuse_io *fuse_io = cb_arg; 1040 1041 if (!status) { 1042 fuse_dispatcher_io_complete_entry(fuse_io, fobject, attr); 1043 } else { 1044 fuse_dispatcher_io_complete_err(fuse_io, status); 1045 } 1046 } 1047 1048 static void 1049 do_mknod(struct fuse_io *fuse_io) 1050 { 1051 int err; 1052 bool compat = fsdev_io_proto_minor(fuse_io) < 12; 1053 struct fuse_mknod_in *arg; 1054 const char *name; 1055 1056 arg = _fsdev_io_in_arg_get_buf(fuse_io, compat ? FUSE_COMPAT_MKNOD_IN_SIZE : sizeof(*arg)); 1057 if (!arg) { 1058 SPDK_ERRLOG("Cannot get fuse_mknod_in (compat=%d)\n", compat); 1059 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1060 return; 1061 } 1062 1063 name = _fsdev_io_in_arg_get_str(fuse_io); 1064 if (!name) { 1065 SPDK_ERRLOG("Cannot get name (compat=%d)\n", compat); 1066 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1067 return; 1068 } 1069 1070 err = spdk_fsdev_mknod(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1071 file_object(fuse_io), name, fsdev_io_d2h_u32(fuse_io, arg->mode), 1072 fsdev_io_d2h_u32(fuse_io, arg->rdev), fuse_io->hdr.uid, fuse_io->hdr.gid, 1073 do_mknod_cpl_clb, fuse_io); 1074 if (err) { 1075 fuse_dispatcher_io_complete_err(fuse_io, err); 1076 } 1077 } 1078 1079 static void 1080 do_mkdir_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 1081 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 1082 { 1083 struct fuse_io *fuse_io = cb_arg; 1084 1085 if (!status) { 1086 fuse_dispatcher_io_complete_entry(fuse_io, fobject, attr); 1087 } else { 1088 fuse_dispatcher_io_complete_err(fuse_io, status); 1089 } 1090 } 1091 1092 static void 1093 do_mkdir(struct fuse_io *fuse_io) 1094 { 1095 int err; 1096 bool compat = fsdev_io_proto_minor(fuse_io) < 12; 1097 struct fuse_mkdir_in *arg; 1098 const char *name; 1099 1100 arg = _fsdev_io_in_arg_get_buf(fuse_io, compat ? sizeof(uint32_t) : sizeof(*arg)); 1101 if (!arg) { 1102 SPDK_ERRLOG("Cannot get fuse_mkdir_in (compat=%d)\n", compat); 1103 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1104 return; 1105 } 1106 1107 name = _fsdev_io_in_arg_get_str(fuse_io); 1108 if (!name) { 1109 SPDK_ERRLOG("Cannot get name (compat=%d)\n", compat); 1110 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1111 return; 1112 } 1113 1114 err = spdk_fsdev_mkdir(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1115 file_object(fuse_io), name, fsdev_io_d2h_u32(fuse_io, arg->mode), 1116 fuse_io->hdr.uid, fuse_io->hdr.gid, do_mkdir_cpl_clb, fuse_io); 1117 if (err) { 1118 fuse_dispatcher_io_complete_err(fuse_io, err); 1119 } 1120 } 1121 1122 static void 1123 do_unlink_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 1124 { 1125 struct fuse_io *fuse_io = cb_arg; 1126 1127 fuse_dispatcher_io_complete_err(fuse_io, status); 1128 } 1129 1130 static void 1131 do_unlink(struct fuse_io *fuse_io) 1132 { 1133 int err; 1134 const char *name; 1135 1136 name = _fsdev_io_in_arg_get_str(fuse_io); 1137 if (!name) { 1138 SPDK_ERRLOG("Cannot get name\n"); 1139 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1140 return; 1141 } 1142 1143 err = spdk_fsdev_unlink(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1144 file_object(fuse_io), name, do_unlink_cpl_clb, fuse_io); 1145 if (err) { 1146 fuse_dispatcher_io_complete_err(fuse_io, err); 1147 } 1148 } 1149 1150 static void 1151 do_rmdir_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 1152 { 1153 struct fuse_io *fuse_io = cb_arg; 1154 1155 fuse_dispatcher_io_complete_err(fuse_io, status); 1156 } 1157 1158 static void 1159 do_rmdir(struct fuse_io *fuse_io) 1160 { 1161 int err; 1162 const char *name; 1163 1164 name = _fsdev_io_in_arg_get_str(fuse_io); 1165 if (!name) { 1166 SPDK_ERRLOG("Cannot get name\n"); 1167 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1168 return; 1169 } 1170 1171 err = spdk_fsdev_rmdir(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1172 file_object(fuse_io), name, do_rmdir_cpl_clb, fuse_io); 1173 if (err) { 1174 fuse_dispatcher_io_complete_err(fuse_io, err); 1175 } 1176 } 1177 1178 static void 1179 do_rename_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 1180 { 1181 struct fuse_io *fuse_io = cb_arg; 1182 1183 fuse_dispatcher_io_complete_err(fuse_io, status); 1184 } 1185 1186 static void 1187 do_rename_common(struct fuse_io *fuse_io, bool version2) 1188 { 1189 int err; 1190 uint64_t newdir; 1191 const char *oldname; 1192 const char *newname; 1193 uint32_t flags = 0; 1194 1195 if (!version2) { 1196 struct fuse_rename_in *arg; 1197 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 1198 if (!arg) { 1199 SPDK_ERRLOG("Cannot get fuse_rename_in\n"); 1200 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1201 return; 1202 } 1203 newdir = fsdev_io_d2h_u64(fuse_io, arg->newdir); 1204 } else { 1205 struct fuse_rename2_in *arg; 1206 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 1207 if (!arg) { 1208 SPDK_ERRLOG("Cannot get fuse_rename2_in\n"); 1209 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1210 return; 1211 } 1212 newdir = fsdev_io_d2h_u64(fuse_io, arg->newdir); 1213 flags = fsdev_io_d2h_u64(fuse_io, arg->flags); 1214 } 1215 1216 oldname = _fsdev_io_in_arg_get_str(fuse_io); 1217 if (!oldname) { 1218 SPDK_ERRLOG("Cannot get oldname\n"); 1219 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1220 return; 1221 } 1222 1223 newname = _fsdev_io_in_arg_get_str(fuse_io); 1224 if (!newname) { 1225 SPDK_ERRLOG("Cannot get newname\n"); 1226 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1227 return; 1228 } 1229 1230 err = spdk_fsdev_rename(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1231 file_object(fuse_io), oldname, ino_to_object(fuse_io, newdir), 1232 newname, flags, do_rename_cpl_clb, fuse_io); 1233 if (err) { 1234 fuse_dispatcher_io_complete_err(fuse_io, err); 1235 } 1236 } 1237 1238 static void 1239 do_rename(struct fuse_io *fuse_io) 1240 { 1241 do_rename_common(fuse_io, false); 1242 } 1243 1244 static void 1245 do_rename2(struct fuse_io *fuse_io) 1246 { 1247 do_rename_common(fuse_io, true); 1248 } 1249 1250 static void 1251 do_link_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 1252 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 1253 { 1254 struct fuse_io *fuse_io = cb_arg; 1255 1256 if (!status) { 1257 fuse_dispatcher_io_complete_entry(fuse_io, fobject, attr); 1258 } else { 1259 fuse_dispatcher_io_complete_err(fuse_io, status); 1260 } 1261 } 1262 1263 static void 1264 do_link(struct fuse_io *fuse_io) 1265 { 1266 int err; 1267 struct fuse_link_in *arg; 1268 const char *name; 1269 uint64_t oldnodeid; 1270 1271 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 1272 if (!arg) { 1273 SPDK_ERRLOG("Cannot get fuse_link_in\n"); 1274 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1275 return; 1276 } 1277 1278 name = _fsdev_io_in_arg_get_str(fuse_io); 1279 if (!name) { 1280 SPDK_ERRLOG("Cannot get name\n"); 1281 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1282 return; 1283 } 1284 1285 oldnodeid = fsdev_io_d2h_u64(fuse_io, arg->oldnodeid); 1286 1287 err = spdk_fsdev_link(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1288 ino_to_object(fuse_io, oldnodeid), file_object(fuse_io), name, 1289 do_link_cpl_clb, fuse_io); 1290 if (err) { 1291 fuse_dispatcher_io_complete_err(fuse_io, err); 1292 } 1293 } 1294 1295 static void 1296 do_fopen_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 1297 struct spdk_fsdev_file_handle *fhandle) 1298 { 1299 struct fuse_io *fuse_io = cb_arg; 1300 1301 if (!status) { 1302 fuse_dispatcher_io_complete_open(fuse_io, fhandle); 1303 } else { 1304 fuse_dispatcher_io_complete_err(fuse_io, status); 1305 } 1306 } 1307 1308 static void 1309 do_open(struct fuse_io *fuse_io) 1310 { 1311 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1312 int err; 1313 struct fuse_open_in *arg; 1314 uint32_t flags; 1315 1316 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 1317 if (!arg) { 1318 SPDK_ERRLOG("Cannot get fuse_forget_in\n"); 1319 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1320 return; 1321 } 1322 1323 if (!fsdev_d2h_open_flags(disp->fuse_arch, fsdev_io_d2h_u32(fuse_io, arg->flags), &flags)) { 1324 SPDK_ERRLOG("Cannot translate flags\n"); 1325 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1326 return; 1327 } 1328 1329 err = spdk_fsdev_fopen(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1330 file_object(fuse_io), flags, 1331 do_fopen_cpl_clb, fuse_io); 1332 if (err) { 1333 fuse_dispatcher_io_complete_err(fuse_io, err); 1334 } 1335 } 1336 1337 static void 1338 do_read_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, uint32_t data_size) 1339 { 1340 struct fuse_io *fuse_io = cb_arg; 1341 1342 fuse_dispatcher_io_complete(fuse_io, data_size, status); 1343 } 1344 1345 static void 1346 do_read(struct fuse_io *fuse_io) 1347 { 1348 int err; 1349 bool compat = fsdev_io_proto_minor(fuse_io) < 9; 1350 struct fuse_read_in *arg; 1351 uint64_t fh; 1352 uint32_t flags = 0; 1353 1354 arg = _fsdev_io_in_arg_get_buf(fuse_io, 1355 compat ? offsetof(struct fuse_read_in, lock_owner) : sizeof(*arg)); 1356 if (!arg) { 1357 SPDK_ERRLOG("Cannot get fuse_read_in\n"); 1358 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1359 return; 1360 } 1361 1362 1363 if (!compat) { 1364 flags = fsdev_io_d2h_u32(fuse_io, arg->flags); 1365 } 1366 1367 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 1368 1369 err = spdk_fsdev_read(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1370 file_object(fuse_io), file_handle(fh), 1371 fsdev_io_d2h_u32(fuse_io, arg->size), fsdev_io_d2h_u64(fuse_io, arg->offset), 1372 flags, fuse_io->out_iov + 1, fuse_io->out_iovcnt - 1, NULL, 1373 do_read_cpl_clb, fuse_io); 1374 if (err) { 1375 fuse_dispatcher_io_complete_err(fuse_io, err); 1376 } 1377 } 1378 1379 static void 1380 do_write_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, uint32_t data_size) 1381 { 1382 struct fuse_io *fuse_io = cb_arg; 1383 1384 fuse_dispatcher_io_complete_write(fuse_io, data_size, status); 1385 } 1386 1387 static void 1388 do_write(struct fuse_io *fuse_io) 1389 { 1390 int err; 1391 bool compat = fsdev_io_proto_minor(fuse_io) < 9; 1392 struct fuse_write_in *arg; 1393 uint64_t fh; 1394 uint64_t flags = 0; 1395 1396 arg = _fsdev_io_in_arg_get_buf(fuse_io, 1397 compat ? FUSE_COMPAT_WRITE_IN_SIZE : sizeof(*arg)); 1398 if (!arg) { 1399 SPDK_ERRLOG("Cannot get fuse_write_in\n"); 1400 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1401 return; 1402 } 1403 1404 if (fuse_io->in_offs.buf_offs) { 1405 SPDK_ERRLOG("Data IOVs should be separate from the header IOV\n"); 1406 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1407 return; 1408 } 1409 1410 if (!compat) { 1411 flags = fsdev_io_d2h_u32(fuse_io, arg->flags); 1412 } 1413 1414 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 1415 1416 err = spdk_fsdev_write(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1417 file_object(fuse_io), file_handle(fh), 1418 fsdev_io_d2h_u32(fuse_io, arg->size), fsdev_io_d2h_u64(fuse_io, arg->offset), 1419 flags, fuse_io->in_iov + fuse_io->in_offs.iov_offs, fuse_io->in_iovcnt - fuse_io->in_offs.iov_offs, 1420 NULL, do_write_cpl_clb, fuse_io); 1421 if (err) { 1422 fuse_dispatcher_io_complete_err(fuse_io, err); 1423 } 1424 } 1425 1426 static void 1427 do_statfs_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 1428 const struct spdk_fsdev_file_statfs *statfs) 1429 { 1430 struct fuse_io *fuse_io = cb_arg; 1431 1432 if (!status) { 1433 fuse_dispatcher_io_complete_statfs(fuse_io, statfs); 1434 } else { 1435 fuse_dispatcher_io_complete_err(fuse_io, status); 1436 } 1437 } 1438 1439 static void 1440 do_statfs(struct fuse_io *fuse_io) 1441 { 1442 int err; 1443 1444 err = spdk_fsdev_statfs(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1445 file_object(fuse_io), do_statfs_cpl_clb, fuse_io); 1446 if (err) { 1447 fuse_dispatcher_io_complete_err(fuse_io, err); 1448 } 1449 } 1450 1451 static void 1452 do_release_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 1453 { 1454 struct fuse_io *fuse_io = cb_arg; 1455 1456 fuse_dispatcher_io_complete_err(fuse_io, status); 1457 } 1458 1459 static void 1460 do_release(struct fuse_io *fuse_io) 1461 { 1462 int err; 1463 bool compat = fsdev_io_proto_minor(fuse_io) < 8; 1464 struct fuse_release_in *arg; 1465 uint64_t fh; 1466 1467 arg = _fsdev_io_in_arg_get_buf(fuse_io, 1468 compat ? offsetof(struct fuse_release_in, lock_owner) : sizeof(*arg)); 1469 if (!arg) { 1470 SPDK_ERRLOG("Cannot get fuse_release_in\n"); 1471 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1472 return; 1473 } 1474 1475 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 1476 1477 err = spdk_fsdev_release(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1478 file_object(fuse_io), file_handle(fh), 1479 do_release_cpl_clb, fuse_io); 1480 if (err) { 1481 fuse_dispatcher_io_complete_err(fuse_io, err); 1482 } 1483 } 1484 1485 static void 1486 do_fsync_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 1487 { 1488 struct fuse_io *fuse_io = cb_arg; 1489 1490 fuse_dispatcher_io_complete_err(fuse_io, status); 1491 } 1492 1493 static void 1494 do_fsync(struct fuse_io *fuse_io) 1495 { 1496 int err; 1497 struct fuse_fsync_in *arg; 1498 uint64_t fh; 1499 bool datasync; 1500 1501 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 1502 if (!arg) { 1503 SPDK_ERRLOG("Cannot get fuse_fsync_in\n"); 1504 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1505 return; 1506 } 1507 1508 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 1509 datasync = (fsdev_io_d2h_u32(fuse_io, arg->fsync_flags) & 1) ? true : false; 1510 1511 err = spdk_fsdev_fsync(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1512 file_object(fuse_io), file_handle(fh), datasync, 1513 do_fsync_cpl_clb, fuse_io); 1514 if (err) { 1515 fuse_dispatcher_io_complete_err(fuse_io, err); 1516 } 1517 } 1518 1519 static void 1520 do_setxattr_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 1521 { 1522 struct fuse_io *fuse_io = cb_arg; 1523 1524 fuse_dispatcher_io_complete_err(fuse_io, status); 1525 } 1526 1527 static void 1528 do_setxattr(struct fuse_io *fuse_io) 1529 { 1530 int err; 1531 struct fuse_setxattr_in *arg; 1532 const char *name; 1533 const char *value; 1534 uint32_t size; 1535 1536 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 1537 if (!arg) { 1538 SPDK_ERRLOG("Cannot get fuse_setxattr_in\n"); 1539 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1540 return; 1541 } 1542 1543 name = _fsdev_io_in_arg_get_str(fuse_io); 1544 if (!name) { 1545 SPDK_ERRLOG("Cannot get name\n"); 1546 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1547 return; 1548 } 1549 1550 size = fsdev_io_d2h_u32(fuse_io, arg->size); 1551 value = _fsdev_io_in_arg_get_buf(fuse_io, size); 1552 if (!value) { 1553 SPDK_ERRLOG("Cannot get value of %" PRIu32 " bytes\n", size); 1554 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1555 return; 1556 } 1557 1558 err = spdk_fsdev_setxattr(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1559 file_object(fuse_io), name, value, size, fsdev_io_d2h_u32(fuse_io, arg->flags), 1560 do_setxattr_cpl_clb, fuse_io); 1561 if (err) { 1562 fuse_dispatcher_io_complete_err(fuse_io, err); 1563 } 1564 } 1565 1566 static void 1567 do_getxattr_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, size_t value_size) 1568 { 1569 struct fuse_io *fuse_io = cb_arg; 1570 1571 if (!status) { 1572 fuse_dispatcher_io_complete_xattr(fuse_io, value_size); 1573 } else { 1574 fuse_dispatcher_io_complete_err(fuse_io, status); 1575 } 1576 } 1577 1578 static void 1579 do_getxattr(struct fuse_io *fuse_io) 1580 { 1581 int err; 1582 struct fuse_getxattr_in *arg; 1583 const char *name; 1584 char *buff; 1585 uint32_t size; 1586 struct iov_offs out_offs_bu; 1587 1588 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 1589 if (!arg) { 1590 SPDK_ERRLOG("Cannot get fuse_getxattr_in\n"); 1591 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1592 return; 1593 } 1594 1595 name = _fsdev_io_in_arg_get_str(fuse_io); 1596 if (!name) { 1597 SPDK_ERRLOG("Cannot get name\n"); 1598 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1599 return; 1600 } 1601 1602 if (fuse_io->out_iovcnt < 2) { 1603 SPDK_ERRLOG("No buffer to getxattr\n"); 1604 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1605 return; 1606 } 1607 1608 size = fsdev_io_d2h_u32(fuse_io, arg->size); 1609 1610 /* NOTE: we want to avoid an additionl allocation and copy and put the xattr directly to the buffer provided in out_iov. 1611 * In order to do so we have to preserve the out_offs, advance it to get the buffer pointer and then restore to allow 1612 * the fuse_dispatcher_io_complete_xattr() to fill the fuse_getxattr_out which precedes this buffer. 1613 */ 1614 out_offs_bu = fuse_io->out_offs; /* Preserve the out offset */ 1615 1616 /* Skip the fuse_getxattr_out */ 1617 _fsdev_io_out_arg_get_buf(fuse_io, sizeof(struct fuse_getxattr_out)); 1618 size -= sizeof(struct fuse_getxattr_out); 1619 1620 buff = _fsdev_io_out_arg_get_buf(fuse_io, size); /* Get the buffer for the xattr */ 1621 if (!buff) { 1622 SPDK_INFOLOG(fuse_dispatcher, "NULL buffer, probably asking for the size\n"); 1623 size = 0; 1624 } 1625 1626 fuse_io->out_offs = out_offs_bu; /* Restore the out offset */ 1627 1628 err = spdk_fsdev_getxattr(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1629 file_object(fuse_io), name, buff, size, 1630 do_getxattr_cpl_clb, fuse_io); 1631 if (err) { 1632 fuse_dispatcher_io_complete_err(fuse_io, err); 1633 } 1634 } 1635 1636 static void 1637 do_listxattr_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, size_t size, 1638 bool size_only) 1639 { 1640 struct fuse_io *fuse_io = cb_arg; 1641 1642 if (status) { 1643 fuse_dispatcher_io_complete_err(fuse_io, status); 1644 } else if (size_only) { 1645 fuse_dispatcher_io_complete_xattr(fuse_io, size); 1646 } else { 1647 fuse_dispatcher_io_complete_ok(fuse_io, size); 1648 } 1649 } 1650 1651 static void 1652 do_listxattr(struct fuse_io *fuse_io) 1653 { 1654 int err; 1655 struct fuse_getxattr_in *arg; 1656 struct iovec *iov; 1657 uint32_t size; 1658 1659 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 1660 if (!arg) { 1661 SPDK_ERRLOG("Cannot get fuse_getxattr_in\n"); 1662 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1663 return; 1664 } 1665 1666 size = fsdev_io_d2h_u32(fuse_io, arg->size); 1667 iov = fuse_io->out_iov + 1; 1668 if (iov->iov_len < size) { 1669 SPDK_ERRLOG("Wrong iov len (%zu < %" PRIu32")\n", iov->iov_len, size); 1670 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1671 return; 1672 } 1673 1674 err = spdk_fsdev_listxattr(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1675 file_object(fuse_io), iov->iov_base, size, 1676 do_listxattr_cpl_clb, fuse_io); 1677 if (err) { 1678 fuse_dispatcher_io_complete_err(fuse_io, err); 1679 } 1680 } 1681 1682 static void 1683 do_removexattr_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 1684 { 1685 struct fuse_io *fuse_io = cb_arg; 1686 1687 fuse_dispatcher_io_complete_err(fuse_io, status); 1688 } 1689 1690 static void 1691 do_removexattr(struct fuse_io *fuse_io) 1692 { 1693 int err; 1694 const char *name = _fsdev_io_in_arg_get_str(fuse_io); 1695 1696 if (!name) { 1697 SPDK_ERRLOG("Cannot get name\n"); 1698 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1699 return; 1700 } 1701 1702 err = spdk_fsdev_removexattr(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1703 file_object(fuse_io), name, do_removexattr_cpl_clb, fuse_io); 1704 if (err) { 1705 fuse_dispatcher_io_complete_err(fuse_io, err); 1706 } 1707 } 1708 1709 static void 1710 do_flush_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 1711 { 1712 struct fuse_io *fuse_io = cb_arg; 1713 1714 fuse_dispatcher_io_complete_err(fuse_io, status); 1715 } 1716 1717 static void 1718 do_flush(struct fuse_io *fuse_io) 1719 { 1720 int err; 1721 bool compat = fsdev_io_proto_minor(fuse_io) < 7; 1722 struct fuse_flush_in *arg; 1723 uint64_t fh; 1724 1725 arg = _fsdev_io_in_arg_get_buf(fuse_io, 1726 compat ? offsetof(struct fuse_flush_in, lock_owner) : sizeof(*arg)); 1727 if (!arg) { 1728 SPDK_ERRLOG("Cannot get fuse_flush_in\n"); 1729 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 1730 return; 1731 } 1732 1733 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 1734 1735 err = spdk_fsdev_flush(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 1736 file_object(fuse_io), file_handle(fh), 1737 do_flush_cpl_clb, fuse_io); 1738 if (err) { 1739 fuse_dispatcher_io_complete_err(fuse_io, err); 1740 } 1741 } 1742 1743 static void 1744 fuse_dispatcher_close_fsdev_and_complete_msg(void *ctx) 1745 { 1746 struct fuse_io *fuse_io = ctx; 1747 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1748 1749 spdk_fsdev_close(disp->desc); 1750 1751 SPDK_DEBUGLOG(fuse_dispatcher, "%s: fdev closed\n", fuse_dispatcher_name(disp)); 1752 1753 disp->desc = NULL; 1754 disp->fsdev_thread = NULL; 1755 1756 fuse_dispatcher_io_complete_err(fuse_io, fuse_io->u.fsdev_close.status); 1757 } 1758 1759 static void 1760 fuse_dispatcher_close_fsdev_and_complete(struct fuse_io *fuse_io, int status) 1761 { 1762 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1763 1764 assert(disp->desc); 1765 1766 fuse_io->u.fsdev_close.status = status; 1767 1768 if (disp->fsdev_thread != spdk_get_thread()) { 1769 spdk_thread_send_msg(disp->fsdev_thread, fuse_dispatcher_close_fsdev_and_complete_msg, fuse_io); 1770 } else { 1771 fuse_dispatcher_close_fsdev_and_complete_msg(fuse_io); 1772 } 1773 } 1774 1775 static void fuse_dispatcher_open_fsdev_rollback(struct fuse_io *fuse_io); 1776 1777 static void 1778 do_root_lookup_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 1779 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr) 1780 { 1781 struct fuse_io *fuse_io = cb_arg; 1782 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1783 1784 if (!status) { 1785 disp->root_fobject = fobject; 1786 SPDK_DEBUGLOG(fuse_dispatcher, "root fobject successfully acquired\n"); 1787 fuse_dispatcher_io_complete_ok(fuse_io, fuse_io->u.init.out_len); 1788 } else { 1789 SPDK_ERRLOG("Failed to lookup for root (err=%d)\n", status); 1790 fuse_dispatcher_open_fsdev_rollback(fuse_io); 1791 } 1792 } 1793 1794 static void 1795 fuse_dispatcher_err_put_channel(struct spdk_io_channel_iter *i) 1796 { 1797 struct spdk_io_channel *io_ch = spdk_io_channel_iter_get_channel(i); 1798 struct spdk_fuse_dispatcher_channel *ch = __disp_ch_from_io_ch(io_ch); 1799 1800 if (ch->fsdev_io_ch) { 1801 spdk_put_io_channel(ch->fsdev_io_ch); 1802 ch->fsdev_io_ch = NULL; 1803 } 1804 1805 spdk_for_each_channel_continue(i, 0); 1806 } 1807 1808 static void 1809 fuse_dispatcher_err_put_channel_done(struct spdk_io_channel_iter *i, int status) 1810 { 1811 struct fuse_io *fuse_io = spdk_io_channel_iter_get_ctx(i); 1812 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1813 1814 if (status) { 1815 SPDK_WARNLOG("%s: putting channels failed with %d\n", fuse_dispatcher_name(disp), status); 1816 /* For now, we continue anyway. We can retry fuse_dispatcher_open_fsdev_rollback, for example */ 1817 } 1818 1819 SPDK_DEBUGLOG(fuse_dispatcher, "%s: putting channels succeeded. Releasing the fdev\n", 1820 fuse_dispatcher_name(disp)); 1821 1822 fuse_dispatcher_close_fsdev_and_complete(fuse_io, ENODEV); 1823 } 1824 1825 static void 1826 fuse_dispatcher_open_fsdev_rollback(struct fuse_io *fuse_io) 1827 { 1828 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1829 1830 spdk_for_each_channel(__disp_to_io_dev(disp), 1831 fuse_dispatcher_err_put_channel, 1832 fuse_io, 1833 fuse_dispatcher_err_put_channel_done); 1834 } 1835 1836 static void 1837 fuse_dispatcher_open_fsdev_continue(struct fuse_io *fuse_io) 1838 { 1839 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1840 struct fuse_init_out outarg; 1841 size_t outargsize = sizeof(outarg); 1842 uint32_t max_readahead = DEFAULT_MAX_READAHEAD; 1843 uint32_t flags = 0; 1844 void *out_buf; 1845 int res; 1846 1847 assert(disp->desc); 1848 1849 memset(&outarg, 0, sizeof(outarg)); 1850 outarg.major = fsdev_io_h2d_u32(fuse_io, FUSE_KERNEL_VERSION); 1851 outarg.minor = fsdev_io_h2d_u32(fuse_io, FUSE_KERNEL_MINOR_VERSION); 1852 1853 if (disp->proto_minor < 5) { 1854 outargsize = FUSE_COMPAT_INIT_OUT_SIZE; 1855 } else if (disp->proto_minor < 23) { 1856 outargsize = FUSE_COMPAT_22_INIT_OUT_SIZE; 1857 } 1858 1859 if (!fuse_io->u.init.legacy_in) { 1860 max_readahead = fsdev_io_d2h_u32(fuse_io, fuse_io->u.init.in->max_readahead); 1861 flags = fsdev_io_d2h_u32(fuse_io, fuse_io->u.init.in->flags); 1862 1863 SPDK_INFOLOG(fuse_dispatcher, "max_readahead: %" PRIu32 " flags=0x%" PRIx32 "\n", 1864 max_readahead, flags); 1865 } 1866 1867 /* Always enable big writes, this is superseded by the max_write option */ 1868 outarg.flags = FUSE_BIG_WRITES; 1869 1870 #define LL_SET_DEFAULT(cond, cap) \ 1871 if ((cond) && flags & (cap)) \ 1872 outarg.flags |= (cap) 1873 LL_SET_DEFAULT(true, FUSE_ASYNC_READ); 1874 LL_SET_DEFAULT(true, FUSE_AUTO_INVAL_DATA); 1875 LL_SET_DEFAULT(true, FUSE_ASYNC_DIO); 1876 LL_SET_DEFAULT(true, FUSE_ATOMIC_O_TRUNC); 1877 LL_SET_DEFAULT(true, FUSE_FLOCK_LOCKS); 1878 LL_SET_DEFAULT(true, FUSE_DO_READDIRPLUS); 1879 LL_SET_DEFAULT(true, FUSE_READDIRPLUS_AUTO); 1880 LL_SET_DEFAULT(true, FUSE_EXPORT_SUPPORT); 1881 LL_SET_DEFAULT(fuse_io->u.init.opts.writeback_cache_enabled, FUSE_WRITEBACK_CACHE); 1882 1883 outarg.flags = fsdev_io_h2d_u32(fuse_io, outarg.flags); 1884 outarg.max_readahead = fsdev_io_h2d_u32(fuse_io, max_readahead); 1885 outarg.max_write = fsdev_io_h2d_u32(fuse_io, fuse_io->u.init.opts.max_write); 1886 if (fsdev_io_proto_minor(fuse_io) >= 13) { 1887 outarg.max_background = fsdev_io_h2d_u16(fuse_io, DEFAULT_MAX_BACKGROUND); 1888 outarg.congestion_threshold = fsdev_io_h2d_u16(fuse_io, DEFAULT_CONGESTION_THRESHOLD); 1889 } 1890 1891 if (fsdev_io_proto_minor(fuse_io) >= 23) { 1892 outarg.time_gran = fsdev_io_h2d_u32(fuse_io, DEFAULT_TIME_GRAN); 1893 } 1894 1895 SPDK_INFOLOG(fuse_dispatcher, "INIT: %" PRIu32 ".%" PRIu32 "\n", 1896 fsdev_io_d2h_u32(fuse_io, outarg.major), fsdev_io_d2h_u32(fuse_io, outarg.minor)); 1897 SPDK_INFOLOG(fuse_dispatcher, "flags: 0x%08" PRIx32 "\n", fsdev_io_d2h_u32(fuse_io, outarg.flags)); 1898 SPDK_INFOLOG(fuse_dispatcher, "max_readahead: %" PRIu32 "\n", 1899 fsdev_io_d2h_u32(fuse_io, outarg.max_readahead)); 1900 SPDK_INFOLOG(fuse_dispatcher, "max_write: %" PRIu32 "\n", 1901 fsdev_io_d2h_u32(fuse_io, outarg.max_write)); 1902 SPDK_INFOLOG(fuse_dispatcher, "max_background: %" PRIu16 "\n", 1903 fsdev_io_d2h_u16(fuse_io, outarg.max_background)); 1904 SPDK_INFOLOG(fuse_dispatcher, "congestion_threshold: %" PRIu16 "\n", 1905 fsdev_io_d2h_u16(fuse_io, outarg.congestion_threshold)); 1906 SPDK_INFOLOG(fuse_dispatcher, "time_gran: %" PRIu32 "\n", fsdev_io_d2h_u32(fuse_io, 1907 outarg.time_gran)); 1908 1909 out_buf = _fsdev_io_out_arg_get_buf(fuse_io, outargsize); 1910 if (!out_buf) { 1911 SPDK_ERRLOG("Cannot get buf to copy %zu bytes\n", outargsize); 1912 fuse_dispatcher_open_fsdev_rollback(fuse_io); 1913 return; 1914 } 1915 1916 memcpy(out_buf, &outarg, outargsize); 1917 1918 fuse_io->u.init.out_len = outargsize; 1919 1920 res = spdk_fsdev_lookup(fuse_io_desc(fuse_io), fuse_io->ch, 0, NULL /* root */, 1921 "" /* will be ignored */, do_root_lookup_cpl_clb, fuse_io); 1922 if (res) { 1923 SPDK_ERRLOG("Failed to initiate lookup for the root (err=%d)\n", res); 1924 fuse_dispatcher_open_fsdev_rollback(fuse_io); 1925 return; 1926 } 1927 } 1928 1929 static void 1930 fuse_dispatcher_get_channel(struct spdk_io_channel_iter *i) 1931 { 1932 struct fuse_io *fuse_io = spdk_io_channel_iter_get_ctx(i); 1933 struct spdk_io_channel *io_ch = spdk_io_channel_iter_get_channel(i); 1934 struct spdk_fuse_dispatcher_channel *ch = __disp_ch_from_io_ch(io_ch); 1935 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1936 1937 assert(!ch->fsdev_io_ch); 1938 1939 ch->fsdev_io_ch = spdk_fsdev_get_io_channel(disp->desc); 1940 1941 if (spdk_io_channel_get_thread(io_ch) == fuse_io->u.init.thread) { 1942 fuse_io->ch = ch->fsdev_io_ch; 1943 } 1944 1945 spdk_for_each_channel_continue(i, 0); 1946 } 1947 1948 static void 1949 fuse_dispatcher_get_channel_done(struct spdk_io_channel_iter *i, int status) 1950 { 1951 struct fuse_io *fuse_io = spdk_io_channel_iter_get_ctx(i); 1952 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1953 1954 if (status) { 1955 SPDK_ERRLOG("%s: getting channels failed with %d\n", fuse_dispatcher_name(disp), status); 1956 fuse_dispatcher_open_fsdev_rollback(fuse_io); 1957 return; 1958 } 1959 1960 SPDK_DEBUGLOG(fuse_dispatcher, "%s: getting succeeded\n", fuse_dispatcher_name(disp)); 1961 fuse_dispatcher_open_fsdev_continue(fuse_io); 1962 } 1963 1964 static void 1965 fuse_dispatcher_fsdev_remove_put_channel(struct spdk_io_channel_iter *i) 1966 { 1967 struct spdk_io_channel *io_ch = spdk_io_channel_iter_get_channel(i); 1968 struct spdk_fuse_dispatcher_channel *ch = __disp_ch_from_io_ch(io_ch); 1969 1970 assert(ch->fsdev_io_ch); 1971 spdk_put_io_channel(ch->fsdev_io_ch); 1972 ch->fsdev_io_ch = NULL; 1973 1974 spdk_for_each_channel_continue(i, 0); 1975 } 1976 1977 static void 1978 fuse_dispatcher_fsdev_remove_put_channel_done(struct spdk_io_channel_iter *i, int status) 1979 { 1980 struct fuse_io *fuse_io = spdk_io_channel_iter_get_ctx(i); 1981 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 1982 1983 if (status) { 1984 SPDK_WARNLOG("%s: putting channels failed with %d\n", fuse_dispatcher_name(disp), status); 1985 } 1986 1987 disp->event_cb(SPDK_FUSE_DISP_EVENT_FSDEV_REMOVE, disp, disp->event_ctx); 1988 } 1989 1990 static void 1991 fuse_dispatcher_fsdev_event_cb(enum spdk_fsdev_event_type type, struct spdk_fsdev *fsdev, 1992 void *event_ctx) 1993 { 1994 struct spdk_fuse_dispatcher *disp = event_ctx; 1995 1996 SPDK_NOTICELOG("%s received fsdev event %d\n", fuse_dispatcher_name(disp), type); 1997 1998 switch (type) { 1999 case SPDK_FSDEV_EVENT_REMOVE: 2000 SPDK_NOTICELOG("%s received SPDK_FSDEV_EVENT_REMOVE\n", fuse_dispatcher_name(disp)); 2001 /* Put the channels, to prevent the further IO submission */ 2002 spdk_for_each_channel(__disp_to_io_dev(disp), 2003 fuse_dispatcher_fsdev_remove_put_channel, 2004 disp, 2005 fuse_dispatcher_fsdev_remove_put_channel_done); 2006 break; 2007 default: 2008 SPDK_NOTICELOG("%s received an unknown fsdev event %d\n", fuse_dispatcher_name(disp), type); 2009 break; 2010 } 2011 } 2012 2013 static bool 2014 fuse_dispatcher_open_fsdev(struct fuse_io *fuse_io) 2015 { 2016 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 2017 int rc; 2018 2019 assert(!disp->desc); 2020 2021 rc = spdk_fsdev_open(disp->fsdev_name, fuse_dispatcher_fsdev_event_cb, disp, &fuse_io->u.init.opts, 2022 &disp->desc); 2023 if (rc) { 2024 SPDK_ERRLOG("spdk_fsdev_open failed with %d\n", rc); 2025 return false; 2026 } 2027 2028 disp->fsdev_thread = spdk_get_thread(); 2029 2030 SPDK_DEBUGLOG(fuse_dispatcher, "%s: spdk_fsdev_open succeeded\n", fuse_dispatcher_name(disp)); 2031 2032 spdk_for_each_channel(__disp_to_io_dev(disp), 2033 fuse_dispatcher_get_channel, 2034 fuse_io, 2035 fuse_dispatcher_get_channel_done); 2036 return true; 2037 } 2038 2039 static void 2040 do_init(struct fuse_io *fuse_io) 2041 { 2042 size_t compat_size = offsetof(struct fuse_init_in, max_readahead); 2043 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 2044 uint32_t flags = 0; 2045 2046 /* First try to read the legacy header */ 2047 fuse_io->u.init.in = _fsdev_io_in_arg_get_buf(fuse_io, compat_size); 2048 if (!fuse_io->u.init.in) { 2049 SPDK_ERRLOG("Cannot get fuse_init_in\n"); 2050 fuse_dispatcher_io_complete_err(fuse_io, -EBADR); 2051 return; 2052 } 2053 2054 disp->proto_major = fsdev_io_d2h_u32(fuse_io, fuse_io->u.init.in->major); 2055 disp->proto_minor = fsdev_io_d2h_u32(fuse_io, fuse_io->u.init.in->minor); 2056 2057 SPDK_DEBUGLOG(fuse_dispatcher, "Proto version: %" PRIu32 ".%" PRIu32 "\n", 2058 disp->proto_major, 2059 disp->proto_minor); 2060 2061 /* Now try to read the whole struct */ 2062 if (disp->proto_major == 7 && disp->proto_minor >= 6) { 2063 void *arg_extra = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*fuse_io->u.init.in) - compat_size); 2064 if (!arg_extra) { 2065 SPDK_ERRLOG("INIT: protocol version: %" PRIu32 ".%" PRIu32 " but legacy data found\n", 2066 disp->proto_major, disp->proto_minor); 2067 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2068 return; 2069 } 2070 fuse_io->u.init.legacy_in = false; 2071 } else { 2072 fuse_io->u.init.legacy_in = true; 2073 } 2074 2075 if (disp->proto_major < 7) { 2076 SPDK_ERRLOG("INIT: unsupported major protocol version: %" PRIu32 "\n", 2077 disp->proto_major); 2078 fuse_dispatcher_io_complete_err(fuse_io, -EAGAIN); 2079 return; 2080 } 2081 2082 if (disp->proto_major > 7) { 2083 /* Wait for a second INIT request with a 7.X version */ 2084 2085 struct fuse_init_out outarg; 2086 size_t outargsize = sizeof(outarg); 2087 2088 memset(&outarg, 0, sizeof(outarg)); 2089 outarg.major = fsdev_io_h2d_u32(fuse_io, FUSE_KERNEL_VERSION); 2090 outarg.minor = fsdev_io_h2d_u32(fuse_io, FUSE_KERNEL_MINOR_VERSION); 2091 2092 fuse_dispatcher_io_copy_and_complete(fuse_io, &outarg, outargsize, 0); 2093 return; 2094 } 2095 2096 if (!fuse_io->u.init.legacy_in) { 2097 flags = fsdev_io_d2h_u32(fuse_io, fuse_io->u.init.in->flags); 2098 2099 SPDK_INFOLOG(fuse_dispatcher, "flags=0x%" PRIx32 "\n", flags); 2100 } 2101 2102 memset(&fuse_io->u.init.opts, 0, sizeof(fuse_io->u.init.opts)); 2103 fuse_io->u.init.opts.opts_size = sizeof(fuse_io->u.init.opts); 2104 fuse_io->u.init.opts.max_write = 0; 2105 fuse_io->u.init.opts.writeback_cache_enabled = flags & FUSE_WRITEBACK_CACHE ? true : false; 2106 fuse_io->u.init.thread = spdk_get_thread(); 2107 2108 if (!fuse_dispatcher_open_fsdev(fuse_io)) { 2109 SPDK_ERRLOG("Cannot open underying fsdev\n"); 2110 fuse_dispatcher_io_complete_err(fuse_io, -ENODEV); 2111 return; 2112 } 2113 } 2114 2115 static void 2116 do_opendir_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 2117 struct spdk_fsdev_file_handle *fhandle) 2118 { 2119 struct fuse_io *fuse_io = cb_arg; 2120 2121 if (!status) { 2122 fuse_dispatcher_io_complete_open(fuse_io, fhandle); 2123 } else { 2124 fuse_dispatcher_io_complete_err(fuse_io, status); 2125 } 2126 } 2127 2128 static void 2129 do_opendir(struct fuse_io *fuse_io) 2130 { 2131 int err; 2132 struct fuse_open_in *arg; 2133 2134 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2135 if (!arg) { 2136 SPDK_ERRLOG("Cannot get fuse_open_in\n"); 2137 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2138 return; 2139 } 2140 2141 err = spdk_fsdev_opendir(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2142 file_object(fuse_io), fsdev_io_d2h_u32(fuse_io, arg->flags), 2143 do_opendir_cpl_clb, fuse_io); 2144 if (err) { 2145 fuse_dispatcher_io_complete_err(fuse_io, err); 2146 } 2147 } 2148 2149 static int 2150 do_readdir_entry_clb(void *cb_arg, struct spdk_io_channel *ch, const char *name, 2151 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr, off_t offset) 2152 { 2153 struct fuse_io *fuse_io = cb_arg; 2154 size_t bytes_remained = fuse_io->u.readdir.size - fuse_io->u.readdir.bytes_written; 2155 size_t direntry_bytes; 2156 2157 direntry_bytes = fuse_io->u.readdir.plus ? 2158 fuse_dispatcher_add_direntry_plus(fuse_io, fuse_io->u.readdir.writep, bytes_remained, 2159 name, fobject, attr, offset) : 2160 fuse_dispatcher_add_direntry(fuse_io, fuse_io->u.readdir.writep, bytes_remained, 2161 name, fobject, attr, offset); 2162 2163 if (direntry_bytes > bytes_remained) { 2164 return EAGAIN; 2165 } 2166 2167 fuse_io->u.readdir.writep += direntry_bytes; 2168 fuse_io->u.readdir.bytes_written += direntry_bytes; 2169 2170 return 0; 2171 } 2172 2173 static void 2174 do_readdir_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 2175 { 2176 struct fuse_io *fuse_io = cb_arg; 2177 2178 if (!status || (status == EAGAIN && fuse_io->u.readdir.bytes_written == fuse_io->u.readdir.size)) { 2179 fuse_dispatcher_io_complete_ok(fuse_io, fuse_io->u.readdir.bytes_written); 2180 } else { 2181 fuse_dispatcher_io_complete_err(fuse_io, status); 2182 } 2183 } 2184 2185 static void 2186 do_readdir_common(struct fuse_io *fuse_io, bool plus) 2187 { 2188 int err; 2189 struct fuse_read_in *arg; 2190 uint64_t fh; 2191 uint32_t size; 2192 2193 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2194 if (!arg) { 2195 SPDK_ERRLOG("Cannot get fuse_read_in\n"); 2196 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2197 return; 2198 } 2199 2200 size = fsdev_io_d2h_u32(fuse_io, arg->size); 2201 2202 fuse_io->u.readdir.writep = _fsdev_io_out_arg_get_buf(fuse_io, size); 2203 if (!fuse_io->u.readdir.writep) { 2204 SPDK_ERRLOG("Cannot get buffer of %" PRIu32 " bytes\n", size); 2205 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2206 return; 2207 } 2208 2209 fuse_io->u.readdir.plus = plus; 2210 fuse_io->u.readdir.size = size; 2211 fuse_io->u.readdir.bytes_written = 0; 2212 2213 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 2214 2215 err = spdk_fsdev_readdir(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2216 file_object(fuse_io), file_handle(fh), 2217 fsdev_io_d2h_u64(fuse_io, arg->offset), 2218 do_readdir_entry_clb, do_readdir_cpl_clb, fuse_io); 2219 if (err) { 2220 fuse_dispatcher_io_complete_err(fuse_io, err); 2221 } 2222 } 2223 2224 static void 2225 do_readdir(struct fuse_io *fuse_io) 2226 { 2227 do_readdir_common(fuse_io, false); 2228 } 2229 2230 static void 2231 do_readdirplus(struct fuse_io *fuse_io) 2232 { 2233 do_readdir_common(fuse_io, true); 2234 } 2235 2236 static void 2237 do_releasedir_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 2238 { 2239 struct fuse_io *fuse_io = cb_arg; 2240 2241 fuse_dispatcher_io_complete_err(fuse_io, status); 2242 } 2243 2244 static void 2245 do_releasedir(struct fuse_io *fuse_io) 2246 { 2247 int err; 2248 struct fuse_release_in *arg; 2249 uint64_t fh; 2250 2251 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2252 if (!arg) { 2253 SPDK_ERRLOG("Cannot get fuse_release_in\n"); 2254 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2255 return; 2256 } 2257 2258 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 2259 2260 err = spdk_fsdev_releasedir(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2261 file_object(fuse_io), file_handle(fh), 2262 do_releasedir_cpl_clb, fuse_io); 2263 if (err) { 2264 fuse_dispatcher_io_complete_err(fuse_io, err); 2265 } 2266 } 2267 2268 static void 2269 do_fsyncdir_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 2270 { 2271 struct fuse_io *fuse_io = cb_arg; 2272 2273 fuse_dispatcher_io_complete_err(fuse_io, status); 2274 } 2275 2276 static void 2277 do_fsyncdir(struct fuse_io *fuse_io) 2278 { 2279 int err; 2280 struct fuse_fsync_in *arg; 2281 uint64_t fh; 2282 bool datasync; 2283 2284 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2285 if (!arg) { 2286 SPDK_ERRLOG("Cannot get fuse_fsync_in\n"); 2287 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2288 return; 2289 } 2290 2291 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 2292 datasync = (fsdev_io_d2h_u32(fuse_io, arg->fsync_flags) & 1) ? true : false; 2293 2294 err = spdk_fsdev_fsyncdir(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2295 file_object(fuse_io), file_handle(fh), datasync, 2296 do_fsyncdir_cpl_clb, fuse_io); 2297 if (err) { 2298 fuse_dispatcher_io_complete_err(fuse_io, err); 2299 } 2300 } 2301 2302 static void 2303 do_getlk(struct fuse_io *fuse_io) 2304 { 2305 SPDK_ERRLOG("GETLK is not supported\n"); 2306 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2307 } 2308 2309 static void 2310 do_setlk_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 2311 { 2312 struct fuse_io *fuse_io = cb_arg; 2313 2314 fuse_dispatcher_io_complete_err(fuse_io, status); 2315 } 2316 2317 static void 2318 do_setlk_common(struct fuse_io *fuse_io) 2319 { 2320 int err; 2321 struct fuse_lk_in *arg; 2322 uint64_t fh; 2323 uint32_t lk_flags; 2324 2325 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2326 if (!arg) { 2327 SPDK_ERRLOG("Cannot get fuse_lk_in\n"); 2328 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2329 return; 2330 } 2331 2332 lk_flags = fsdev_io_d2h_u64(fuse_io, arg->lk_flags); 2333 2334 if (lk_flags & FUSE_LK_FLOCK) { 2335 int op = 0; 2336 2337 switch (arg->lk.type) { 2338 case F_RDLCK: 2339 op = LOCK_SH; 2340 break; 2341 case F_WRLCK: 2342 op = LOCK_EX; 2343 break; 2344 case F_UNLCK: 2345 op = LOCK_UN; 2346 break; 2347 } 2348 2349 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 2350 2351 err = spdk_fsdev_flock(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2352 file_object(fuse_io), file_handle(fh), op, 2353 do_setlk_cpl_clb, fuse_io); 2354 if (err) { 2355 fuse_dispatcher_io_complete_err(fuse_io, err); 2356 } 2357 } else { 2358 SPDK_ERRLOG("SETLK: with no FUSE_LK_FLOCK is not supported\n"); 2359 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2360 } 2361 } 2362 2363 static void 2364 do_setlk(struct fuse_io *fuse_io) 2365 { 2366 do_setlk_common(fuse_io); 2367 } 2368 2369 static void 2370 do_setlkw(struct fuse_io *fuse_io) 2371 { 2372 SPDK_ERRLOG("SETLKW is not supported\n"); 2373 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2374 } 2375 2376 static void 2377 do_access(struct fuse_io *fuse_io) 2378 { 2379 SPDK_ERRLOG("ACCESS is not supported\n"); 2380 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2381 } 2382 2383 static void 2384 do_create_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, 2385 struct spdk_fsdev_file_object *fobject, const struct spdk_fsdev_file_attr *attr, 2386 struct spdk_fsdev_file_handle *fhandle) 2387 { 2388 struct fuse_io *fuse_io = cb_arg; 2389 2390 if (!status) { 2391 fuse_dispatcher_io_complete_create(fuse_io, fobject, attr, fhandle); 2392 } else { 2393 fuse_dispatcher_io_complete_err(fuse_io, status); 2394 } 2395 } 2396 2397 static void 2398 do_create(struct fuse_io *fuse_io) 2399 { 2400 int err; 2401 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 2402 bool compat = fsdev_io_proto_minor(fuse_io) < 12; 2403 struct fuse_create_in *arg; 2404 const char *name; 2405 uint32_t flags, mode, umask = 0; 2406 size_t arg_size = compat ? sizeof(struct fuse_open_in) : sizeof(*arg); 2407 2408 arg = _fsdev_io_in_arg_get_buf(fuse_io, arg_size); 2409 if (!arg) { 2410 SPDK_ERRLOG("Cannot get fuse_create_in (compat=%d)\n", compat); 2411 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2412 return; 2413 } 2414 2415 name = _fsdev_io_in_arg_get_str(fuse_io); 2416 if (!name) { 2417 SPDK_ERRLOG("Cannot get name (compat=%d)\n", compat); 2418 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2419 return; 2420 } 2421 2422 mode = fsdev_io_d2h_u32(fuse_io, arg->mode); 2423 if (!compat) { 2424 umask = fsdev_io_d2h_u32(fuse_io, arg->umask); 2425 } 2426 2427 if (!fsdev_d2h_open_flags(disp->fuse_arch, fsdev_io_d2h_u32(fuse_io, arg->flags), &flags)) { 2428 SPDK_ERRLOG("Cannot translate flags\n"); 2429 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2430 return; 2431 } 2432 2433 err = spdk_fsdev_create(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2434 file_object(fuse_io), name, mode, flags, umask, fuse_io->hdr.uid, 2435 fuse_io->hdr.gid, do_create_cpl_clb, fuse_io); 2436 if (err) { 2437 fuse_dispatcher_io_complete_err(fuse_io, err); 2438 } 2439 } 2440 2441 static void 2442 do_abort_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 2443 { 2444 struct fuse_io *fuse_io = cb_arg; 2445 2446 fuse_dispatcher_io_complete_err(fuse_io, status); 2447 } 2448 2449 static void 2450 do_interrupt(struct fuse_io *fuse_io) 2451 { 2452 int err; 2453 struct fuse_interrupt_in *arg; 2454 uint64_t unique; 2455 2456 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2457 if (!arg) { 2458 SPDK_ERRLOG("Cannot get fuse_access_in\n"); 2459 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2460 return; 2461 } 2462 2463 unique = fsdev_io_d2h_u64(fuse_io, arg->unique); 2464 2465 SPDK_DEBUGLOG(fuse_dispatcher, "INTERRUPT: %" PRIu64 "\n", unique); 2466 2467 err = spdk_fsdev_abort(fuse_io_desc(fuse_io), fuse_io->ch, unique, do_abort_cpl_clb, fuse_io); 2468 if (err) { 2469 fuse_dispatcher_io_complete_err(fuse_io, err); 2470 } 2471 } 2472 2473 static void 2474 do_bmap(struct fuse_io *fuse_io) 2475 { 2476 SPDK_ERRLOG("BMAP is not supported\n"); 2477 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2478 } 2479 2480 static void 2481 do_ioctl(struct fuse_io *fuse_io) 2482 { 2483 SPDK_ERRLOG("IOCTL is not supported\n"); 2484 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2485 } 2486 2487 static void 2488 do_poll(struct fuse_io *fuse_io) 2489 { 2490 SPDK_ERRLOG("POLL is not supported\n"); 2491 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2492 } 2493 2494 static void 2495 do_fallocate_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 2496 { 2497 struct fuse_io *fuse_io = cb_arg; 2498 2499 fuse_dispatcher_io_complete_err(fuse_io, status); 2500 } 2501 2502 static void 2503 do_fallocate(struct fuse_io *fuse_io) 2504 { 2505 int err; 2506 struct fuse_fallocate_in *arg; 2507 uint64_t fh; 2508 2509 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2510 if (!arg) { 2511 SPDK_ERRLOG("Cannot get fuse_fallocate_in\n"); 2512 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2513 return; 2514 } 2515 2516 fh = fsdev_io_d2h_u64(fuse_io, arg->fh); 2517 2518 err = spdk_fsdev_fallocate(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2519 file_object(fuse_io), file_handle(fh), 2520 fsdev_io_d2h_u32(fuse_io, arg->mode), fsdev_io_d2h_u64(fuse_io, arg->offset), 2521 fsdev_io_d2h_u64(fuse_io, arg->length), 2522 do_fallocate_cpl_clb, fuse_io); 2523 if (err) { 2524 fuse_dispatcher_io_complete_err(fuse_io, err); 2525 } 2526 } 2527 2528 static void 2529 fuse_dispatcher_destroy_put_channel(struct spdk_io_channel_iter *i) 2530 { 2531 struct spdk_io_channel *io_ch = spdk_io_channel_iter_get_channel(i); 2532 struct spdk_fuse_dispatcher_channel *ch = __disp_ch_from_io_ch(io_ch); 2533 2534 if (ch->fsdev_io_ch) { 2535 spdk_put_io_channel(ch->fsdev_io_ch); 2536 ch->fsdev_io_ch = NULL; 2537 } 2538 2539 spdk_for_each_channel_continue(i, 0); 2540 } 2541 2542 static void 2543 fuse_dispatcher_destroy_put_channel_done(struct spdk_io_channel_iter *i, int status) 2544 { 2545 struct fuse_io *fuse_io = spdk_io_channel_iter_get_ctx(i); 2546 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 2547 2548 if (status) { 2549 SPDK_WARNLOG("%s: putting channels failed with %d\n", fuse_dispatcher_name(disp), status); 2550 fuse_dispatcher_io_complete_err(fuse_io, status); 2551 return; 2552 } 2553 2554 SPDK_DEBUGLOG(fuse_dispatcher, "%s: putting channels succeeded. Releasing the fdev\n", 2555 fuse_dispatcher_name(disp)); 2556 2557 fuse_dispatcher_close_fsdev_and_complete(fuse_io, 0); 2558 } 2559 2560 static void 2561 do_forget_root_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 2562 { 2563 struct fuse_io *fuse_io = cb_arg; 2564 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 2565 2566 if (status) { 2567 SPDK_ERRLOG("Failed to forget the root (err=%d)\n", status); 2568 fuse_dispatcher_io_complete_err(fuse_io, status); 2569 return; 2570 } 2571 2572 disp->root_fobject = NULL; 2573 SPDK_DEBUGLOG(fuse_dispatcher, "root fobject successfully forgotten\n"); 2574 2575 spdk_for_each_channel(__disp_to_io_dev(disp), 2576 fuse_dispatcher_destroy_put_channel, 2577 fuse_io, 2578 fuse_dispatcher_destroy_put_channel_done); 2579 } 2580 2581 static void 2582 do_destroy(struct fuse_io *fuse_io) 2583 { 2584 struct spdk_fuse_dispatcher *disp = fuse_io->disp; 2585 2586 disp->proto_major = disp->proto_minor = 0; 2587 2588 SPDK_DEBUGLOG(fuse_dispatcher, "DESTROY\n"); 2589 2590 if (disp->root_fobject) { 2591 int err = spdk_fsdev_forget(fuse_io_desc(fuse_io), fuse_io->ch, 0, disp->root_fobject, 1, 2592 do_forget_root_cpl_clb, fuse_io); 2593 if (err) { 2594 SPDK_ERRLOG("Failed to initiate forget for root (err=%d)\n", err); 2595 fuse_dispatcher_io_complete_err(fuse_io, err); 2596 return; 2597 } 2598 } else { 2599 fuse_dispatcher_close_fsdev_and_complete(fuse_io, 0); 2600 } 2601 } 2602 2603 static void 2604 do_batch_forget_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status) 2605 { 2606 struct fuse_io *fuse_io = cb_arg; 2607 2608 if (status) { 2609 fuse_io->u.batch_forget.status = status; 2610 } 2611 2612 fuse_io->u.batch_forget.to_forget--; 2613 2614 if (!fuse_io->u.batch_forget.to_forget) { 2615 /* FUSE_BATCH_FORGET requires no response */ 2616 fuse_dispatcher_io_complete_none(fuse_io, fuse_io->u.batch_forget.status); 2617 } 2618 } 2619 2620 static void 2621 do_batch_forget(struct fuse_io *fuse_io) 2622 { 2623 int err; 2624 struct fuse_batch_forget_in *arg; 2625 struct fuse_forget_data *forgets; 2626 size_t scount; 2627 uint32_t count, i; 2628 2629 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2630 if (!arg) { 2631 SPDK_ERRLOG("Cannot get fuse_batch_forget_in\n"); 2632 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2633 return; 2634 } 2635 2636 /* Prevent integer overflow. The compiler emits the following warning 2637 * unless we use the scount local variable: 2638 * 2639 * error: comparison is always false due to limited range of data type 2640 * [-Werror=type-limits] 2641 * 2642 * This may be true on 64-bit hosts but we need this check for 32-bit 2643 * hosts. 2644 */ 2645 scount = fsdev_io_d2h_u32(fuse_io, arg->count); 2646 if (scount > SIZE_MAX / sizeof(forgets[0])) { 2647 SPDK_WARNLOG("Too many forgets (%zu >= %zu)\n", scount, 2648 SIZE_MAX / sizeof(forgets[0])); 2649 /* FUSE_BATCH_FORGET requires no response */ 2650 fuse_dispatcher_io_complete_none(fuse_io, -EINVAL); 2651 return; 2652 } 2653 2654 count = scount; 2655 if (!count) { 2656 SPDK_WARNLOG("0 forgets requested\n"); 2657 /* FUSE_BATCH_FORGET requires no response */ 2658 fuse_dispatcher_io_complete_none(fuse_io, -EINVAL); 2659 return; 2660 } 2661 2662 forgets = _fsdev_io_in_arg_get_buf(fuse_io, count * sizeof(forgets[0])); 2663 if (!forgets) { 2664 SPDK_WARNLOG("Cannot get expected forgets (%" PRIu32 ")\n", count); 2665 /* FUSE_BATCH_FORGET requires no response */ 2666 fuse_dispatcher_io_complete_none(fuse_io, -EINVAL); 2667 return; 2668 } 2669 2670 fuse_io->u.batch_forget.to_forget = 0; 2671 fuse_io->u.batch_forget.status = 0; 2672 2673 for (i = 0; i < count; i++) { 2674 uint64_t ino = fsdev_io_d2h_u64(fuse_io, forgets[i].ino); 2675 uint64_t nlookup = fsdev_io_d2h_u64(fuse_io, forgets[i].nlookup); 2676 err = spdk_fsdev_forget(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2677 ino_to_object(fuse_io, ino), nlookup, 2678 do_batch_forget_cpl_clb, fuse_io); 2679 if (!err) { 2680 fuse_io->u.batch_forget.to_forget++; 2681 } else { 2682 fuse_io->u.batch_forget.status = err; 2683 } 2684 } 2685 2686 if (!fuse_io->u.batch_forget.to_forget) { 2687 /* FUSE_BATCH_FORGET requires no response */ 2688 fuse_dispatcher_io_complete_none(fuse_io, fuse_io->u.batch_forget.status); 2689 } 2690 } 2691 2692 static void 2693 do_copy_file_range_cpl_clb(void *cb_arg, struct spdk_io_channel *ch, int status, uint32_t data_size) 2694 { 2695 struct fuse_io *fuse_io = cb_arg; 2696 2697 fuse_dispatcher_io_complete_write(fuse_io, data_size, status); 2698 } 2699 2700 static void 2701 do_copy_file_range(struct fuse_io *fuse_io) 2702 { 2703 int err; 2704 struct fuse_copy_file_range_in *arg; 2705 uint64_t fh_in, fh_out, nodeid_out; 2706 2707 arg = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*arg)); 2708 if (!arg) { 2709 SPDK_ERRLOG("Cannot get fuse_copy_file_range_in\n"); 2710 fuse_dispatcher_io_complete_err(fuse_io, -EINVAL); 2711 return; 2712 } 2713 2714 fh_in = fsdev_io_d2h_u64(fuse_io, arg->fh_in); 2715 nodeid_out = fsdev_io_d2h_u64(fuse_io, arg->nodeid_out); 2716 fh_out = fsdev_io_d2h_u64(fuse_io, arg->fh_out); 2717 2718 err = spdk_fsdev_copy_file_range(fuse_io_desc(fuse_io), fuse_io->ch, fuse_io->hdr.unique, 2719 file_object(fuse_io), file_handle(fh_in), fsdev_io_d2h_u64(fuse_io, arg->off_in), 2720 ino_to_object(fuse_io, nodeid_out), file_handle(fh_out), fsdev_io_d2h_u64(fuse_io, arg->off_out), 2721 fsdev_io_d2h_u64(fuse_io, arg->len), fsdev_io_d2h_u64(fuse_io, arg->flags), 2722 do_copy_file_range_cpl_clb, fuse_io); 2723 2724 if (err) { 2725 fuse_dispatcher_io_complete_err(fuse_io, err); 2726 } 2727 } 2728 2729 static void 2730 do_setupmapping(struct fuse_io *fuse_io) 2731 { 2732 SPDK_ERRLOG("SETUPMAPPING is not supported\n"); 2733 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2734 } 2735 2736 static void 2737 do_removemapping(struct fuse_io *fuse_io) 2738 { 2739 SPDK_ERRLOG("REMOVEMAPPING is not supported\n"); 2740 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2741 } 2742 2743 static void 2744 do_syncfs(struct fuse_io *fuse_io) 2745 { 2746 SPDK_ERRLOG("SYNCFS is not supported\n"); 2747 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2748 } 2749 2750 static const struct { 2751 void (*func)(struct fuse_io *fuse_io); 2752 const char *name; 2753 } fuse_ll_ops[] = { 2754 [FUSE_LOOKUP] = { do_lookup, "LOOKUP" }, 2755 [FUSE_FORGET] = { do_forget, "FORGET" }, 2756 [FUSE_GETATTR] = { do_getattr, "GETATTR" }, 2757 [FUSE_SETATTR] = { do_setattr, "SETATTR" }, 2758 [FUSE_READLINK] = { do_readlink, "READLINK" }, 2759 [FUSE_SYMLINK] = { do_symlink, "SYMLINK" }, 2760 [FUSE_MKNOD] = { do_mknod, "MKNOD" }, 2761 [FUSE_MKDIR] = { do_mkdir, "MKDIR" }, 2762 [FUSE_UNLINK] = { do_unlink, "UNLINK" }, 2763 [FUSE_RMDIR] = { do_rmdir, "RMDIR" }, 2764 [FUSE_RENAME] = { do_rename, "RENAME" }, 2765 [FUSE_LINK] = { do_link, "LINK" }, 2766 [FUSE_OPEN] = { do_open, "OPEN" }, 2767 [FUSE_READ] = { do_read, "READ" }, 2768 [FUSE_WRITE] = { do_write, "WRITE" }, 2769 [FUSE_STATFS] = { do_statfs, "STATFS" }, 2770 [FUSE_RELEASE] = { do_release, "RELEASE" }, 2771 [FUSE_FSYNC] = { do_fsync, "FSYNC" }, 2772 [FUSE_SETXATTR] = { do_setxattr, "SETXATTR" }, 2773 [FUSE_GETXATTR] = { do_getxattr, "GETXATTR" }, 2774 [FUSE_LISTXATTR] = { do_listxattr, "LISTXATTR" }, 2775 [FUSE_REMOVEXATTR] = { do_removexattr, "REMOVEXATTR" }, 2776 [FUSE_FLUSH] = { do_flush, "FLUSH" }, 2777 [FUSE_INIT] = { do_init, "INIT" }, 2778 [FUSE_OPENDIR] = { do_opendir, "OPENDIR" }, 2779 [FUSE_READDIR] = { do_readdir, "READDIR" }, 2780 [FUSE_RELEASEDIR] = { do_releasedir, "RELEASEDIR" }, 2781 [FUSE_FSYNCDIR] = { do_fsyncdir, "FSYNCDIR" }, 2782 [FUSE_GETLK] = { do_getlk, "GETLK" }, 2783 [FUSE_SETLK] = { do_setlk, "SETLK" }, 2784 [FUSE_SETLKW] = { do_setlkw, "SETLKW" }, 2785 [FUSE_ACCESS] = { do_access, "ACCESS" }, 2786 [FUSE_CREATE] = { do_create, "CREATE" }, 2787 [FUSE_INTERRUPT] = { do_interrupt, "INTERRUPT" }, 2788 [FUSE_BMAP] = { do_bmap, "BMAP" }, 2789 [FUSE_IOCTL] = { do_ioctl, "IOCTL" }, 2790 [FUSE_POLL] = { do_poll, "POLL" }, 2791 [FUSE_FALLOCATE] = { do_fallocate, "FALLOCATE" }, 2792 [FUSE_DESTROY] = { do_destroy, "DESTROY" }, 2793 [FUSE_NOTIFY_REPLY] = { NULL, "NOTIFY_REPLY" }, 2794 [FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" }, 2795 [FUSE_READDIRPLUS] = { do_readdirplus, "READDIRPLUS"}, 2796 [FUSE_RENAME2] = { do_rename2, "RENAME2" }, 2797 [FUSE_COPY_FILE_RANGE] = { do_copy_file_range, "COPY_FILE_RANGE" }, 2798 [FUSE_SETUPMAPPING] = { do_setupmapping, "SETUPMAPPING" }, 2799 [FUSE_REMOVEMAPPING] = { do_removemapping, "REMOVEMAPPING" }, 2800 [FUSE_SYNCFS] = { do_syncfs, "SYNCFS" }, 2801 }; 2802 2803 static int 2804 spdk_fuse_dispatcher_handle_fuse_req(struct spdk_fuse_dispatcher *disp, struct fuse_io *fuse_io) 2805 { 2806 struct fuse_in_header *hdr; 2807 2808 if (!fuse_io->in_iovcnt || !fuse_io->in_iov) { 2809 SPDK_ERRLOG("Bad IO: no IN iov (%d, %p)\n", fuse_io->in_iovcnt, fuse_io->in_iov); 2810 goto exit; 2811 } 2812 2813 hdr = _fsdev_io_in_arg_get_buf(fuse_io, sizeof(*hdr)); 2814 if (!hdr) { 2815 SPDK_ERRLOG("Bad IO: cannot get fuse_in_header\n"); 2816 goto exit; 2817 } 2818 2819 fuse_io->hdr.opcode = fsdev_io_d2h_u32(fuse_io, hdr->opcode); 2820 2821 if (spdk_unlikely(!fuse_io->ch)) { 2822 /* FUSE_INIT is allowed with no channel. It'll open the fsdev and get channels */ 2823 if (fuse_io->hdr.opcode != FUSE_INIT) { 2824 /* The fsdev is not currently active. Complete this request. */ 2825 SPDK_ERRLOG("IO (%" PRIu32 ") arrived while there's no channel\n", fuse_io->hdr.opcode); 2826 goto exit; 2827 } 2828 } 2829 2830 if (spdk_likely(_fuse_op_requires_reply(hdr->opcode))) { 2831 struct fuse_out_header *out_hdr = _fsdev_io_out_arg_get_buf(fuse_io, sizeof(*out_hdr)); 2832 if (!out_hdr) { 2833 SPDK_ERRLOG("Bad IO: cannot get out_hdr\n"); 2834 goto exit; 2835 } 2836 2837 UNUSED(out_hdr); /* We don't need it here, we just made a check and a reservation */ 2838 } 2839 2840 if (fuse_io->hdr.opcode >= SPDK_COUNTOF(fuse_ll_ops)) { 2841 SPDK_ERRLOG("Bad IO: opt_code is out of range (%" PRIu32 " > %zu)\n", fuse_io->hdr.opcode, 2842 SPDK_COUNTOF(fuse_ll_ops)); 2843 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2844 return 0; 2845 } 2846 2847 if (!fuse_ll_ops[fuse_io->hdr.opcode].func) { 2848 SPDK_ERRLOG("Bad IO: no handler for (%" PRIu32 ") %s\n", fuse_io->hdr.opcode, 2849 fuse_ll_ops[fuse_io->hdr.opcode].name); 2850 fuse_dispatcher_io_complete_err(fuse_io, -ENOSYS); 2851 return 0; 2852 } 2853 2854 fuse_io->hdr.len = fsdev_io_d2h_u32(fuse_io, hdr->len); 2855 fuse_io->hdr.unique = fsdev_io_d2h_u64(fuse_io, hdr->unique); 2856 fuse_io->hdr.nodeid = fsdev_io_d2h_u64(fuse_io, hdr->nodeid); 2857 fuse_io->hdr.uid = fsdev_io_d2h_u32(fuse_io, hdr->uid); 2858 fuse_io->hdr.gid = fsdev_io_d2h_u32(fuse_io, hdr->gid); 2859 fuse_io->hdr.pid = fsdev_io_d2h_u32(fuse_io, hdr->pid); 2860 2861 SPDK_DEBUGLOG(fuse_dispatcher, "IO arrived: %" PRIu32 " (%s) len=%" PRIu32 " unique=%" PRIu64 2862 " nodeid=%" PRIu64 " uid=%" PRIu32 " gid=%" PRIu32 " pid=%" PRIu32 "\n", fuse_io->hdr.opcode, 2863 fuse_ll_ops[fuse_io->hdr.opcode].name, fuse_io->hdr.len, fuse_io->hdr.unique, 2864 fuse_io->hdr.nodeid, fuse_io->hdr.uid, fuse_io->hdr.gid, fuse_io->hdr.pid); 2865 2866 fuse_ll_ops[fuse_io->hdr.opcode].func(fuse_io); 2867 return 0; 2868 2869 exit: 2870 spdk_mempool_put(g_fuse_mgr.fuse_io_pool, fuse_io); 2871 return -EINVAL; 2872 } 2873 2874 static int 2875 fuse_dispatcher_channel_create(void *io_device, void *ctx_buf) 2876 { 2877 struct spdk_fuse_dispatcher *disp = __disp_from_io_dev(io_device); 2878 struct spdk_fuse_dispatcher_channel *ch = ctx_buf; 2879 2880 if (disp->desc) { 2881 ch->fsdev_io_ch = spdk_fsdev_get_io_channel(disp->desc); 2882 } 2883 2884 return 0; 2885 } 2886 2887 static void 2888 fuse_dispatcher_channel_destroy(void *io_device, void *ctx_buf) 2889 { 2890 struct spdk_fuse_dispatcher *disp = __disp_from_io_dev(io_device); 2891 struct spdk_fuse_dispatcher_channel *ch = ctx_buf; 2892 2893 UNUSED(disp); 2894 2895 if (ch->fsdev_io_ch) { 2896 assert(disp->desc); 2897 spdk_put_io_channel(ch->fsdev_io_ch); 2898 ch->fsdev_io_ch = NULL; 2899 } 2900 } 2901 2902 int 2903 spdk_fuse_dispatcher_create(const char *fsdev_name, spdk_fuse_dispatcher_event_cb event_cb, 2904 void *event_ctx, spdk_fuse_dispatcher_create_cpl_cb cb, void *cb_arg) 2905 { 2906 struct spdk_fuse_dispatcher *disp; 2907 char *io_dev_name; 2908 size_t fsdev_name_len; 2909 2910 if (!fsdev_name || !event_cb || !cb) { 2911 SPDK_ERRLOG("Invalid params\n"); 2912 return -EINVAL; 2913 } 2914 2915 io_dev_name = spdk_sprintf_alloc("fuse_disp_%s", fsdev_name); 2916 if (!io_dev_name) { 2917 SPDK_ERRLOG("Could not format io_dev name (%s)\n", fsdev_name); 2918 return -ENOMEM; 2919 } 2920 2921 fsdev_name_len = strlen(fsdev_name); 2922 2923 disp = calloc(1, sizeof(*disp) + fsdev_name_len + 1); 2924 if (!disp) { 2925 SPDK_ERRLOG("Could not allocate spdk_fuse_dispatcher\n"); 2926 free(io_dev_name); 2927 return -ENOMEM; 2928 } 2929 2930 pthread_mutex_lock(&g_fuse_mgr.lock); 2931 if (!g_fuse_mgr.ref_cnt) { 2932 struct spdk_fsdev_opts opts; 2933 spdk_fsdev_get_opts(&opts, sizeof(opts)); 2934 2935 g_fuse_mgr.fuse_io_pool = spdk_mempool_create("FUSE_disp_ios", opts.fsdev_io_pool_size, 2936 sizeof(struct fuse_io), opts.fsdev_io_cache_size, SPDK_ENV_NUMA_ID_ANY); 2937 if (!g_fuse_mgr.fuse_io_pool) { 2938 pthread_mutex_unlock(&g_fuse_mgr.lock); 2939 SPDK_ERRLOG("Could not create mempool\n"); 2940 free(io_dev_name); 2941 free(disp); 2942 return -ENOMEM; 2943 } 2944 } 2945 g_fuse_mgr.ref_cnt++; 2946 pthread_mutex_unlock(&g_fuse_mgr.lock); 2947 2948 spdk_io_device_register(__disp_to_io_dev(disp), 2949 fuse_dispatcher_channel_create, fuse_dispatcher_channel_destroy, 2950 sizeof(struct spdk_fuse_dispatcher_channel), 2951 io_dev_name); 2952 2953 free(io_dev_name); 2954 2955 memcpy(disp->fsdev_name, fsdev_name, fsdev_name_len + 1); 2956 disp->event_cb = event_cb; 2957 disp->event_ctx = event_ctx; 2958 disp->fuse_arch = SPDK_FUSE_ARCH_NATIVE; 2959 2960 cb(cb_arg, disp); 2961 2962 return 0; 2963 } 2964 2965 int 2966 spdk_fuse_dispatcher_set_arch(struct spdk_fuse_dispatcher *disp, enum spdk_fuse_arch fuse_arch) 2967 { 2968 switch (fuse_arch) { 2969 case SPDK_FUSE_ARCH_NATIVE: 2970 case SPDK_FUSE_ARCH_X86: 2971 case SPDK_FUSE_ARCH_X86_64: 2972 case SPDK_FUSE_ARCH_ARM: 2973 case SPDK_FUSE_ARCH_ARM64: 2974 SPDK_NOTICELOG("FUSE arch set to %d\n", fuse_arch); 2975 disp->fuse_arch = fuse_arch; 2976 return 0; 2977 default: 2978 return -EINVAL; 2979 } 2980 } 2981 2982 const char * 2983 spdk_fuse_dispatcher_get_fsdev_name(struct spdk_fuse_dispatcher *disp) 2984 { 2985 return fuse_dispatcher_name(disp); 2986 } 2987 2988 struct spdk_io_channel * 2989 spdk_fuse_dispatcher_get_io_channel(struct spdk_fuse_dispatcher *disp) 2990 { 2991 return spdk_get_io_channel(__disp_to_io_dev(disp)); 2992 } 2993 2994 int 2995 spdk_fuse_dispatcher_submit_request(struct spdk_fuse_dispatcher *disp, 2996 struct spdk_io_channel *ch, 2997 struct iovec *in_iov, int in_iovcnt, 2998 struct iovec *out_iov, int out_iovcnt, 2999 spdk_fuse_dispatcher_submit_cpl_cb clb, void *cb_arg) 3000 { 3001 struct fuse_io *fuse_io; 3002 struct spdk_fuse_dispatcher_channel *disp_ch = __disp_ch_from_io_ch(ch); 3003 3004 fuse_io = spdk_mempool_get(g_fuse_mgr.fuse_io_pool); 3005 3006 if (!fuse_io) { 3007 SPDK_ERRLOG("We ran out of FUSE IOs\n"); 3008 return -ENOBUFS; 3009 } 3010 3011 fuse_io->disp = disp; 3012 fuse_io->ch = disp_ch->fsdev_io_ch; 3013 fuse_io->in_iov = in_iov; 3014 fuse_io->in_iovcnt = in_iovcnt; 3015 fuse_io->out_iov = out_iov; 3016 fuse_io->out_iovcnt = out_iovcnt; 3017 fuse_io->cpl_cb = clb; 3018 fuse_io->cpl_cb_arg = cb_arg; 3019 3020 fuse_io->in_offs.iov_offs = 0; 3021 fuse_io->in_offs.buf_offs = 0; 3022 fuse_io->out_offs.iov_offs = 0; 3023 fuse_io->out_offs.buf_offs = 0; 3024 3025 return spdk_fuse_dispatcher_handle_fuse_req(disp, fuse_io); 3026 } 3027 3028 struct fuse_dispatcher_delete_ctx { 3029 struct spdk_fuse_dispatcher *disp; 3030 spdk_fuse_dispatcher_delete_cpl_cb cb; 3031 void *cb_arg; 3032 }; 3033 3034 static void 3035 fuse_dispatcher_delete_done(struct fuse_dispatcher_delete_ctx *ctx, int status) 3036 { 3037 struct spdk_fuse_dispatcher *disp = ctx->disp; 3038 3039 if (!status) { 3040 SPDK_DEBUGLOG(fuse_dispatcher, "%s: deletion succeeded\n", fuse_dispatcher_name(disp)); 3041 3042 spdk_io_device_unregister(__disp_to_io_dev(disp), NULL); 3043 3044 free(disp); 3045 3046 pthread_mutex_lock(&g_fuse_mgr.lock); 3047 g_fuse_mgr.ref_cnt--; 3048 if (!g_fuse_mgr.ref_cnt) { 3049 spdk_mempool_free(g_fuse_mgr.fuse_io_pool); 3050 g_fuse_mgr.fuse_io_pool = NULL; 3051 } 3052 pthread_mutex_unlock(&g_fuse_mgr.lock); 3053 } else { 3054 SPDK_ERRLOG("%s: deletion failed with %d\n", fuse_dispatcher_name(disp), status); 3055 } 3056 3057 ctx->cb(ctx->cb_arg, (uint32_t)(-status)); 3058 free(ctx); 3059 } 3060 3061 static void 3062 fuse_dispatcher_delete_put_channel(struct spdk_io_channel_iter *i) 3063 { 3064 struct spdk_io_channel *io_ch = spdk_io_channel_iter_get_channel(i); 3065 struct spdk_fuse_dispatcher_channel *ch = __disp_ch_from_io_ch(io_ch); 3066 3067 if (ch->fsdev_io_ch) { 3068 spdk_put_io_channel(ch->fsdev_io_ch); 3069 ch->fsdev_io_ch = NULL; 3070 } 3071 3072 spdk_for_each_channel_continue(i, 0); 3073 } 3074 3075 static void 3076 fuse_dispatcher_delete_put_channel_done(struct spdk_io_channel_iter *i, int status) 3077 { 3078 struct fuse_dispatcher_delete_ctx *ctx = spdk_io_channel_iter_get_ctx(i); 3079 struct spdk_fuse_dispatcher *disp = ctx->disp; 3080 3081 if (status) { 3082 SPDK_ERRLOG("%s: putting channels failed with %d\n", fuse_dispatcher_name(disp), status); 3083 fuse_dispatcher_delete_done(ctx, status); 3084 return; 3085 } 3086 3087 SPDK_DEBUGLOG(fuse_dispatcher, "%s: putting channels succeeded. Releasing the fdev\n", 3088 fuse_dispatcher_name(disp)); 3089 3090 spdk_fsdev_close(disp->desc); 3091 3092 fuse_dispatcher_delete_done(ctx, 0); 3093 } 3094 3095 int 3096 spdk_fuse_dispatcher_delete(struct spdk_fuse_dispatcher *disp, 3097 spdk_fuse_dispatcher_delete_cpl_cb cb, void *cb_arg) 3098 { 3099 struct fuse_dispatcher_delete_ctx *ctx; 3100 3101 ctx = calloc(1, sizeof(*ctx)); 3102 if (!ctx) { 3103 SPDK_ERRLOG("cannot allocate context\n"); 3104 return -ENOMEM; 3105 } 3106 3107 ctx->disp = disp; 3108 ctx->cb = cb; 3109 ctx->cb_arg = cb_arg; 3110 3111 if (disp->desc) { 3112 SPDK_DEBUGLOG(fuse_dispatcher, "%s: fsdev still open. Releasing the channels.\n", 3113 fuse_dispatcher_name(disp)); 3114 3115 spdk_for_each_channel(__disp_to_io_dev(disp), 3116 fuse_dispatcher_delete_put_channel, 3117 ctx, 3118 fuse_dispatcher_delete_put_channel_done); 3119 } else { 3120 fuse_dispatcher_delete_done(ctx, 0); 3121 } 3122 3123 return 0; 3124 } 3125 3126 SPDK_LOG_REGISTER_COMPONENT(fuse_dispatcher) 3127