1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/stdinc.h" 35 36 #include "spdk/blobfs.h" 37 #include "spdk/conf.h" 38 #include "blobfs_internal.h" 39 40 #include "spdk/queue.h" 41 #include "spdk/thread.h" 42 #include "spdk/assert.h" 43 #include "spdk/env.h" 44 #include "spdk/util.h" 45 #include "spdk_internal/log.h" 46 #include "spdk/trace.h" 47 48 #define BLOBFS_TRACE(file, str, args...) \ 49 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s " str, file->name, ##args) 50 51 #define BLOBFS_TRACE_RW(file, str, args...) \ 52 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS_RW, "file=%s " str, file->name, ##args) 53 54 #define BLOBFS_DEFAULT_CACHE_SIZE (4ULL * 1024 * 1024 * 1024) 55 #define SPDK_BLOBFS_DEFAULT_OPTS_CLUSTER_SZ (1024 * 1024) 56 57 static uint64_t g_fs_cache_size = BLOBFS_DEFAULT_CACHE_SIZE; 58 static struct spdk_mempool *g_cache_pool; 59 static TAILQ_HEAD(, spdk_file) g_caches; 60 static int g_fs_count = 0; 61 static pthread_mutex_t g_cache_init_lock = PTHREAD_MUTEX_INITIALIZER; 62 static pthread_spinlock_t g_caches_lock; 63 64 #define TRACE_GROUP_BLOBFS 0x7 65 #define TRACE_BLOBFS_XATTR_START SPDK_TPOINT_ID(TRACE_GROUP_BLOBFS, 0x0) 66 #define TRACE_BLOBFS_XATTR_END SPDK_TPOINT_ID(TRACE_GROUP_BLOBFS, 0x1) 67 #define TRACE_BLOBFS_OPEN SPDK_TPOINT_ID(TRACE_GROUP_BLOBFS, 0x2) 68 #define TRACE_BLOBFS_CLOSE SPDK_TPOINT_ID(TRACE_GROUP_BLOBFS, 0x3) 69 #define TRACE_BLOBFS_DELETE_START SPDK_TPOINT_ID(TRACE_GROUP_BLOBFS, 0x4) 70 #define TRACE_BLOBFS_DELETE_DONE SPDK_TPOINT_ID(TRACE_GROUP_BLOBFS, 0x5) 71 72 SPDK_TRACE_REGISTER_FN(blobfs_trace, "blobfs", TRACE_GROUP_BLOBFS) 73 { 74 spdk_trace_register_description("BLOBFS_XATTR_START", 75 TRACE_BLOBFS_XATTR_START, 76 OWNER_NONE, OBJECT_NONE, 0, 77 SPDK_TRACE_ARG_TYPE_STR, 78 "file: "); 79 spdk_trace_register_description("BLOBFS_XATTR_END", 80 TRACE_BLOBFS_XATTR_END, 81 OWNER_NONE, OBJECT_NONE, 0, 82 SPDK_TRACE_ARG_TYPE_STR, 83 "file: "); 84 spdk_trace_register_description("BLOBFS_OPEN", 85 TRACE_BLOBFS_OPEN, 86 OWNER_NONE, OBJECT_NONE, 0, 87 SPDK_TRACE_ARG_TYPE_STR, 88 "file: "); 89 spdk_trace_register_description("BLOBFS_CLOSE", 90 TRACE_BLOBFS_CLOSE, 91 OWNER_NONE, OBJECT_NONE, 0, 92 SPDK_TRACE_ARG_TYPE_STR, 93 "file: "); 94 spdk_trace_register_description("BLOBFS_DELETE_START", 95 TRACE_BLOBFS_DELETE_START, 96 OWNER_NONE, OBJECT_NONE, 0, 97 SPDK_TRACE_ARG_TYPE_STR, 98 "file: "); 99 spdk_trace_register_description("BLOBFS_DELETE_DONE", 100 TRACE_BLOBFS_DELETE_DONE, 101 OWNER_NONE, OBJECT_NONE, 0, 102 SPDK_TRACE_ARG_TYPE_STR, 103 "file: "); 104 } 105 106 void 107 spdk_cache_buffer_free(struct cache_buffer *cache_buffer) 108 { 109 spdk_mempool_put(g_cache_pool, cache_buffer->buf); 110 free(cache_buffer); 111 } 112 113 #define CACHE_READAHEAD_THRESHOLD (128 * 1024) 114 115 struct spdk_file { 116 struct spdk_filesystem *fs; 117 struct spdk_blob *blob; 118 char *name; 119 uint64_t trace_arg_name; 120 uint64_t length; 121 bool is_deleted; 122 bool open_for_writing; 123 uint64_t length_flushed; 124 uint64_t append_pos; 125 uint64_t seq_byte_count; 126 uint64_t next_seq_offset; 127 uint32_t priority; 128 TAILQ_ENTRY(spdk_file) tailq; 129 spdk_blob_id blobid; 130 uint32_t ref_count; 131 pthread_spinlock_t lock; 132 struct cache_buffer *last; 133 struct cache_tree *tree; 134 TAILQ_HEAD(open_requests_head, spdk_fs_request) open_requests; 135 TAILQ_HEAD(sync_requests_head, spdk_fs_request) sync_requests; 136 TAILQ_ENTRY(spdk_file) cache_tailq; 137 }; 138 139 struct spdk_deleted_file { 140 spdk_blob_id id; 141 TAILQ_ENTRY(spdk_deleted_file) tailq; 142 }; 143 144 struct spdk_filesystem { 145 struct spdk_blob_store *bs; 146 TAILQ_HEAD(, spdk_file) files; 147 struct spdk_bs_opts bs_opts; 148 struct spdk_bs_dev *bdev; 149 fs_send_request_fn send_request; 150 151 struct { 152 uint32_t max_ops; 153 struct spdk_io_channel *sync_io_channel; 154 struct spdk_fs_channel *sync_fs_channel; 155 } sync_target; 156 157 struct { 158 uint32_t max_ops; 159 struct spdk_io_channel *md_io_channel; 160 struct spdk_fs_channel *md_fs_channel; 161 } md_target; 162 163 struct { 164 uint32_t max_ops; 165 } io_target; 166 }; 167 168 struct spdk_fs_cb_args { 169 union { 170 spdk_fs_op_with_handle_complete fs_op_with_handle; 171 spdk_fs_op_complete fs_op; 172 spdk_file_op_with_handle_complete file_op_with_handle; 173 spdk_file_op_complete file_op; 174 spdk_file_stat_op_complete stat_op; 175 } fn; 176 void *arg; 177 sem_t *sem; 178 struct spdk_filesystem *fs; 179 struct spdk_file *file; 180 int rc; 181 struct iovec *iovs; 182 uint32_t iovcnt; 183 struct iovec iov; 184 union { 185 struct { 186 TAILQ_HEAD(, spdk_deleted_file) deleted_files; 187 } fs_load; 188 struct { 189 uint64_t length; 190 } truncate; 191 struct { 192 struct spdk_io_channel *channel; 193 void *pin_buf; 194 int is_read; 195 off_t offset; 196 size_t length; 197 uint64_t start_lba; 198 uint64_t num_lba; 199 uint32_t blocklen; 200 } rw; 201 struct { 202 const char *old_name; 203 const char *new_name; 204 } rename; 205 struct { 206 struct cache_buffer *cache_buffer; 207 uint64_t length; 208 } flush; 209 struct { 210 struct cache_buffer *cache_buffer; 211 uint64_t length; 212 uint64_t offset; 213 } readahead; 214 struct { 215 uint64_t offset; 216 TAILQ_ENTRY(spdk_fs_request) tailq; 217 bool xattr_in_progress; 218 } sync; 219 struct { 220 uint32_t num_clusters; 221 } resize; 222 struct { 223 const char *name; 224 uint32_t flags; 225 TAILQ_ENTRY(spdk_fs_request) tailq; 226 } open; 227 struct { 228 const char *name; 229 struct spdk_blob *blob; 230 } create; 231 struct { 232 const char *name; 233 } delete; 234 struct { 235 const char *name; 236 } stat; 237 } op; 238 }; 239 240 static void cache_free_buffers(struct spdk_file *file); 241 static void spdk_fs_io_device_unregister(struct spdk_filesystem *fs); 242 static void spdk_fs_free_io_channels(struct spdk_filesystem *fs); 243 244 void 245 spdk_fs_opts_init(struct spdk_blobfs_opts *opts) 246 { 247 opts->cluster_sz = SPDK_BLOBFS_DEFAULT_OPTS_CLUSTER_SZ; 248 } 249 250 static void 251 __initialize_cache(void) 252 { 253 assert(g_cache_pool == NULL); 254 255 g_cache_pool = spdk_mempool_create("spdk_fs_cache", 256 g_fs_cache_size / CACHE_BUFFER_SIZE, 257 CACHE_BUFFER_SIZE, 258 SPDK_MEMPOOL_DEFAULT_CACHE_SIZE, 259 SPDK_ENV_SOCKET_ID_ANY); 260 if (!g_cache_pool) { 261 SPDK_ERRLOG("Create mempool failed, you may " 262 "increase the memory and try again\n"); 263 assert(false); 264 } 265 TAILQ_INIT(&g_caches); 266 pthread_spin_init(&g_caches_lock, 0); 267 } 268 269 static void 270 __free_cache(void) 271 { 272 assert(g_cache_pool != NULL); 273 274 spdk_mempool_free(g_cache_pool); 275 g_cache_pool = NULL; 276 } 277 278 static uint64_t 279 __file_get_blob_size(struct spdk_file *file) 280 { 281 uint64_t cluster_sz; 282 283 cluster_sz = file->fs->bs_opts.cluster_sz; 284 return cluster_sz * spdk_blob_get_num_clusters(file->blob); 285 } 286 287 struct spdk_fs_request { 288 struct spdk_fs_cb_args args; 289 TAILQ_ENTRY(spdk_fs_request) link; 290 struct spdk_fs_channel *channel; 291 }; 292 293 struct spdk_fs_channel { 294 struct spdk_fs_request *req_mem; 295 TAILQ_HEAD(, spdk_fs_request) reqs; 296 sem_t sem; 297 struct spdk_filesystem *fs; 298 struct spdk_io_channel *bs_channel; 299 fs_send_request_fn send_request; 300 bool sync; 301 uint32_t outstanding_reqs; 302 pthread_spinlock_t lock; 303 }; 304 305 /* For now, this is effectively an alias. But eventually we'll shift 306 * some data members over. */ 307 struct spdk_fs_thread_ctx { 308 struct spdk_fs_channel ch; 309 }; 310 311 static struct spdk_fs_request * 312 alloc_fs_request_with_iov(struct spdk_fs_channel *channel, uint32_t iovcnt) 313 { 314 struct spdk_fs_request *req; 315 struct iovec *iovs = NULL; 316 317 if (iovcnt > 1) { 318 iovs = calloc(iovcnt, sizeof(struct iovec)); 319 if (!iovs) { 320 return NULL; 321 } 322 } 323 324 if (channel->sync) { 325 pthread_spin_lock(&channel->lock); 326 } 327 328 req = TAILQ_FIRST(&channel->reqs); 329 if (req) { 330 channel->outstanding_reqs++; 331 TAILQ_REMOVE(&channel->reqs, req, link); 332 } 333 334 if (channel->sync) { 335 pthread_spin_unlock(&channel->lock); 336 } 337 338 if (req == NULL) { 339 SPDK_ERRLOG("Cannot allocate req on spdk_fs_channel =%p\n", channel); 340 free(iovs); 341 return NULL; 342 } 343 memset(req, 0, sizeof(*req)); 344 req->channel = channel; 345 if (iovcnt > 1) { 346 req->args.iovs = iovs; 347 } else { 348 req->args.iovs = &req->args.iov; 349 } 350 req->args.iovcnt = iovcnt; 351 352 return req; 353 } 354 355 static struct spdk_fs_request * 356 alloc_fs_request(struct spdk_fs_channel *channel) 357 { 358 return alloc_fs_request_with_iov(channel, 0); 359 } 360 361 static void 362 free_fs_request(struct spdk_fs_request *req) 363 { 364 struct spdk_fs_channel *channel = req->channel; 365 366 if (req->args.iovcnt > 1) { 367 free(req->args.iovs); 368 } 369 370 if (channel->sync) { 371 pthread_spin_lock(&channel->lock); 372 } 373 374 TAILQ_INSERT_HEAD(&req->channel->reqs, req, link); 375 channel->outstanding_reqs--; 376 377 if (channel->sync) { 378 pthread_spin_unlock(&channel->lock); 379 } 380 } 381 382 static int 383 _spdk_fs_channel_create(struct spdk_filesystem *fs, struct spdk_fs_channel *channel, 384 uint32_t max_ops) 385 { 386 uint32_t i; 387 388 channel->req_mem = calloc(max_ops, sizeof(struct spdk_fs_request)); 389 if (!channel->req_mem) { 390 return -1; 391 } 392 393 channel->outstanding_reqs = 0; 394 TAILQ_INIT(&channel->reqs); 395 sem_init(&channel->sem, 0, 0); 396 397 for (i = 0; i < max_ops; i++) { 398 TAILQ_INSERT_TAIL(&channel->reqs, &channel->req_mem[i], link); 399 } 400 401 channel->fs = fs; 402 403 return 0; 404 } 405 406 static int 407 _spdk_fs_md_channel_create(void *io_device, void *ctx_buf) 408 { 409 struct spdk_filesystem *fs; 410 struct spdk_fs_channel *channel = ctx_buf; 411 412 fs = SPDK_CONTAINEROF(io_device, struct spdk_filesystem, md_target); 413 414 return _spdk_fs_channel_create(fs, channel, fs->md_target.max_ops); 415 } 416 417 static int 418 _spdk_fs_sync_channel_create(void *io_device, void *ctx_buf) 419 { 420 struct spdk_filesystem *fs; 421 struct spdk_fs_channel *channel = ctx_buf; 422 423 fs = SPDK_CONTAINEROF(io_device, struct spdk_filesystem, sync_target); 424 425 return _spdk_fs_channel_create(fs, channel, fs->sync_target.max_ops); 426 } 427 428 static int 429 _spdk_fs_io_channel_create(void *io_device, void *ctx_buf) 430 { 431 struct spdk_filesystem *fs; 432 struct spdk_fs_channel *channel = ctx_buf; 433 434 fs = SPDK_CONTAINEROF(io_device, struct spdk_filesystem, io_target); 435 436 return _spdk_fs_channel_create(fs, channel, fs->io_target.max_ops); 437 } 438 439 static void 440 _spdk_fs_channel_destroy(void *io_device, void *ctx_buf) 441 { 442 struct spdk_fs_channel *channel = ctx_buf; 443 444 if (channel->outstanding_reqs > 0) { 445 SPDK_ERRLOG("channel freed with %" PRIu32 " outstanding requests!\n", 446 channel->outstanding_reqs); 447 } 448 449 free(channel->req_mem); 450 if (channel->bs_channel != NULL) { 451 spdk_bs_free_io_channel(channel->bs_channel); 452 } 453 } 454 455 static void 456 __send_request_direct(fs_request_fn fn, void *arg) 457 { 458 fn(arg); 459 } 460 461 static void 462 common_fs_bs_init(struct spdk_filesystem *fs, struct spdk_blob_store *bs) 463 { 464 fs->bs = bs; 465 fs->bs_opts.cluster_sz = spdk_bs_get_cluster_size(bs); 466 fs->md_target.md_fs_channel->bs_channel = spdk_bs_alloc_io_channel(fs->bs); 467 fs->md_target.md_fs_channel->send_request = __send_request_direct; 468 fs->sync_target.sync_fs_channel->bs_channel = spdk_bs_alloc_io_channel(fs->bs); 469 fs->sync_target.sync_fs_channel->send_request = __send_request_direct; 470 471 pthread_mutex_lock(&g_cache_init_lock); 472 if (g_fs_count == 0) { 473 __initialize_cache(); 474 } 475 g_fs_count++; 476 pthread_mutex_unlock(&g_cache_init_lock); 477 } 478 479 static void 480 init_cb(void *ctx, struct spdk_blob_store *bs, int bserrno) 481 { 482 struct spdk_fs_request *req = ctx; 483 struct spdk_fs_cb_args *args = &req->args; 484 struct spdk_filesystem *fs = args->fs; 485 486 if (bserrno == 0) { 487 common_fs_bs_init(fs, bs); 488 } else { 489 free(fs); 490 fs = NULL; 491 } 492 493 args->fn.fs_op_with_handle(args->arg, fs, bserrno); 494 free_fs_request(req); 495 } 496 497 static void 498 fs_conf_parse(void) 499 { 500 struct spdk_conf_section *sp; 501 502 sp = spdk_conf_find_section(NULL, "Blobfs"); 503 if (sp == NULL) { 504 g_fs_cache_buffer_shift = CACHE_BUFFER_SHIFT_DEFAULT; 505 return; 506 } 507 508 g_fs_cache_buffer_shift = spdk_conf_section_get_intval(sp, "CacheBufferShift"); 509 if (g_fs_cache_buffer_shift <= 0) { 510 g_fs_cache_buffer_shift = CACHE_BUFFER_SHIFT_DEFAULT; 511 } 512 } 513 514 static struct spdk_filesystem * 515 fs_alloc(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn) 516 { 517 struct spdk_filesystem *fs; 518 519 fs = calloc(1, sizeof(*fs)); 520 if (fs == NULL) { 521 return NULL; 522 } 523 524 fs->bdev = dev; 525 fs->send_request = send_request_fn; 526 TAILQ_INIT(&fs->files); 527 528 fs->md_target.max_ops = 512; 529 spdk_io_device_register(&fs->md_target, _spdk_fs_md_channel_create, _spdk_fs_channel_destroy, 530 sizeof(struct spdk_fs_channel), "blobfs_md"); 531 fs->md_target.md_io_channel = spdk_get_io_channel(&fs->md_target); 532 fs->md_target.md_fs_channel = spdk_io_channel_get_ctx(fs->md_target.md_io_channel); 533 534 fs->sync_target.max_ops = 512; 535 spdk_io_device_register(&fs->sync_target, _spdk_fs_sync_channel_create, _spdk_fs_channel_destroy, 536 sizeof(struct spdk_fs_channel), "blobfs_sync"); 537 fs->sync_target.sync_io_channel = spdk_get_io_channel(&fs->sync_target); 538 fs->sync_target.sync_fs_channel = spdk_io_channel_get_ctx(fs->sync_target.sync_io_channel); 539 540 fs->io_target.max_ops = 512; 541 spdk_io_device_register(&fs->io_target, _spdk_fs_io_channel_create, _spdk_fs_channel_destroy, 542 sizeof(struct spdk_fs_channel), "blobfs_io"); 543 544 return fs; 545 } 546 547 static void 548 __wake_caller(void *arg, int fserrno) 549 { 550 struct spdk_fs_cb_args *args = arg; 551 552 args->rc = fserrno; 553 sem_post(args->sem); 554 } 555 556 void 557 spdk_fs_init(struct spdk_bs_dev *dev, struct spdk_blobfs_opts *opt, 558 fs_send_request_fn send_request_fn, 559 spdk_fs_op_with_handle_complete cb_fn, void *cb_arg) 560 { 561 struct spdk_filesystem *fs; 562 struct spdk_fs_request *req; 563 struct spdk_fs_cb_args *args; 564 struct spdk_bs_opts opts = {}; 565 566 fs = fs_alloc(dev, send_request_fn); 567 if (fs == NULL) { 568 cb_fn(cb_arg, NULL, -ENOMEM); 569 return; 570 } 571 572 fs_conf_parse(); 573 574 req = alloc_fs_request(fs->md_target.md_fs_channel); 575 if (req == NULL) { 576 spdk_fs_free_io_channels(fs); 577 spdk_fs_io_device_unregister(fs); 578 cb_fn(cb_arg, NULL, -ENOMEM); 579 return; 580 } 581 582 args = &req->args; 583 args->fn.fs_op_with_handle = cb_fn; 584 args->arg = cb_arg; 585 args->fs = fs; 586 587 spdk_bs_opts_init(&opts); 588 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "BLOBFS"); 589 if (opt) { 590 opts.cluster_sz = opt->cluster_sz; 591 } 592 spdk_bs_init(dev, &opts, init_cb, req); 593 } 594 595 static struct spdk_file * 596 file_alloc(struct spdk_filesystem *fs) 597 { 598 struct spdk_file *file; 599 600 file = calloc(1, sizeof(*file)); 601 if (file == NULL) { 602 return NULL; 603 } 604 605 file->tree = calloc(1, sizeof(*file->tree)); 606 if (file->tree == NULL) { 607 free(file); 608 return NULL; 609 } 610 611 file->fs = fs; 612 TAILQ_INIT(&file->open_requests); 613 TAILQ_INIT(&file->sync_requests); 614 pthread_spin_init(&file->lock, 0); 615 TAILQ_INSERT_TAIL(&fs->files, file, tailq); 616 file->priority = SPDK_FILE_PRIORITY_LOW; 617 return file; 618 } 619 620 static void fs_load_done(void *ctx, int bserrno); 621 622 static int 623 _handle_deleted_files(struct spdk_fs_request *req) 624 { 625 struct spdk_fs_cb_args *args = &req->args; 626 struct spdk_filesystem *fs = args->fs; 627 628 if (!TAILQ_EMPTY(&args->op.fs_load.deleted_files)) { 629 struct spdk_deleted_file *deleted_file; 630 631 deleted_file = TAILQ_FIRST(&args->op.fs_load.deleted_files); 632 TAILQ_REMOVE(&args->op.fs_load.deleted_files, deleted_file, tailq); 633 spdk_bs_delete_blob(fs->bs, deleted_file->id, fs_load_done, req); 634 free(deleted_file); 635 return 0; 636 } 637 638 return 1; 639 } 640 641 static void 642 fs_load_done(void *ctx, int bserrno) 643 { 644 struct spdk_fs_request *req = ctx; 645 struct spdk_fs_cb_args *args = &req->args; 646 struct spdk_filesystem *fs = args->fs; 647 648 /* The filesystem has been loaded. Now check if there are any files that 649 * were marked for deletion before last unload. Do not complete the 650 * fs_load callback until all of them have been deleted on disk. 651 */ 652 if (_handle_deleted_files(req) == 0) { 653 /* We found a file that's been marked for deleting but not actually 654 * deleted yet. This function will get called again once the delete 655 * operation is completed. 656 */ 657 return; 658 } 659 660 args->fn.fs_op_with_handle(args->arg, fs, 0); 661 free_fs_request(req); 662 663 } 664 665 static void 666 _file_build_trace_arg_name(struct spdk_file *f) 667 { 668 f->trace_arg_name = 0; 669 memcpy(&f->trace_arg_name, f->name, 670 spdk_min(sizeof(f->trace_arg_name), strlen(f->name))); 671 } 672 673 static void 674 iter_cb(void *ctx, struct spdk_blob *blob, int rc) 675 { 676 struct spdk_fs_request *req = ctx; 677 struct spdk_fs_cb_args *args = &req->args; 678 struct spdk_filesystem *fs = args->fs; 679 uint64_t *length; 680 const char *name; 681 uint32_t *is_deleted; 682 size_t value_len; 683 684 if (rc < 0) { 685 args->fn.fs_op_with_handle(args->arg, fs, rc); 686 free_fs_request(req); 687 return; 688 } 689 690 rc = spdk_blob_get_xattr_value(blob, "name", (const void **)&name, &value_len); 691 if (rc < 0) { 692 args->fn.fs_op_with_handle(args->arg, fs, rc); 693 free_fs_request(req); 694 return; 695 } 696 697 rc = spdk_blob_get_xattr_value(blob, "length", (const void **)&length, &value_len); 698 if (rc < 0) { 699 args->fn.fs_op_with_handle(args->arg, fs, rc); 700 free_fs_request(req); 701 return; 702 } 703 704 assert(value_len == 8); 705 706 /* This file could be deleted last time without close it, then app crashed, so we delete it now */ 707 rc = spdk_blob_get_xattr_value(blob, "is_deleted", (const void **)&is_deleted, &value_len); 708 if (rc < 0) { 709 struct spdk_file *f; 710 711 f = file_alloc(fs); 712 if (f == NULL) { 713 args->fn.fs_op_with_handle(args->arg, fs, -ENOMEM); 714 free_fs_request(req); 715 return; 716 } 717 718 f->name = strdup(name); 719 _file_build_trace_arg_name(f); 720 f->blobid = spdk_blob_get_id(blob); 721 f->length = *length; 722 f->length_flushed = *length; 723 f->append_pos = *length; 724 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "added file %s length=%ju\n", f->name, f->length); 725 } else { 726 struct spdk_deleted_file *deleted_file; 727 728 deleted_file = calloc(1, sizeof(*deleted_file)); 729 if (deleted_file == NULL) { 730 args->fn.fs_op_with_handle(args->arg, fs, -ENOMEM); 731 free_fs_request(req); 732 return; 733 } 734 deleted_file->id = spdk_blob_get_id(blob); 735 TAILQ_INSERT_TAIL(&args->op.fs_load.deleted_files, deleted_file, tailq); 736 } 737 } 738 739 static void 740 load_cb(void *ctx, struct spdk_blob_store *bs, int bserrno) 741 { 742 struct spdk_fs_request *req = ctx; 743 struct spdk_fs_cb_args *args = &req->args; 744 struct spdk_filesystem *fs = args->fs; 745 struct spdk_bs_type bstype; 746 static const struct spdk_bs_type blobfs_type = {"BLOBFS"}; 747 static const struct spdk_bs_type zeros; 748 749 if (bserrno != 0) { 750 args->fn.fs_op_with_handle(args->arg, NULL, bserrno); 751 free_fs_request(req); 752 free(fs); 753 return; 754 } 755 756 bstype = spdk_bs_get_bstype(bs); 757 758 if (!memcmp(&bstype, &zeros, sizeof(bstype))) { 759 SPDK_DEBUGLOG(SPDK_LOG_BLOB, "assigning bstype\n"); 760 spdk_bs_set_bstype(bs, blobfs_type); 761 } else if (memcmp(&bstype, &blobfs_type, sizeof(bstype))) { 762 SPDK_DEBUGLOG(SPDK_LOG_BLOB, "not blobfs\n"); 763 SPDK_LOGDUMP(SPDK_LOG_BLOB, "bstype", &bstype, sizeof(bstype)); 764 args->fn.fs_op_with_handle(args->arg, NULL, bserrno); 765 free_fs_request(req); 766 free(fs); 767 return; 768 } 769 770 common_fs_bs_init(fs, bs); 771 fs_load_done(req, 0); 772 } 773 774 static void 775 spdk_fs_io_device_unregister(struct spdk_filesystem *fs) 776 { 777 assert(fs != NULL); 778 spdk_io_device_unregister(&fs->md_target, NULL); 779 spdk_io_device_unregister(&fs->sync_target, NULL); 780 spdk_io_device_unregister(&fs->io_target, NULL); 781 free(fs); 782 } 783 784 static void 785 spdk_fs_free_io_channels(struct spdk_filesystem *fs) 786 { 787 assert(fs != NULL); 788 spdk_fs_free_io_channel(fs->md_target.md_io_channel); 789 spdk_fs_free_io_channel(fs->sync_target.sync_io_channel); 790 } 791 792 void 793 spdk_fs_load(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn, 794 spdk_fs_op_with_handle_complete cb_fn, void *cb_arg) 795 { 796 struct spdk_filesystem *fs; 797 struct spdk_fs_cb_args *args; 798 struct spdk_fs_request *req; 799 struct spdk_bs_opts bs_opts; 800 801 fs = fs_alloc(dev, send_request_fn); 802 if (fs == NULL) { 803 cb_fn(cb_arg, NULL, -ENOMEM); 804 return; 805 } 806 807 fs_conf_parse(); 808 809 req = alloc_fs_request(fs->md_target.md_fs_channel); 810 if (req == NULL) { 811 spdk_fs_free_io_channels(fs); 812 spdk_fs_io_device_unregister(fs); 813 cb_fn(cb_arg, NULL, -ENOMEM); 814 return; 815 } 816 817 args = &req->args; 818 args->fn.fs_op_with_handle = cb_fn; 819 args->arg = cb_arg; 820 args->fs = fs; 821 TAILQ_INIT(&args->op.fs_load.deleted_files); 822 spdk_bs_opts_init(&bs_opts); 823 bs_opts.iter_cb_fn = iter_cb; 824 bs_opts.iter_cb_arg = req; 825 spdk_bs_load(dev, &bs_opts, load_cb, req); 826 } 827 828 static void 829 unload_cb(void *ctx, int bserrno) 830 { 831 struct spdk_fs_request *req = ctx; 832 struct spdk_fs_cb_args *args = &req->args; 833 struct spdk_filesystem *fs = args->fs; 834 struct spdk_file *file, *tmp; 835 836 TAILQ_FOREACH_SAFE(file, &fs->files, tailq, tmp) { 837 TAILQ_REMOVE(&fs->files, file, tailq); 838 cache_free_buffers(file); 839 free(file->name); 840 free(file->tree); 841 free(file); 842 } 843 844 pthread_mutex_lock(&g_cache_init_lock); 845 g_fs_count--; 846 if (g_fs_count == 0) { 847 __free_cache(); 848 } 849 pthread_mutex_unlock(&g_cache_init_lock); 850 851 args->fn.fs_op(args->arg, bserrno); 852 free(req); 853 854 spdk_fs_io_device_unregister(fs); 855 } 856 857 void 858 spdk_fs_unload(struct spdk_filesystem *fs, spdk_fs_op_complete cb_fn, void *cb_arg) 859 { 860 struct spdk_fs_request *req; 861 struct spdk_fs_cb_args *args; 862 863 /* 864 * We must free the md_channel before unloading the blobstore, so just 865 * allocate this request from the general heap. 866 */ 867 req = calloc(1, sizeof(*req)); 868 if (req == NULL) { 869 cb_fn(cb_arg, -ENOMEM); 870 return; 871 } 872 873 args = &req->args; 874 args->fn.fs_op = cb_fn; 875 args->arg = cb_arg; 876 args->fs = fs; 877 878 spdk_fs_free_io_channels(fs); 879 spdk_bs_unload(fs->bs, unload_cb, req); 880 } 881 882 static struct spdk_file * 883 fs_find_file(struct spdk_filesystem *fs, const char *name) 884 { 885 struct spdk_file *file; 886 887 TAILQ_FOREACH(file, &fs->files, tailq) { 888 if (!strncmp(name, file->name, SPDK_FILE_NAME_MAX)) { 889 return file; 890 } 891 } 892 893 return NULL; 894 } 895 896 void 897 spdk_fs_file_stat_async(struct spdk_filesystem *fs, const char *name, 898 spdk_file_stat_op_complete cb_fn, void *cb_arg) 899 { 900 struct spdk_file_stat stat; 901 struct spdk_file *f = NULL; 902 903 if (strnlen(name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 904 cb_fn(cb_arg, NULL, -ENAMETOOLONG); 905 return; 906 } 907 908 f = fs_find_file(fs, name); 909 if (f != NULL) { 910 stat.blobid = f->blobid; 911 stat.size = f->append_pos >= f->length ? f->append_pos : f->length; 912 cb_fn(cb_arg, &stat, 0); 913 return; 914 } 915 916 cb_fn(cb_arg, NULL, -ENOENT); 917 } 918 919 static void 920 __copy_stat(void *arg, struct spdk_file_stat *stat, int fserrno) 921 { 922 struct spdk_fs_request *req = arg; 923 struct spdk_fs_cb_args *args = &req->args; 924 925 args->rc = fserrno; 926 if (fserrno == 0) { 927 memcpy(args->arg, stat, sizeof(*stat)); 928 } 929 sem_post(args->sem); 930 } 931 932 static void 933 __file_stat(void *arg) 934 { 935 struct spdk_fs_request *req = arg; 936 struct spdk_fs_cb_args *args = &req->args; 937 938 spdk_fs_file_stat_async(args->fs, args->op.stat.name, 939 args->fn.stat_op, req); 940 } 941 942 int 943 spdk_fs_file_stat(struct spdk_filesystem *fs, struct spdk_fs_thread_ctx *ctx, 944 const char *name, struct spdk_file_stat *stat) 945 { 946 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 947 struct spdk_fs_request *req; 948 int rc; 949 950 req = alloc_fs_request(channel); 951 if (req == NULL) { 952 return -ENOMEM; 953 } 954 955 req->args.fs = fs; 956 req->args.op.stat.name = name; 957 req->args.fn.stat_op = __copy_stat; 958 req->args.arg = stat; 959 req->args.sem = &channel->sem; 960 channel->send_request(__file_stat, req); 961 sem_wait(&channel->sem); 962 963 rc = req->args.rc; 964 free_fs_request(req); 965 966 return rc; 967 } 968 969 static void 970 fs_create_blob_close_cb(void *ctx, int bserrno) 971 { 972 int rc; 973 struct spdk_fs_request *req = ctx; 974 struct spdk_fs_cb_args *args = &req->args; 975 976 rc = args->rc ? args->rc : bserrno; 977 args->fn.file_op(args->arg, rc); 978 free_fs_request(req); 979 } 980 981 static void 982 fs_create_blob_resize_cb(void *ctx, int bserrno) 983 { 984 struct spdk_fs_request *req = ctx; 985 struct spdk_fs_cb_args *args = &req->args; 986 struct spdk_file *f = args->file; 987 struct spdk_blob *blob = args->op.create.blob; 988 uint64_t length = 0; 989 990 args->rc = bserrno; 991 if (bserrno) { 992 spdk_blob_close(blob, fs_create_blob_close_cb, args); 993 return; 994 } 995 996 spdk_blob_set_xattr(blob, "name", f->name, strlen(f->name) + 1); 997 spdk_blob_set_xattr(blob, "length", &length, sizeof(length)); 998 999 spdk_blob_close(blob, fs_create_blob_close_cb, args); 1000 } 1001 1002 static void 1003 fs_create_blob_open_cb(void *ctx, struct spdk_blob *blob, int bserrno) 1004 { 1005 struct spdk_fs_request *req = ctx; 1006 struct spdk_fs_cb_args *args = &req->args; 1007 1008 if (bserrno) { 1009 args->fn.file_op(args->arg, bserrno); 1010 free_fs_request(req); 1011 return; 1012 } 1013 1014 args->op.create.blob = blob; 1015 spdk_blob_resize(blob, 1, fs_create_blob_resize_cb, req); 1016 } 1017 1018 static void 1019 fs_create_blob_create_cb(void *ctx, spdk_blob_id blobid, int bserrno) 1020 { 1021 struct spdk_fs_request *req = ctx; 1022 struct spdk_fs_cb_args *args = &req->args; 1023 struct spdk_file *f = args->file; 1024 1025 if (bserrno) { 1026 args->fn.file_op(args->arg, bserrno); 1027 free_fs_request(req); 1028 return; 1029 } 1030 1031 f->blobid = blobid; 1032 spdk_bs_open_blob(f->fs->bs, blobid, fs_create_blob_open_cb, req); 1033 } 1034 1035 void 1036 spdk_fs_create_file_async(struct spdk_filesystem *fs, const char *name, 1037 spdk_file_op_complete cb_fn, void *cb_arg) 1038 { 1039 struct spdk_file *file; 1040 struct spdk_fs_request *req; 1041 struct spdk_fs_cb_args *args; 1042 1043 if (strnlen(name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 1044 cb_fn(cb_arg, -ENAMETOOLONG); 1045 return; 1046 } 1047 1048 file = fs_find_file(fs, name); 1049 if (file != NULL) { 1050 cb_fn(cb_arg, -EEXIST); 1051 return; 1052 } 1053 1054 file = file_alloc(fs); 1055 if (file == NULL) { 1056 cb_fn(cb_arg, -ENOMEM); 1057 return; 1058 } 1059 1060 req = alloc_fs_request(fs->md_target.md_fs_channel); 1061 if (req == NULL) { 1062 cb_fn(cb_arg, -ENOMEM); 1063 return; 1064 } 1065 1066 args = &req->args; 1067 args->file = file; 1068 args->fn.file_op = cb_fn; 1069 args->arg = cb_arg; 1070 1071 file->name = strdup(name); 1072 _file_build_trace_arg_name(file); 1073 spdk_bs_create_blob(fs->bs, fs_create_blob_create_cb, args); 1074 } 1075 1076 static void 1077 __fs_create_file_done(void *arg, int fserrno) 1078 { 1079 struct spdk_fs_request *req = arg; 1080 struct spdk_fs_cb_args *args = &req->args; 1081 1082 args->rc = fserrno; 1083 sem_post(args->sem); 1084 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s\n", args->op.create.name); 1085 } 1086 1087 static void 1088 __fs_create_file(void *arg) 1089 { 1090 struct spdk_fs_request *req = arg; 1091 struct spdk_fs_cb_args *args = &req->args; 1092 1093 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s\n", args->op.create.name); 1094 spdk_fs_create_file_async(args->fs, args->op.create.name, __fs_create_file_done, req); 1095 } 1096 1097 int 1098 spdk_fs_create_file(struct spdk_filesystem *fs, struct spdk_fs_thread_ctx *ctx, const char *name) 1099 { 1100 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 1101 struct spdk_fs_request *req; 1102 struct spdk_fs_cb_args *args; 1103 int rc; 1104 1105 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s\n", name); 1106 1107 req = alloc_fs_request(channel); 1108 if (req == NULL) { 1109 return -ENOMEM; 1110 } 1111 1112 args = &req->args; 1113 args->fs = fs; 1114 args->op.create.name = name; 1115 args->sem = &channel->sem; 1116 fs->send_request(__fs_create_file, req); 1117 sem_wait(&channel->sem); 1118 rc = args->rc; 1119 free_fs_request(req); 1120 1121 return rc; 1122 } 1123 1124 static void 1125 fs_open_blob_done(void *ctx, struct spdk_blob *blob, int bserrno) 1126 { 1127 struct spdk_fs_request *req = ctx; 1128 struct spdk_fs_cb_args *args = &req->args; 1129 struct spdk_file *f = args->file; 1130 1131 f->blob = blob; 1132 while (!TAILQ_EMPTY(&f->open_requests)) { 1133 req = TAILQ_FIRST(&f->open_requests); 1134 args = &req->args; 1135 TAILQ_REMOVE(&f->open_requests, req, args.op.open.tailq); 1136 spdk_trace_record(TRACE_BLOBFS_OPEN, 0, 0, 0, f->trace_arg_name); 1137 args->fn.file_op_with_handle(args->arg, f, bserrno); 1138 free_fs_request(req); 1139 } 1140 } 1141 1142 static void 1143 fs_open_blob_create_cb(void *ctx, int bserrno) 1144 { 1145 struct spdk_fs_request *req = ctx; 1146 struct spdk_fs_cb_args *args = &req->args; 1147 struct spdk_file *file = args->file; 1148 struct spdk_filesystem *fs = args->fs; 1149 1150 if (file == NULL) { 1151 /* 1152 * This is from an open with CREATE flag - the file 1153 * is now created so look it up in the file list for this 1154 * filesystem. 1155 */ 1156 file = fs_find_file(fs, args->op.open.name); 1157 assert(file != NULL); 1158 args->file = file; 1159 } 1160 1161 file->ref_count++; 1162 TAILQ_INSERT_TAIL(&file->open_requests, req, args.op.open.tailq); 1163 if (file->ref_count == 1) { 1164 assert(file->blob == NULL); 1165 spdk_bs_open_blob(fs->bs, file->blobid, fs_open_blob_done, req); 1166 } else if (file->blob != NULL) { 1167 fs_open_blob_done(req, file->blob, 0); 1168 } else { 1169 /* 1170 * The blob open for this file is in progress due to a previous 1171 * open request. When that open completes, it will invoke the 1172 * open callback for this request. 1173 */ 1174 } 1175 } 1176 1177 void 1178 spdk_fs_open_file_async(struct spdk_filesystem *fs, const char *name, uint32_t flags, 1179 spdk_file_op_with_handle_complete cb_fn, void *cb_arg) 1180 { 1181 struct spdk_file *f = NULL; 1182 struct spdk_fs_request *req; 1183 struct spdk_fs_cb_args *args; 1184 1185 if (strnlen(name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 1186 cb_fn(cb_arg, NULL, -ENAMETOOLONG); 1187 return; 1188 } 1189 1190 f = fs_find_file(fs, name); 1191 if (f == NULL && !(flags & SPDK_BLOBFS_OPEN_CREATE)) { 1192 cb_fn(cb_arg, NULL, -ENOENT); 1193 return; 1194 } 1195 1196 if (f != NULL && f->is_deleted == true) { 1197 cb_fn(cb_arg, NULL, -ENOENT); 1198 return; 1199 } 1200 1201 req = alloc_fs_request(fs->md_target.md_fs_channel); 1202 if (req == NULL) { 1203 cb_fn(cb_arg, NULL, -ENOMEM); 1204 return; 1205 } 1206 1207 args = &req->args; 1208 args->fn.file_op_with_handle = cb_fn; 1209 args->arg = cb_arg; 1210 args->file = f; 1211 args->fs = fs; 1212 args->op.open.name = name; 1213 1214 if (f == NULL) { 1215 spdk_fs_create_file_async(fs, name, fs_open_blob_create_cb, req); 1216 } else { 1217 fs_open_blob_create_cb(req, 0); 1218 } 1219 } 1220 1221 static void 1222 __fs_open_file_done(void *arg, struct spdk_file *file, int bserrno) 1223 { 1224 struct spdk_fs_request *req = arg; 1225 struct spdk_fs_cb_args *args = &req->args; 1226 1227 args->file = file; 1228 __wake_caller(args, bserrno); 1229 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s\n", args->op.open.name); 1230 } 1231 1232 static void 1233 __fs_open_file(void *arg) 1234 { 1235 struct spdk_fs_request *req = arg; 1236 struct spdk_fs_cb_args *args = &req->args; 1237 1238 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s\n", args->op.open.name); 1239 spdk_fs_open_file_async(args->fs, args->op.open.name, args->op.open.flags, 1240 __fs_open_file_done, req); 1241 } 1242 1243 int 1244 spdk_fs_open_file(struct spdk_filesystem *fs, struct spdk_fs_thread_ctx *ctx, 1245 const char *name, uint32_t flags, struct spdk_file **file) 1246 { 1247 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 1248 struct spdk_fs_request *req; 1249 struct spdk_fs_cb_args *args; 1250 int rc; 1251 1252 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s\n", name); 1253 1254 req = alloc_fs_request(channel); 1255 if (req == NULL) { 1256 return -ENOMEM; 1257 } 1258 1259 args = &req->args; 1260 args->fs = fs; 1261 args->op.open.name = name; 1262 args->op.open.flags = flags; 1263 args->sem = &channel->sem; 1264 fs->send_request(__fs_open_file, req); 1265 sem_wait(&channel->sem); 1266 rc = args->rc; 1267 if (rc == 0) { 1268 *file = args->file; 1269 } else { 1270 *file = NULL; 1271 } 1272 free_fs_request(req); 1273 1274 return rc; 1275 } 1276 1277 static void 1278 fs_rename_blob_close_cb(void *ctx, int bserrno) 1279 { 1280 struct spdk_fs_request *req = ctx; 1281 struct spdk_fs_cb_args *args = &req->args; 1282 1283 args->fn.fs_op(args->arg, bserrno); 1284 free_fs_request(req); 1285 } 1286 1287 static void 1288 fs_rename_blob_open_cb(void *ctx, struct spdk_blob *blob, int bserrno) 1289 { 1290 struct spdk_fs_request *req = ctx; 1291 struct spdk_fs_cb_args *args = &req->args; 1292 const char *new_name = args->op.rename.new_name; 1293 1294 spdk_blob_set_xattr(blob, "name", new_name, strlen(new_name) + 1); 1295 spdk_blob_close(blob, fs_rename_blob_close_cb, req); 1296 } 1297 1298 static void 1299 __spdk_fs_md_rename_file(struct spdk_fs_request *req) 1300 { 1301 struct spdk_fs_cb_args *args = &req->args; 1302 struct spdk_file *f; 1303 1304 f = fs_find_file(args->fs, args->op.rename.old_name); 1305 if (f == NULL) { 1306 args->fn.fs_op(args->arg, -ENOENT); 1307 free_fs_request(req); 1308 return; 1309 } 1310 1311 free(f->name); 1312 f->name = strdup(args->op.rename.new_name); 1313 _file_build_trace_arg_name(f); 1314 args->file = f; 1315 spdk_bs_open_blob(args->fs->bs, f->blobid, fs_rename_blob_open_cb, req); 1316 } 1317 1318 static void 1319 fs_rename_delete_done(void *arg, int fserrno) 1320 { 1321 __spdk_fs_md_rename_file(arg); 1322 } 1323 1324 void 1325 spdk_fs_rename_file_async(struct spdk_filesystem *fs, 1326 const char *old_name, const char *new_name, 1327 spdk_file_op_complete cb_fn, void *cb_arg) 1328 { 1329 struct spdk_file *f; 1330 struct spdk_fs_request *req; 1331 struct spdk_fs_cb_args *args; 1332 1333 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "old=%s new=%s\n", old_name, new_name); 1334 if (strnlen(new_name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 1335 cb_fn(cb_arg, -ENAMETOOLONG); 1336 return; 1337 } 1338 1339 req = alloc_fs_request(fs->md_target.md_fs_channel); 1340 if (req == NULL) { 1341 cb_fn(cb_arg, -ENOMEM); 1342 return; 1343 } 1344 1345 args = &req->args; 1346 args->fn.fs_op = cb_fn; 1347 args->fs = fs; 1348 args->arg = cb_arg; 1349 args->op.rename.old_name = old_name; 1350 args->op.rename.new_name = new_name; 1351 1352 f = fs_find_file(fs, new_name); 1353 if (f == NULL) { 1354 __spdk_fs_md_rename_file(req); 1355 return; 1356 } 1357 1358 /* 1359 * The rename overwrites an existing file. So delete the existing file, then 1360 * do the actual rename. 1361 */ 1362 spdk_fs_delete_file_async(fs, new_name, fs_rename_delete_done, req); 1363 } 1364 1365 static void 1366 __fs_rename_file_done(void *arg, int fserrno) 1367 { 1368 struct spdk_fs_request *req = arg; 1369 struct spdk_fs_cb_args *args = &req->args; 1370 1371 __wake_caller(args, fserrno); 1372 } 1373 1374 static void 1375 __fs_rename_file(void *arg) 1376 { 1377 struct spdk_fs_request *req = arg; 1378 struct spdk_fs_cb_args *args = &req->args; 1379 1380 spdk_fs_rename_file_async(args->fs, args->op.rename.old_name, args->op.rename.new_name, 1381 __fs_rename_file_done, req); 1382 } 1383 1384 int 1385 spdk_fs_rename_file(struct spdk_filesystem *fs, struct spdk_fs_thread_ctx *ctx, 1386 const char *old_name, const char *new_name) 1387 { 1388 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 1389 struct spdk_fs_request *req; 1390 struct spdk_fs_cb_args *args; 1391 int rc; 1392 1393 req = alloc_fs_request(channel); 1394 if (req == NULL) { 1395 return -ENOMEM; 1396 } 1397 1398 args = &req->args; 1399 1400 args->fs = fs; 1401 args->op.rename.old_name = old_name; 1402 args->op.rename.new_name = new_name; 1403 args->sem = &channel->sem; 1404 fs->send_request(__fs_rename_file, req); 1405 sem_wait(&channel->sem); 1406 rc = args->rc; 1407 free_fs_request(req); 1408 return rc; 1409 } 1410 1411 static void 1412 blob_delete_cb(void *ctx, int bserrno) 1413 { 1414 struct spdk_fs_request *req = ctx; 1415 struct spdk_fs_cb_args *args = &req->args; 1416 1417 args->fn.file_op(args->arg, bserrno); 1418 free_fs_request(req); 1419 } 1420 1421 void 1422 spdk_fs_delete_file_async(struct spdk_filesystem *fs, const char *name, 1423 spdk_file_op_complete cb_fn, void *cb_arg) 1424 { 1425 struct spdk_file *f; 1426 spdk_blob_id blobid; 1427 struct spdk_fs_request *req; 1428 struct spdk_fs_cb_args *args; 1429 1430 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s\n", name); 1431 1432 if (strnlen(name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 1433 cb_fn(cb_arg, -ENAMETOOLONG); 1434 return; 1435 } 1436 1437 f = fs_find_file(fs, name); 1438 if (f == NULL) { 1439 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "Cannot find the file=%s to deleted\n", name); 1440 cb_fn(cb_arg, -ENOENT); 1441 return; 1442 } 1443 1444 req = alloc_fs_request(fs->md_target.md_fs_channel); 1445 if (req == NULL) { 1446 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "Cannot allocate the req for the file=%s to deleted\n", name); 1447 cb_fn(cb_arg, -ENOMEM); 1448 return; 1449 } 1450 1451 args = &req->args; 1452 args->fn.file_op = cb_fn; 1453 args->arg = cb_arg; 1454 1455 if (f->ref_count > 0) { 1456 /* If the ref > 0, we mark the file as deleted and delete it when we close it. */ 1457 f->is_deleted = true; 1458 spdk_blob_set_xattr(f->blob, "is_deleted", &f->is_deleted, sizeof(bool)); 1459 spdk_blob_sync_md(f->blob, blob_delete_cb, req); 1460 return; 1461 } 1462 1463 TAILQ_REMOVE(&fs->files, f, tailq); 1464 1465 cache_free_buffers(f); 1466 1467 blobid = f->blobid; 1468 1469 free(f->name); 1470 free(f->tree); 1471 free(f); 1472 1473 spdk_bs_delete_blob(fs->bs, blobid, blob_delete_cb, req); 1474 } 1475 1476 static uint64_t 1477 fs_name_to_uint64(const char *name) 1478 { 1479 uint64_t result = 0; 1480 memcpy(&result, name, spdk_min(sizeof(result), strlen(name))); 1481 return result; 1482 } 1483 1484 static void 1485 __fs_delete_file_done(void *arg, int fserrno) 1486 { 1487 struct spdk_fs_request *req = arg; 1488 struct spdk_fs_cb_args *args = &req->args; 1489 1490 spdk_trace_record(TRACE_BLOBFS_DELETE_DONE, 0, 0, 0, fs_name_to_uint64(args->op.delete.name)); 1491 __wake_caller(args, fserrno); 1492 } 1493 1494 static void 1495 __fs_delete_file(void *arg) 1496 { 1497 struct spdk_fs_request *req = arg; 1498 struct spdk_fs_cb_args *args = &req->args; 1499 1500 spdk_trace_record(TRACE_BLOBFS_DELETE_START, 0, 0, 0, fs_name_to_uint64(args->op.delete.name)); 1501 spdk_fs_delete_file_async(args->fs, args->op.delete.name, __fs_delete_file_done, req); 1502 } 1503 1504 int 1505 spdk_fs_delete_file(struct spdk_filesystem *fs, struct spdk_fs_thread_ctx *ctx, 1506 const char *name) 1507 { 1508 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 1509 struct spdk_fs_request *req; 1510 struct spdk_fs_cb_args *args; 1511 int rc; 1512 1513 req = alloc_fs_request(channel); 1514 if (req == NULL) { 1515 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "Cannot allocate req to delete file=%s\n", name); 1516 return -ENOMEM; 1517 } 1518 1519 args = &req->args; 1520 args->fs = fs; 1521 args->op.delete.name = name; 1522 args->sem = &channel->sem; 1523 fs->send_request(__fs_delete_file, req); 1524 sem_wait(&channel->sem); 1525 rc = args->rc; 1526 free_fs_request(req); 1527 1528 return rc; 1529 } 1530 1531 spdk_fs_iter 1532 spdk_fs_iter_first(struct spdk_filesystem *fs) 1533 { 1534 struct spdk_file *f; 1535 1536 f = TAILQ_FIRST(&fs->files); 1537 return f; 1538 } 1539 1540 spdk_fs_iter 1541 spdk_fs_iter_next(spdk_fs_iter iter) 1542 { 1543 struct spdk_file *f = iter; 1544 1545 if (f == NULL) { 1546 return NULL; 1547 } 1548 1549 f = TAILQ_NEXT(f, tailq); 1550 return f; 1551 } 1552 1553 const char * 1554 spdk_file_get_name(struct spdk_file *file) 1555 { 1556 return file->name; 1557 } 1558 1559 uint64_t 1560 spdk_file_get_length(struct spdk_file *file) 1561 { 1562 uint64_t length; 1563 1564 assert(file != NULL); 1565 1566 length = file->append_pos >= file->length ? file->append_pos : file->length; 1567 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s length=0x%jx\n", file->name, length); 1568 return length; 1569 } 1570 1571 static void 1572 fs_truncate_complete_cb(void *ctx, int bserrno) 1573 { 1574 struct spdk_fs_request *req = ctx; 1575 struct spdk_fs_cb_args *args = &req->args; 1576 1577 args->fn.file_op(args->arg, bserrno); 1578 free_fs_request(req); 1579 } 1580 1581 static void 1582 fs_truncate_resize_cb(void *ctx, int bserrno) 1583 { 1584 struct spdk_fs_request *req = ctx; 1585 struct spdk_fs_cb_args *args = &req->args; 1586 struct spdk_file *file = args->file; 1587 uint64_t *length = &args->op.truncate.length; 1588 1589 if (bserrno) { 1590 args->fn.file_op(args->arg, bserrno); 1591 free_fs_request(req); 1592 return; 1593 } 1594 1595 spdk_blob_set_xattr(file->blob, "length", length, sizeof(*length)); 1596 1597 file->length = *length; 1598 if (file->append_pos > file->length) { 1599 file->append_pos = file->length; 1600 } 1601 1602 spdk_blob_sync_md(file->blob, fs_truncate_complete_cb, req); 1603 } 1604 1605 static uint64_t 1606 __bytes_to_clusters(uint64_t length, uint64_t cluster_sz) 1607 { 1608 return (length + cluster_sz - 1) / cluster_sz; 1609 } 1610 1611 void 1612 spdk_file_truncate_async(struct spdk_file *file, uint64_t length, 1613 spdk_file_op_complete cb_fn, void *cb_arg) 1614 { 1615 struct spdk_filesystem *fs; 1616 size_t num_clusters; 1617 struct spdk_fs_request *req; 1618 struct spdk_fs_cb_args *args; 1619 1620 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s old=0x%jx new=0x%jx\n", file->name, file->length, length); 1621 if (length == file->length) { 1622 cb_fn(cb_arg, 0); 1623 return; 1624 } 1625 1626 req = alloc_fs_request(file->fs->md_target.md_fs_channel); 1627 if (req == NULL) { 1628 cb_fn(cb_arg, -ENOMEM); 1629 return; 1630 } 1631 1632 args = &req->args; 1633 args->fn.file_op = cb_fn; 1634 args->arg = cb_arg; 1635 args->file = file; 1636 args->op.truncate.length = length; 1637 fs = file->fs; 1638 1639 num_clusters = __bytes_to_clusters(length, fs->bs_opts.cluster_sz); 1640 1641 spdk_blob_resize(file->blob, num_clusters, fs_truncate_resize_cb, req); 1642 } 1643 1644 static void 1645 __truncate(void *arg) 1646 { 1647 struct spdk_fs_request *req = arg; 1648 struct spdk_fs_cb_args *args = &req->args; 1649 1650 spdk_file_truncate_async(args->file, args->op.truncate.length, 1651 args->fn.file_op, args); 1652 } 1653 1654 int 1655 spdk_file_truncate(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx, 1656 uint64_t length) 1657 { 1658 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 1659 struct spdk_fs_request *req; 1660 struct spdk_fs_cb_args *args; 1661 int rc; 1662 1663 req = alloc_fs_request(channel); 1664 if (req == NULL) { 1665 return -ENOMEM; 1666 } 1667 1668 args = &req->args; 1669 1670 args->file = file; 1671 args->op.truncate.length = length; 1672 args->fn.file_op = __wake_caller; 1673 args->sem = &channel->sem; 1674 1675 channel->send_request(__truncate, req); 1676 sem_wait(&channel->sem); 1677 rc = args->rc; 1678 free_fs_request(req); 1679 1680 return rc; 1681 } 1682 1683 static void 1684 __rw_done(void *ctx, int bserrno) 1685 { 1686 struct spdk_fs_request *req = ctx; 1687 struct spdk_fs_cb_args *args = &req->args; 1688 1689 spdk_free(args->op.rw.pin_buf); 1690 args->fn.file_op(args->arg, bserrno); 1691 free_fs_request(req); 1692 } 1693 1694 static void 1695 __read_done(void *ctx, int bserrno) 1696 { 1697 struct spdk_fs_request *req = ctx; 1698 struct spdk_fs_cb_args *args = &req->args; 1699 1700 assert(req != NULL); 1701 if (args->op.rw.is_read) { 1702 memcpy(args->iovs[0].iov_base, 1703 args->op.rw.pin_buf + (args->op.rw.offset & (args->op.rw.blocklen - 1)), 1704 args->iovs[0].iov_len); 1705 __rw_done(req, 0); 1706 } else { 1707 memcpy(args->op.rw.pin_buf + (args->op.rw.offset & (args->op.rw.blocklen - 1)), 1708 args->iovs[0].iov_base, 1709 args->iovs[0].iov_len); 1710 spdk_blob_io_write(args->file->blob, args->op.rw.channel, 1711 args->op.rw.pin_buf, 1712 args->op.rw.start_lba, args->op.rw.num_lba, 1713 __rw_done, req); 1714 } 1715 } 1716 1717 static void 1718 __do_blob_read(void *ctx, int fserrno) 1719 { 1720 struct spdk_fs_request *req = ctx; 1721 struct spdk_fs_cb_args *args = &req->args; 1722 1723 if (fserrno) { 1724 __rw_done(req, fserrno); 1725 return; 1726 } 1727 spdk_blob_io_read(args->file->blob, args->op.rw.channel, 1728 args->op.rw.pin_buf, 1729 args->op.rw.start_lba, args->op.rw.num_lba, 1730 __read_done, req); 1731 } 1732 1733 static void 1734 __get_page_parameters(struct spdk_file *file, uint64_t offset, uint64_t length, 1735 uint64_t *start_lba, uint32_t *lba_size, uint64_t *num_lba) 1736 { 1737 uint64_t end_lba; 1738 1739 *lba_size = spdk_bs_get_io_unit_size(file->fs->bs); 1740 *start_lba = offset / *lba_size; 1741 end_lba = (offset + length - 1) / *lba_size; 1742 *num_lba = (end_lba - *start_lba + 1); 1743 } 1744 1745 static void 1746 __readwrite(struct spdk_file *file, struct spdk_io_channel *_channel, 1747 void *payload, uint64_t offset, uint64_t length, 1748 spdk_file_op_complete cb_fn, void *cb_arg, int is_read) 1749 { 1750 struct spdk_fs_request *req; 1751 struct spdk_fs_cb_args *args; 1752 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 1753 uint64_t start_lba, num_lba, pin_buf_length; 1754 uint32_t lba_size; 1755 1756 if (is_read && offset + length > file->length) { 1757 cb_fn(cb_arg, -EINVAL); 1758 return; 1759 } 1760 1761 req = alloc_fs_request_with_iov(channel, 1); 1762 if (req == NULL) { 1763 cb_fn(cb_arg, -ENOMEM); 1764 return; 1765 } 1766 1767 __get_page_parameters(file, offset, length, &start_lba, &lba_size, &num_lba); 1768 1769 args = &req->args; 1770 args->fn.file_op = cb_fn; 1771 args->arg = cb_arg; 1772 args->file = file; 1773 args->op.rw.channel = channel->bs_channel; 1774 args->iovs[0].iov_base = payload; 1775 args->iovs[0].iov_len = (size_t)length; 1776 args->op.rw.is_read = is_read; 1777 args->op.rw.offset = offset; 1778 args->op.rw.blocklen = lba_size; 1779 1780 pin_buf_length = num_lba * lba_size; 1781 args->op.rw.pin_buf = spdk_malloc(pin_buf_length, lba_size, NULL, 1782 SPDK_ENV_SOCKET_ID_ANY, SPDK_MALLOC_DMA); 1783 if (args->op.rw.pin_buf == NULL) { 1784 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "Failed to allocate buf for: file=%s offset=%jx length=%jx\n", 1785 file->name, offset, length); 1786 free_fs_request(req); 1787 cb_fn(cb_arg, -ENOMEM); 1788 return; 1789 } 1790 1791 args->op.rw.start_lba = start_lba; 1792 args->op.rw.num_lba = num_lba; 1793 1794 if (!is_read && file->length < offset + length) { 1795 spdk_file_truncate_async(file, offset + length, __do_blob_read, req); 1796 } else { 1797 __do_blob_read(req, 0); 1798 } 1799 } 1800 1801 void 1802 spdk_file_write_async(struct spdk_file *file, struct spdk_io_channel *channel, 1803 void *payload, uint64_t offset, uint64_t length, 1804 spdk_file_op_complete cb_fn, void *cb_arg) 1805 { 1806 __readwrite(file, channel, payload, offset, length, cb_fn, cb_arg, 0); 1807 } 1808 1809 void 1810 spdk_file_read_async(struct spdk_file *file, struct spdk_io_channel *channel, 1811 void *payload, uint64_t offset, uint64_t length, 1812 spdk_file_op_complete cb_fn, void *cb_arg) 1813 { 1814 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "file=%s offset=%jx length=%jx\n", 1815 file->name, offset, length); 1816 __readwrite(file, channel, payload, offset, length, cb_fn, cb_arg, 1); 1817 } 1818 1819 struct spdk_io_channel * 1820 spdk_fs_alloc_io_channel(struct spdk_filesystem *fs) 1821 { 1822 struct spdk_io_channel *io_channel; 1823 struct spdk_fs_channel *fs_channel; 1824 1825 io_channel = spdk_get_io_channel(&fs->io_target); 1826 fs_channel = spdk_io_channel_get_ctx(io_channel); 1827 fs_channel->bs_channel = spdk_bs_alloc_io_channel(fs->bs); 1828 fs_channel->send_request = __send_request_direct; 1829 1830 return io_channel; 1831 } 1832 1833 void 1834 spdk_fs_free_io_channel(struct spdk_io_channel *channel) 1835 { 1836 spdk_put_io_channel(channel); 1837 } 1838 1839 struct spdk_fs_thread_ctx * 1840 spdk_fs_alloc_thread_ctx(struct spdk_filesystem *fs) 1841 { 1842 struct spdk_fs_thread_ctx *ctx; 1843 1844 ctx = calloc(1, sizeof(*ctx)); 1845 if (!ctx) { 1846 return NULL; 1847 } 1848 1849 _spdk_fs_channel_create(fs, &ctx->ch, 512); 1850 1851 ctx->ch.send_request = fs->send_request; 1852 ctx->ch.sync = 1; 1853 pthread_spin_init(&ctx->ch.lock, 0); 1854 1855 return ctx; 1856 } 1857 1858 1859 void 1860 spdk_fs_free_thread_ctx(struct spdk_fs_thread_ctx *ctx) 1861 { 1862 assert(ctx->ch.sync == 1); 1863 1864 while (true) { 1865 pthread_spin_lock(&ctx->ch.lock); 1866 if (ctx->ch.outstanding_reqs == 0) { 1867 pthread_spin_unlock(&ctx->ch.lock); 1868 break; 1869 } 1870 pthread_spin_unlock(&ctx->ch.lock); 1871 usleep(1000); 1872 } 1873 1874 _spdk_fs_channel_destroy(NULL, &ctx->ch); 1875 free(ctx); 1876 } 1877 1878 void 1879 spdk_fs_set_cache_size(uint64_t size_in_mb) 1880 { 1881 g_fs_cache_size = size_in_mb * 1024 * 1024; 1882 } 1883 1884 uint64_t 1885 spdk_fs_get_cache_size(void) 1886 { 1887 return g_fs_cache_size / (1024 * 1024); 1888 } 1889 1890 static void __file_flush(void *ctx); 1891 1892 static void * 1893 alloc_cache_memory_buffer(struct spdk_file *context) 1894 { 1895 struct spdk_file *file; 1896 void *buf; 1897 1898 buf = spdk_mempool_get(g_cache_pool); 1899 if (buf != NULL) { 1900 return buf; 1901 } 1902 1903 pthread_spin_lock(&g_caches_lock); 1904 TAILQ_FOREACH(file, &g_caches, cache_tailq) { 1905 if (!file->open_for_writing && 1906 file->priority == SPDK_FILE_PRIORITY_LOW && 1907 file != context) { 1908 break; 1909 } 1910 } 1911 pthread_spin_unlock(&g_caches_lock); 1912 if (file != NULL) { 1913 cache_free_buffers(file); 1914 buf = spdk_mempool_get(g_cache_pool); 1915 if (buf != NULL) { 1916 return buf; 1917 } 1918 } 1919 1920 pthread_spin_lock(&g_caches_lock); 1921 TAILQ_FOREACH(file, &g_caches, cache_tailq) { 1922 if (!file->open_for_writing && file != context) { 1923 break; 1924 } 1925 } 1926 pthread_spin_unlock(&g_caches_lock); 1927 if (file != NULL) { 1928 cache_free_buffers(file); 1929 buf = spdk_mempool_get(g_cache_pool); 1930 if (buf != NULL) { 1931 return buf; 1932 } 1933 } 1934 1935 pthread_spin_lock(&g_caches_lock); 1936 TAILQ_FOREACH(file, &g_caches, cache_tailq) { 1937 if (file != context) { 1938 break; 1939 } 1940 } 1941 pthread_spin_unlock(&g_caches_lock); 1942 if (file != NULL) { 1943 cache_free_buffers(file); 1944 buf = spdk_mempool_get(g_cache_pool); 1945 if (buf != NULL) { 1946 return buf; 1947 } 1948 } 1949 1950 return NULL; 1951 } 1952 1953 static struct cache_buffer * 1954 cache_insert_buffer(struct spdk_file *file, uint64_t offset) 1955 { 1956 struct cache_buffer *buf; 1957 int count = 0; 1958 1959 buf = calloc(1, sizeof(*buf)); 1960 if (buf == NULL) { 1961 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "calloc failed\n"); 1962 return NULL; 1963 } 1964 1965 buf->buf = alloc_cache_memory_buffer(file); 1966 while (buf->buf == NULL) { 1967 /* 1968 * TODO: alloc_cache_memory_buffer() should eventually free 1969 * some buffers. Need a more sophisticated check here, instead 1970 * of just bailing if 100 tries does not result in getting a 1971 * free buffer. This will involve using the sync channel's 1972 * semaphore to block until a buffer becomes available. 1973 */ 1974 if (count++ == 100) { 1975 SPDK_ERRLOG("Could not allocate cache buffer for file=%p on offset=%jx\n", 1976 file, offset); 1977 free(buf); 1978 return NULL; 1979 } 1980 buf->buf = alloc_cache_memory_buffer(file); 1981 } 1982 1983 buf->buf_size = CACHE_BUFFER_SIZE; 1984 buf->offset = offset; 1985 1986 pthread_spin_lock(&g_caches_lock); 1987 if (file->tree->present_mask == 0) { 1988 TAILQ_INSERT_TAIL(&g_caches, file, cache_tailq); 1989 } 1990 file->tree = spdk_tree_insert_buffer(file->tree, buf); 1991 pthread_spin_unlock(&g_caches_lock); 1992 1993 return buf; 1994 } 1995 1996 static struct cache_buffer * 1997 cache_append_buffer(struct spdk_file *file) 1998 { 1999 struct cache_buffer *last; 2000 2001 assert(file->last == NULL || file->last->bytes_filled == file->last->buf_size); 2002 assert((file->append_pos % CACHE_BUFFER_SIZE) == 0); 2003 2004 last = cache_insert_buffer(file, file->append_pos); 2005 if (last == NULL) { 2006 SPDK_DEBUGLOG(SPDK_LOG_BLOBFS, "cache_insert_buffer failed\n"); 2007 return NULL; 2008 } 2009 2010 file->last = last; 2011 2012 return last; 2013 } 2014 2015 static void __check_sync_reqs(struct spdk_file *file); 2016 2017 static void 2018 __file_cache_finish_sync(void *ctx, int bserrno) 2019 { 2020 struct spdk_file *file; 2021 struct spdk_fs_request *sync_req = ctx; 2022 struct spdk_fs_cb_args *sync_args; 2023 2024 sync_args = &sync_req->args; 2025 file = sync_args->file; 2026 pthread_spin_lock(&file->lock); 2027 assert(sync_args->op.sync.offset <= file->length_flushed); 2028 spdk_trace_record(TRACE_BLOBFS_XATTR_END, 0, sync_args->op.sync.offset, 2029 0, file->trace_arg_name); 2030 BLOBFS_TRACE(file, "sync done offset=%jx\n", sync_args->op.sync.offset); 2031 TAILQ_REMOVE(&file->sync_requests, sync_req, args.op.sync.tailq); 2032 pthread_spin_unlock(&file->lock); 2033 2034 sync_args->fn.file_op(sync_args->arg, bserrno); 2035 pthread_spin_lock(&file->lock); 2036 free_fs_request(sync_req); 2037 pthread_spin_unlock(&file->lock); 2038 2039 __check_sync_reqs(file); 2040 } 2041 2042 static void 2043 __check_sync_reqs(struct spdk_file *file) 2044 { 2045 struct spdk_fs_request *sync_req; 2046 2047 pthread_spin_lock(&file->lock); 2048 2049 TAILQ_FOREACH(sync_req, &file->sync_requests, args.op.sync.tailq) { 2050 if (sync_req->args.op.sync.offset <= file->length_flushed) { 2051 break; 2052 } 2053 } 2054 2055 if (sync_req != NULL && !sync_req->args.op.sync.xattr_in_progress) { 2056 BLOBFS_TRACE(file, "set xattr length 0x%jx\n", file->length_flushed); 2057 sync_req->args.op.sync.xattr_in_progress = true; 2058 spdk_blob_set_xattr(file->blob, "length", &file->length_flushed, 2059 sizeof(file->length_flushed)); 2060 2061 pthread_spin_unlock(&file->lock); 2062 spdk_trace_record(TRACE_BLOBFS_XATTR_START, 0, file->length_flushed, 2063 0, file->trace_arg_name); 2064 spdk_blob_sync_md(file->blob, __file_cache_finish_sync, sync_req); 2065 } else { 2066 pthread_spin_unlock(&file->lock); 2067 } 2068 } 2069 2070 static void 2071 __file_flush_done(void *ctx, int bserrno) 2072 { 2073 struct spdk_fs_request *req = ctx; 2074 struct spdk_fs_cb_args *args = &req->args; 2075 struct spdk_file *file = args->file; 2076 struct cache_buffer *next = args->op.flush.cache_buffer; 2077 2078 BLOBFS_TRACE(file, "length=%jx\n", args->op.flush.length); 2079 2080 pthread_spin_lock(&file->lock); 2081 next->in_progress = false; 2082 next->bytes_flushed += args->op.flush.length; 2083 file->length_flushed += args->op.flush.length; 2084 if (file->length_flushed > file->length) { 2085 file->length = file->length_flushed; 2086 } 2087 if (next->bytes_flushed == next->buf_size) { 2088 BLOBFS_TRACE(file, "write buffer fully flushed 0x%jx\n", file->length_flushed); 2089 next = spdk_tree_find_buffer(file->tree, file->length_flushed); 2090 } 2091 2092 /* 2093 * Assert that there is no cached data that extends past the end of the underlying 2094 * blob. 2095 */ 2096 assert(next == NULL || next->offset < __file_get_blob_size(file) || 2097 next->bytes_filled == 0); 2098 2099 pthread_spin_unlock(&file->lock); 2100 2101 __check_sync_reqs(file); 2102 2103 __file_flush(req); 2104 } 2105 2106 static void 2107 __file_flush(void *ctx) 2108 { 2109 struct spdk_fs_request *req = ctx; 2110 struct spdk_fs_cb_args *args = &req->args; 2111 struct spdk_file *file = args->file; 2112 struct cache_buffer *next; 2113 uint64_t offset, length, start_lba, num_lba; 2114 uint32_t lba_size; 2115 2116 pthread_spin_lock(&file->lock); 2117 next = spdk_tree_find_buffer(file->tree, file->length_flushed); 2118 if (next == NULL || next->in_progress) { 2119 /* 2120 * There is either no data to flush, or a flush I/O is already in 2121 * progress. So return immediately - if a flush I/O is in 2122 * progress we will flush more data after that is completed. 2123 */ 2124 free_fs_request(req); 2125 if (next == NULL) { 2126 /* 2127 * For cases where a file's cache was evicted, and then the 2128 * file was later appended, we will write the data directly 2129 * to disk and bypass cache. So just update length_flushed 2130 * here to reflect that all data was already written to disk. 2131 */ 2132 file->length_flushed = file->append_pos; 2133 } 2134 pthread_spin_unlock(&file->lock); 2135 if (next == NULL) { 2136 /* 2137 * There is no data to flush, but we still need to check for any 2138 * outstanding sync requests to make sure metadata gets updated. 2139 */ 2140 __check_sync_reqs(file); 2141 } 2142 return; 2143 } 2144 2145 offset = next->offset + next->bytes_flushed; 2146 length = next->bytes_filled - next->bytes_flushed; 2147 if (length == 0) { 2148 free_fs_request(req); 2149 pthread_spin_unlock(&file->lock); 2150 return; 2151 } 2152 args->op.flush.length = length; 2153 args->op.flush.cache_buffer = next; 2154 2155 __get_page_parameters(file, offset, length, &start_lba, &lba_size, &num_lba); 2156 2157 next->in_progress = true; 2158 BLOBFS_TRACE(file, "offset=%jx length=%jx page start=%jx num=%jx\n", 2159 offset, length, start_lba, num_lba); 2160 pthread_spin_unlock(&file->lock); 2161 spdk_blob_io_write(file->blob, file->fs->sync_target.sync_fs_channel->bs_channel, 2162 next->buf + (start_lba * lba_size) - next->offset, 2163 start_lba, num_lba, __file_flush_done, req); 2164 } 2165 2166 static void 2167 __file_extend_done(void *arg, int bserrno) 2168 { 2169 struct spdk_fs_cb_args *args = arg; 2170 2171 __wake_caller(args, bserrno); 2172 } 2173 2174 static void 2175 __file_extend_resize_cb(void *_args, int bserrno) 2176 { 2177 struct spdk_fs_cb_args *args = _args; 2178 struct spdk_file *file = args->file; 2179 2180 if (bserrno) { 2181 __wake_caller(args, bserrno); 2182 return; 2183 } 2184 2185 spdk_blob_sync_md(file->blob, __file_extend_done, args); 2186 } 2187 2188 static void 2189 __file_extend_blob(void *_args) 2190 { 2191 struct spdk_fs_cb_args *args = _args; 2192 struct spdk_file *file = args->file; 2193 2194 spdk_blob_resize(file->blob, args->op.resize.num_clusters, __file_extend_resize_cb, args); 2195 } 2196 2197 static void 2198 __rw_from_file_done(void *ctx, int bserrno) 2199 { 2200 struct spdk_fs_request *req = ctx; 2201 2202 __wake_caller(&req->args, bserrno); 2203 free_fs_request(req); 2204 } 2205 2206 static void 2207 __rw_from_file(void *ctx) 2208 { 2209 struct spdk_fs_request *req = ctx; 2210 struct spdk_fs_cb_args *args = &req->args; 2211 struct spdk_file *file = args->file; 2212 2213 if (args->op.rw.is_read) { 2214 spdk_file_read_async(file, file->fs->sync_target.sync_io_channel, args->iovs[0].iov_base, 2215 args->op.rw.offset, (uint64_t)args->iovs[0].iov_len, 2216 __rw_from_file_done, req); 2217 } else { 2218 spdk_file_write_async(file, file->fs->sync_target.sync_io_channel, args->iovs[0].iov_base, 2219 args->op.rw.offset, (uint64_t)args->iovs[0].iov_len, 2220 __rw_from_file_done, req); 2221 } 2222 } 2223 2224 static int 2225 __send_rw_from_file(struct spdk_file *file, void *payload, 2226 uint64_t offset, uint64_t length, bool is_read, 2227 struct spdk_fs_channel *channel) 2228 { 2229 struct spdk_fs_request *req; 2230 struct spdk_fs_cb_args *args; 2231 2232 req = alloc_fs_request_with_iov(channel, 1); 2233 if (req == NULL) { 2234 sem_post(&channel->sem); 2235 return -ENOMEM; 2236 } 2237 2238 args = &req->args; 2239 args->file = file; 2240 args->sem = &channel->sem; 2241 args->iovs[0].iov_base = payload; 2242 args->iovs[0].iov_len = (size_t)length; 2243 args->op.rw.offset = offset; 2244 args->op.rw.is_read = is_read; 2245 file->fs->send_request(__rw_from_file, req); 2246 return 0; 2247 } 2248 2249 int 2250 spdk_file_write(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx, 2251 void *payload, uint64_t offset, uint64_t length) 2252 { 2253 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 2254 struct spdk_fs_request *flush_req; 2255 uint64_t rem_length, copy, blob_size, cluster_sz; 2256 uint32_t cache_buffers_filled = 0; 2257 uint8_t *cur_payload; 2258 struct cache_buffer *last; 2259 2260 BLOBFS_TRACE_RW(file, "offset=%jx length=%jx\n", offset, length); 2261 2262 if (length == 0) { 2263 return 0; 2264 } 2265 2266 if (offset != file->append_pos) { 2267 BLOBFS_TRACE(file, " error offset=%jx append_pos=%jx\n", offset, file->append_pos); 2268 return -EINVAL; 2269 } 2270 2271 pthread_spin_lock(&file->lock); 2272 file->open_for_writing = true; 2273 2274 if ((file->last == NULL) && (file->append_pos % CACHE_BUFFER_SIZE == 0)) { 2275 cache_append_buffer(file); 2276 } 2277 2278 if (file->last == NULL) { 2279 int rc; 2280 2281 file->append_pos += length; 2282 pthread_spin_unlock(&file->lock); 2283 rc = __send_rw_from_file(file, payload, offset, length, false, channel); 2284 sem_wait(&channel->sem); 2285 return rc; 2286 } 2287 2288 blob_size = __file_get_blob_size(file); 2289 2290 if ((offset + length) > blob_size) { 2291 struct spdk_fs_cb_args extend_args = {}; 2292 2293 cluster_sz = file->fs->bs_opts.cluster_sz; 2294 extend_args.sem = &channel->sem; 2295 extend_args.op.resize.num_clusters = __bytes_to_clusters((offset + length), cluster_sz); 2296 extend_args.file = file; 2297 BLOBFS_TRACE(file, "start resize to %u clusters\n", extend_args.op.resize.num_clusters); 2298 pthread_spin_unlock(&file->lock); 2299 file->fs->send_request(__file_extend_blob, &extend_args); 2300 sem_wait(&channel->sem); 2301 if (extend_args.rc) { 2302 return extend_args.rc; 2303 } 2304 } 2305 2306 flush_req = alloc_fs_request(channel); 2307 if (flush_req == NULL) { 2308 pthread_spin_unlock(&file->lock); 2309 return -ENOMEM; 2310 } 2311 2312 last = file->last; 2313 rem_length = length; 2314 cur_payload = payload; 2315 while (rem_length > 0) { 2316 copy = last->buf_size - last->bytes_filled; 2317 if (copy > rem_length) { 2318 copy = rem_length; 2319 } 2320 BLOBFS_TRACE_RW(file, " fill offset=%jx length=%jx\n", file->append_pos, copy); 2321 memcpy(&last->buf[last->bytes_filled], cur_payload, copy); 2322 file->append_pos += copy; 2323 if (file->length < file->append_pos) { 2324 file->length = file->append_pos; 2325 } 2326 cur_payload += copy; 2327 last->bytes_filled += copy; 2328 rem_length -= copy; 2329 if (last->bytes_filled == last->buf_size) { 2330 cache_buffers_filled++; 2331 last = cache_append_buffer(file); 2332 if (last == NULL) { 2333 BLOBFS_TRACE(file, "nomem\n"); 2334 free_fs_request(flush_req); 2335 pthread_spin_unlock(&file->lock); 2336 return -ENOMEM; 2337 } 2338 } 2339 } 2340 2341 pthread_spin_unlock(&file->lock); 2342 2343 if (cache_buffers_filled == 0) { 2344 free_fs_request(flush_req); 2345 return 0; 2346 } 2347 2348 flush_req->args.file = file; 2349 file->fs->send_request(__file_flush, flush_req); 2350 return 0; 2351 } 2352 2353 static void 2354 __readahead_done(void *ctx, int bserrno) 2355 { 2356 struct spdk_fs_request *req = ctx; 2357 struct spdk_fs_cb_args *args = &req->args; 2358 struct cache_buffer *cache_buffer = args->op.readahead.cache_buffer; 2359 struct spdk_file *file = args->file; 2360 2361 BLOBFS_TRACE(file, "offset=%jx\n", cache_buffer->offset); 2362 2363 pthread_spin_lock(&file->lock); 2364 cache_buffer->bytes_filled = args->op.readahead.length; 2365 cache_buffer->bytes_flushed = args->op.readahead.length; 2366 cache_buffer->in_progress = false; 2367 pthread_spin_unlock(&file->lock); 2368 2369 free_fs_request(req); 2370 } 2371 2372 static void 2373 __readahead(void *ctx) 2374 { 2375 struct spdk_fs_request *req = ctx; 2376 struct spdk_fs_cb_args *args = &req->args; 2377 struct spdk_file *file = args->file; 2378 uint64_t offset, length, start_lba, num_lba; 2379 uint32_t lba_size; 2380 2381 offset = args->op.readahead.offset; 2382 length = args->op.readahead.length; 2383 assert(length > 0); 2384 2385 __get_page_parameters(file, offset, length, &start_lba, &lba_size, &num_lba); 2386 2387 BLOBFS_TRACE(file, "offset=%jx length=%jx page start=%jx num=%jx\n", 2388 offset, length, start_lba, num_lba); 2389 spdk_blob_io_read(file->blob, file->fs->sync_target.sync_fs_channel->bs_channel, 2390 args->op.readahead.cache_buffer->buf, 2391 start_lba, num_lba, __readahead_done, req); 2392 } 2393 2394 static uint64_t 2395 __next_cache_buffer_offset(uint64_t offset) 2396 { 2397 return (offset + CACHE_BUFFER_SIZE) & ~(CACHE_TREE_LEVEL_MASK(0)); 2398 } 2399 2400 static void 2401 check_readahead(struct spdk_file *file, uint64_t offset, 2402 struct spdk_fs_channel *channel) 2403 { 2404 struct spdk_fs_request *req; 2405 struct spdk_fs_cb_args *args; 2406 2407 offset = __next_cache_buffer_offset(offset); 2408 if (spdk_tree_find_buffer(file->tree, offset) != NULL || file->length <= offset) { 2409 return; 2410 } 2411 2412 req = alloc_fs_request(channel); 2413 if (req == NULL) { 2414 return; 2415 } 2416 args = &req->args; 2417 2418 BLOBFS_TRACE(file, "offset=%jx\n", offset); 2419 2420 args->file = file; 2421 args->op.readahead.offset = offset; 2422 args->op.readahead.cache_buffer = cache_insert_buffer(file, offset); 2423 if (!args->op.readahead.cache_buffer) { 2424 BLOBFS_TRACE(file, "Cannot allocate buf for offset=%jx\n", offset); 2425 free_fs_request(req); 2426 return; 2427 } 2428 2429 args->op.readahead.cache_buffer->in_progress = true; 2430 if (file->length < (offset + CACHE_BUFFER_SIZE)) { 2431 args->op.readahead.length = file->length & (CACHE_BUFFER_SIZE - 1); 2432 } else { 2433 args->op.readahead.length = CACHE_BUFFER_SIZE; 2434 } 2435 file->fs->send_request(__readahead, req); 2436 } 2437 2438 static int 2439 __file_read(struct spdk_file *file, void *payload, uint64_t offset, uint64_t length, 2440 struct spdk_fs_channel *channel) 2441 { 2442 struct cache_buffer *buf; 2443 int rc; 2444 2445 buf = spdk_tree_find_filled_buffer(file->tree, offset); 2446 if (buf == NULL) { 2447 pthread_spin_unlock(&file->lock); 2448 rc = __send_rw_from_file(file, payload, offset, length, true, channel); 2449 pthread_spin_lock(&file->lock); 2450 return rc; 2451 } 2452 2453 if ((offset + length) > (buf->offset + buf->bytes_filled)) { 2454 length = buf->offset + buf->bytes_filled - offset; 2455 } 2456 BLOBFS_TRACE(file, "read %p offset=%ju length=%ju\n", payload, offset, length); 2457 memcpy(payload, &buf->buf[offset - buf->offset], length); 2458 if ((offset + length) % CACHE_BUFFER_SIZE == 0) { 2459 pthread_spin_lock(&g_caches_lock); 2460 spdk_tree_remove_buffer(file->tree, buf); 2461 if (file->tree->present_mask == 0) { 2462 TAILQ_REMOVE(&g_caches, file, cache_tailq); 2463 } 2464 pthread_spin_unlock(&g_caches_lock); 2465 } 2466 2467 sem_post(&channel->sem); 2468 return 0; 2469 } 2470 2471 int64_t 2472 spdk_file_read(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx, 2473 void *payload, uint64_t offset, uint64_t length) 2474 { 2475 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 2476 uint64_t final_offset, final_length; 2477 uint32_t sub_reads = 0; 2478 int rc = 0; 2479 2480 pthread_spin_lock(&file->lock); 2481 2482 BLOBFS_TRACE_RW(file, "offset=%ju length=%ju\n", offset, length); 2483 2484 file->open_for_writing = false; 2485 2486 if (length == 0 || offset >= file->append_pos) { 2487 pthread_spin_unlock(&file->lock); 2488 return 0; 2489 } 2490 2491 if (offset + length > file->append_pos) { 2492 length = file->append_pos - offset; 2493 } 2494 2495 if (offset != file->next_seq_offset) { 2496 file->seq_byte_count = 0; 2497 } 2498 file->seq_byte_count += length; 2499 file->next_seq_offset = offset + length; 2500 if (file->seq_byte_count >= CACHE_READAHEAD_THRESHOLD) { 2501 check_readahead(file, offset, channel); 2502 check_readahead(file, offset + CACHE_BUFFER_SIZE, channel); 2503 } 2504 2505 final_length = 0; 2506 final_offset = offset + length; 2507 while (offset < final_offset) { 2508 length = NEXT_CACHE_BUFFER_OFFSET(offset) - offset; 2509 if (length > (final_offset - offset)) { 2510 length = final_offset - offset; 2511 } 2512 rc = __file_read(file, payload, offset, length, channel); 2513 if (rc == 0) { 2514 final_length += length; 2515 } else { 2516 break; 2517 } 2518 payload += length; 2519 offset += length; 2520 sub_reads++; 2521 } 2522 pthread_spin_unlock(&file->lock); 2523 while (sub_reads-- > 0) { 2524 sem_wait(&channel->sem); 2525 } 2526 if (rc == 0) { 2527 return final_length; 2528 } else { 2529 return rc; 2530 } 2531 } 2532 2533 static void 2534 _file_sync(struct spdk_file *file, struct spdk_fs_channel *channel, 2535 spdk_file_op_complete cb_fn, void *cb_arg) 2536 { 2537 struct spdk_fs_request *sync_req; 2538 struct spdk_fs_request *flush_req; 2539 struct spdk_fs_cb_args *sync_args; 2540 struct spdk_fs_cb_args *flush_args; 2541 2542 BLOBFS_TRACE(file, "offset=%jx\n", file->append_pos); 2543 2544 pthread_spin_lock(&file->lock); 2545 if (file->append_pos <= file->length_flushed) { 2546 BLOBFS_TRACE(file, "done - no data to flush\n"); 2547 pthread_spin_unlock(&file->lock); 2548 cb_fn(cb_arg, 0); 2549 return; 2550 } 2551 2552 sync_req = alloc_fs_request(channel); 2553 if (!sync_req) { 2554 pthread_spin_unlock(&file->lock); 2555 cb_fn(cb_arg, -ENOMEM); 2556 return; 2557 } 2558 sync_args = &sync_req->args; 2559 2560 flush_req = alloc_fs_request(channel); 2561 if (!flush_req) { 2562 pthread_spin_unlock(&file->lock); 2563 cb_fn(cb_arg, -ENOMEM); 2564 return; 2565 } 2566 flush_args = &flush_req->args; 2567 2568 sync_args->file = file; 2569 sync_args->fn.file_op = cb_fn; 2570 sync_args->arg = cb_arg; 2571 sync_args->op.sync.offset = file->append_pos; 2572 sync_args->op.sync.xattr_in_progress = false; 2573 TAILQ_INSERT_TAIL(&file->sync_requests, sync_req, args.op.sync.tailq); 2574 pthread_spin_unlock(&file->lock); 2575 2576 flush_args->file = file; 2577 channel->send_request(__file_flush, flush_req); 2578 } 2579 2580 int 2581 spdk_file_sync(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx) 2582 { 2583 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 2584 struct spdk_fs_cb_args args = {}; 2585 2586 args.sem = &channel->sem; 2587 _file_sync(file, channel, __wake_caller, &args); 2588 sem_wait(&channel->sem); 2589 2590 return args.rc; 2591 } 2592 2593 void 2594 spdk_file_sync_async(struct spdk_file *file, struct spdk_io_channel *_channel, 2595 spdk_file_op_complete cb_fn, void *cb_arg) 2596 { 2597 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 2598 2599 _file_sync(file, channel, cb_fn, cb_arg); 2600 } 2601 2602 void 2603 spdk_file_set_priority(struct spdk_file *file, uint32_t priority) 2604 { 2605 BLOBFS_TRACE(file, "priority=%u\n", priority); 2606 file->priority = priority; 2607 2608 } 2609 2610 /* 2611 * Close routines 2612 */ 2613 2614 static void 2615 __file_close_async_done(void *ctx, int bserrno) 2616 { 2617 struct spdk_fs_request *req = ctx; 2618 struct spdk_fs_cb_args *args = &req->args; 2619 struct spdk_file *file = args->file; 2620 2621 spdk_trace_record(TRACE_BLOBFS_CLOSE, 0, 0, 0, file->trace_arg_name); 2622 2623 if (file->is_deleted) { 2624 spdk_fs_delete_file_async(file->fs, file->name, blob_delete_cb, ctx); 2625 return; 2626 } 2627 2628 args->fn.file_op(args->arg, bserrno); 2629 free_fs_request(req); 2630 } 2631 2632 static void 2633 __file_close_async(struct spdk_file *file, struct spdk_fs_request *req) 2634 { 2635 struct spdk_blob *blob; 2636 2637 pthread_spin_lock(&file->lock); 2638 if (file->ref_count == 0) { 2639 pthread_spin_unlock(&file->lock); 2640 __file_close_async_done(req, -EBADF); 2641 return; 2642 } 2643 2644 file->ref_count--; 2645 if (file->ref_count > 0) { 2646 pthread_spin_unlock(&file->lock); 2647 req->args.fn.file_op(req->args.arg, 0); 2648 free_fs_request(req); 2649 return; 2650 } 2651 2652 pthread_spin_unlock(&file->lock); 2653 2654 blob = file->blob; 2655 file->blob = NULL; 2656 spdk_blob_close(blob, __file_close_async_done, req); 2657 } 2658 2659 static void 2660 __file_close_async__sync_done(void *arg, int fserrno) 2661 { 2662 struct spdk_fs_request *req = arg; 2663 struct spdk_fs_cb_args *args = &req->args; 2664 2665 __file_close_async(args->file, req); 2666 } 2667 2668 void 2669 spdk_file_close_async(struct spdk_file *file, spdk_file_op_complete cb_fn, void *cb_arg) 2670 { 2671 struct spdk_fs_request *req; 2672 struct spdk_fs_cb_args *args; 2673 2674 req = alloc_fs_request(file->fs->md_target.md_fs_channel); 2675 if (req == NULL) { 2676 cb_fn(cb_arg, -ENOMEM); 2677 return; 2678 } 2679 2680 args = &req->args; 2681 args->file = file; 2682 args->fn.file_op = cb_fn; 2683 args->arg = cb_arg; 2684 2685 spdk_file_sync_async(file, file->fs->md_target.md_io_channel, __file_close_async__sync_done, req); 2686 } 2687 2688 static void 2689 __file_close(void *arg) 2690 { 2691 struct spdk_fs_request *req = arg; 2692 struct spdk_fs_cb_args *args = &req->args; 2693 struct spdk_file *file = args->file; 2694 2695 __file_close_async(file, req); 2696 } 2697 2698 int 2699 spdk_file_close(struct spdk_file *file, struct spdk_fs_thread_ctx *ctx) 2700 { 2701 struct spdk_fs_channel *channel = (struct spdk_fs_channel *)ctx; 2702 struct spdk_fs_request *req; 2703 struct spdk_fs_cb_args *args; 2704 2705 req = alloc_fs_request(channel); 2706 if (req == NULL) { 2707 return -ENOMEM; 2708 } 2709 2710 args = &req->args; 2711 2712 spdk_file_sync(file, ctx); 2713 BLOBFS_TRACE(file, "name=%s\n", file->name); 2714 args->file = file; 2715 args->sem = &channel->sem; 2716 args->fn.file_op = __wake_caller; 2717 args->arg = args; 2718 channel->send_request(__file_close, req); 2719 sem_wait(&channel->sem); 2720 2721 return args->rc; 2722 } 2723 2724 int 2725 spdk_file_get_id(struct spdk_file *file, void *id, size_t size) 2726 { 2727 if (size < sizeof(spdk_blob_id)) { 2728 return -EINVAL; 2729 } 2730 2731 memcpy(id, &file->blobid, sizeof(spdk_blob_id)); 2732 2733 return sizeof(spdk_blob_id); 2734 } 2735 2736 static void 2737 cache_free_buffers(struct spdk_file *file) 2738 { 2739 BLOBFS_TRACE(file, "free=%s\n", file->name); 2740 pthread_spin_lock(&file->lock); 2741 pthread_spin_lock(&g_caches_lock); 2742 if (file->tree->present_mask == 0) { 2743 pthread_spin_unlock(&g_caches_lock); 2744 pthread_spin_unlock(&file->lock); 2745 return; 2746 } 2747 spdk_tree_free_buffers(file->tree); 2748 2749 TAILQ_REMOVE(&g_caches, file, cache_tailq); 2750 /* If not freed, put it in the end of the queue */ 2751 if (file->tree->present_mask != 0) { 2752 TAILQ_INSERT_TAIL(&g_caches, file, cache_tailq); 2753 } 2754 file->last = NULL; 2755 pthread_spin_unlock(&g_caches_lock); 2756 pthread_spin_unlock(&file->lock); 2757 } 2758 2759 SPDK_LOG_REGISTER_COMPONENT("blobfs", SPDK_LOG_BLOBFS) 2760 SPDK_LOG_REGISTER_COMPONENT("blobfs_rw", SPDK_LOG_BLOBFS_RW) 2761