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 <stdbool.h> 35 #include <assert.h> 36 #include <errno.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <pthread.h> 40 41 #include "spdk/blobfs.h" 42 #include "blobfs_internal.h" 43 44 #include "spdk/queue.h" 45 #include "spdk/io_channel.h" 46 #include "spdk/assert.h" 47 #include "spdk/env.h" 48 #include "spdk_internal/log.h" 49 50 #define BLOBFS_TRACE(file, str, args...) \ 51 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s " str, file->name, ##args) 52 53 #define BLOBFS_TRACE_RW(file, str, args...) \ 54 SPDK_TRACELOG(SPDK_TRACE_BLOBFS_RW, "file=%s " str, file->name, ##args) 55 56 #define BLOBFS_CACHE_SIZE (4ULL * 1024 * 1024 * 1024) 57 58 static uint64_t g_fs_cache_size = BLOBFS_CACHE_SIZE; 59 static struct spdk_mempool *g_cache_pool; 60 static TAILQ_HEAD(, spdk_file) g_caches; 61 static pthread_spinlock_t g_caches_lock; 62 63 static void 64 __sem_post(void *arg, int bserrno) 65 { 66 sem_t *sem = arg; 67 68 sem_post(sem); 69 } 70 71 void 72 spdk_cache_buffer_free(struct cache_buffer *cache_buffer) 73 { 74 spdk_mempool_put(g_cache_pool, cache_buffer->buf); 75 free(cache_buffer); 76 } 77 78 #define CACHE_READAHEAD_THRESHOLD (128 * 1024) 79 80 struct spdk_file { 81 struct spdk_filesystem *fs; 82 struct spdk_blob *blob; 83 char *name; 84 uint64_t length; 85 bool open_for_writing; 86 uint64_t length_flushed; 87 uint64_t append_pos; 88 uint64_t seq_byte_count; 89 uint64_t next_seq_offset; 90 uint32_t priority; 91 TAILQ_ENTRY(spdk_file) tailq; 92 spdk_blob_id blobid; 93 uint32_t ref_count; 94 pthread_spinlock_t lock; 95 struct cache_buffer *last; 96 struct cache_tree *tree; 97 TAILQ_HEAD(open_requests_head, spdk_fs_request) open_requests; 98 TAILQ_HEAD(sync_requests_head, spdk_fs_request) sync_requests; 99 TAILQ_ENTRY(spdk_file) cache_tailq; 100 }; 101 102 struct spdk_filesystem { 103 struct spdk_blob_store *bs; 104 TAILQ_HEAD(, spdk_file) files; 105 struct spdk_bs_opts bs_opts; 106 struct spdk_bs_dev *bdev; 107 fs_send_request_fn send_request; 108 struct spdk_io_channel *sync_io_channel; 109 struct spdk_fs_channel *sync_fs_channel; 110 struct spdk_io_channel *md_io_channel; 111 struct spdk_fs_channel *md_fs_channel; 112 }; 113 114 struct spdk_fs_cb_args { 115 union { 116 spdk_fs_op_with_handle_complete fs_op_with_handle; 117 spdk_fs_op_complete fs_op; 118 spdk_file_op_with_handle_complete file_op_with_handle; 119 spdk_file_op_complete file_op; 120 spdk_file_stat_op_complete stat_op; 121 } fn; 122 void *arg; 123 sem_t *sem; 124 struct spdk_filesystem *fs; 125 struct spdk_file *file; 126 int rc; 127 bool from_request; 128 union { 129 struct { 130 uint64_t length; 131 } truncate; 132 struct { 133 struct spdk_io_channel *channel; 134 void *user_buf; 135 void *pin_buf; 136 int is_read; 137 off_t offset; 138 size_t length; 139 uint64_t start_page; 140 uint64_t num_pages; 141 uint32_t blocklen; 142 } rw; 143 struct { 144 const char *old_name; 145 const char *new_name; 146 } rename; 147 struct { 148 struct cache_buffer *cache_buffer; 149 uint64_t length; 150 } flush; 151 struct { 152 struct cache_buffer *cache_buffer; 153 uint64_t length; 154 uint64_t offset; 155 } readahead; 156 struct { 157 uint64_t offset; 158 TAILQ_ENTRY(spdk_fs_request) tailq; 159 } sync; 160 struct { 161 uint32_t num_clusters; 162 } resize; 163 struct { 164 const char *name; 165 uint32_t flags; 166 TAILQ_ENTRY(spdk_fs_request) tailq; 167 } open; 168 struct { 169 const char *name; 170 } create; 171 struct { 172 const char *name; 173 } delete; 174 struct { 175 const char *name; 176 } stat; 177 } op; 178 }; 179 180 static void cache_free_buffers(struct spdk_file *file); 181 182 static void 183 __initialize_cache(void) 184 { 185 if (g_cache_pool != NULL) { 186 return; 187 } 188 189 g_cache_pool = spdk_mempool_create("spdk_fs_cache", 190 g_fs_cache_size / CACHE_BUFFER_SIZE, 191 CACHE_BUFFER_SIZE, -1, SPDK_ENV_SOCKET_ID_ANY); 192 TAILQ_INIT(&g_caches); 193 pthread_spin_init(&g_caches_lock, 0); 194 } 195 196 static uint64_t 197 __file_get_blob_size(struct spdk_file *file) 198 { 199 uint64_t cluster_sz; 200 201 cluster_sz = file->fs->bs_opts.cluster_sz; 202 return cluster_sz * spdk_blob_get_num_clusters(file->blob); 203 } 204 205 struct spdk_fs_request { 206 struct spdk_fs_cb_args args; 207 TAILQ_ENTRY(spdk_fs_request) link; 208 struct spdk_fs_channel *channel; 209 }; 210 211 struct spdk_fs_channel { 212 struct spdk_fs_request *req_mem; 213 TAILQ_HEAD(, spdk_fs_request) reqs; 214 sem_t sem; 215 struct spdk_filesystem *fs; 216 struct spdk_io_channel *bs_channel; 217 fs_send_request_fn send_request; 218 }; 219 220 static struct spdk_fs_request * 221 alloc_fs_request(struct spdk_fs_channel *channel) 222 { 223 struct spdk_fs_request *req; 224 225 req = TAILQ_FIRST(&channel->reqs); 226 if (!req) { 227 return NULL; 228 } 229 TAILQ_REMOVE(&channel->reqs, req, link); 230 memset(req, 0, sizeof(*req)); 231 req->channel = channel; 232 req->args.from_request = true; 233 234 return req; 235 } 236 237 static void 238 free_fs_request(struct spdk_fs_request *req) 239 { 240 TAILQ_INSERT_HEAD(&req->channel->reqs, req, link); 241 } 242 243 static int 244 _spdk_fs_channel_create(void *io_device, uint32_t priority, void *ctx_buf, void *unique_ctx) 245 { 246 struct spdk_filesystem *fs = io_device; 247 struct spdk_fs_channel *channel = ctx_buf; 248 uint32_t max_ops = *(uint32_t *)unique_ctx; 249 uint32_t i; 250 251 channel->req_mem = calloc(max_ops, sizeof(struct spdk_fs_request)); 252 if (!channel->req_mem) { 253 free(channel); 254 return -1; 255 } 256 257 TAILQ_INIT(&channel->reqs); 258 sem_init(&channel->sem, 0, 0); 259 260 for (i = 0; i < max_ops; i++) { 261 TAILQ_INSERT_TAIL(&channel->reqs, &channel->req_mem[i], link); 262 } 263 264 channel->fs = fs; 265 266 return 0; 267 } 268 269 static void 270 _spdk_fs_channel_destroy(void *io_device, void *ctx_buf) 271 { 272 struct spdk_fs_channel *channel = ctx_buf; 273 274 free(channel->req_mem); 275 if (channel->bs_channel != NULL) { 276 spdk_bs_free_io_channel(channel->bs_channel); 277 } 278 } 279 280 static void 281 __send_request_direct(fs_request_fn fn, void *arg) 282 { 283 fn(arg); 284 } 285 286 static void 287 common_fs_bs_init(struct spdk_filesystem *fs, struct spdk_blob_store *bs) 288 { 289 fs->bs = bs; 290 fs->bs_opts.cluster_sz = spdk_bs_get_cluster_size(bs); 291 fs->md_fs_channel->bs_channel = spdk_bs_alloc_io_channel(fs->bs, SPDK_IO_PRIORITY_DEFAULT, 512); 292 fs->md_fs_channel->send_request = __send_request_direct; 293 fs->sync_fs_channel->bs_channel = spdk_bs_alloc_io_channel(fs->bs, SPDK_IO_PRIORITY_DEFAULT, 512); 294 fs->sync_fs_channel->send_request = __send_request_direct; 295 } 296 297 static void 298 init_cb(void *ctx, struct spdk_blob_store *bs, int bserrno) 299 { 300 struct spdk_fs_request *req = ctx; 301 struct spdk_fs_cb_args *args = &req->args; 302 struct spdk_filesystem *fs = args->fs; 303 304 if (bserrno == 0) { 305 common_fs_bs_init(fs, bs); 306 } else { 307 free(fs); 308 } 309 310 args->fn.fs_op_with_handle(args->arg, fs, bserrno); 311 free_fs_request(req); 312 } 313 314 static struct spdk_filesystem * 315 fs_alloc(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn) 316 { 317 struct spdk_filesystem *fs; 318 uint32_t max_ops = 512; 319 320 fs = calloc(1, sizeof(*fs)); 321 if (fs == NULL) { 322 return NULL; 323 } 324 325 fs->bdev = dev; 326 fs->send_request = send_request_fn; 327 TAILQ_INIT(&fs->files); 328 spdk_io_device_register(fs, _spdk_fs_channel_create, _spdk_fs_channel_destroy, 329 sizeof(struct spdk_fs_channel)); 330 331 fs->md_io_channel = spdk_get_io_channel(fs, SPDK_IO_PRIORITY_DEFAULT, true, (void *)&max_ops); 332 fs->md_fs_channel = spdk_io_channel_get_ctx(fs->md_io_channel); 333 334 fs->sync_io_channel = spdk_get_io_channel(fs, SPDK_IO_PRIORITY_DEFAULT, true, (void *)&max_ops); 335 fs->sync_fs_channel = spdk_io_channel_get_ctx(fs->sync_io_channel); 336 337 __initialize_cache(); 338 339 return fs; 340 } 341 342 void 343 spdk_fs_init(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn, 344 spdk_fs_op_with_handle_complete cb_fn, void *cb_arg) 345 { 346 struct spdk_filesystem *fs; 347 struct spdk_fs_request *req; 348 struct spdk_fs_cb_args *args; 349 350 fs = fs_alloc(dev, send_request_fn); 351 if (fs == NULL) { 352 cb_fn(cb_arg, NULL, -ENOMEM); 353 return; 354 } 355 356 req = alloc_fs_request(fs->md_fs_channel); 357 if (req == NULL) { 358 cb_fn(cb_arg, NULL, -ENOMEM); 359 return; 360 } 361 362 args = &req->args; 363 args->fn.fs_op_with_handle = cb_fn; 364 args->arg = cb_arg; 365 args->fs = fs; 366 367 spdk_bs_init(dev, NULL, init_cb, req); 368 } 369 370 static struct spdk_file * 371 file_alloc(struct spdk_filesystem *fs) 372 { 373 struct spdk_file *file; 374 375 file = calloc(1, sizeof(*file)); 376 if (file == NULL) { 377 return NULL; 378 } 379 380 file->fs = fs; 381 TAILQ_INIT(&file->open_requests); 382 TAILQ_INIT(&file->sync_requests); 383 pthread_spin_init(&file->lock, 0); 384 file->tree = calloc(1, sizeof(*file->tree)); 385 TAILQ_INSERT_TAIL(&fs->files, file, tailq); 386 file->priority = SPDK_FILE_PRIORITY_LOW; 387 return file; 388 } 389 390 static void 391 iter_cb(void *ctx, struct spdk_blob *blob, int rc) 392 { 393 struct spdk_fs_request *req = ctx; 394 struct spdk_fs_cb_args *args = &req->args; 395 struct spdk_filesystem *fs = args->fs; 396 struct spdk_file *f; 397 uint64_t *length; 398 const char *name; 399 size_t value_len; 400 401 if (rc == -ENOENT) { 402 /* Finished iterating */ 403 args->fn.fs_op_with_handle(args->arg, fs, 0); 404 free_fs_request(req); 405 return; 406 } else if (rc < 0) { 407 args->fn.fs_op_with_handle(args->arg, fs, rc); 408 free_fs_request(req); 409 return; 410 } 411 412 rc = spdk_bs_md_get_xattr_value(blob, "name", (const void **)&name, &value_len); 413 if (rc < 0) { 414 args->fn.fs_op_with_handle(args->arg, fs, rc); 415 free_fs_request(req); 416 return; 417 } 418 419 rc = spdk_bs_md_get_xattr_value(blob, "length", (const void **)&length, &value_len); 420 if (rc < 0) { 421 args->fn.fs_op_with_handle(args->arg, fs, rc); 422 free_fs_request(req); 423 return; 424 } 425 assert(value_len == 8); 426 427 f = file_alloc(fs); 428 if (f == NULL) { 429 args->fn.fs_op_with_handle(args->arg, fs, -ENOMEM); 430 free_fs_request(req); 431 return; 432 } 433 434 f->name = strdup(name); 435 f->blobid = spdk_blob_get_id(blob); 436 f->length = *length; 437 f->length_flushed = *length; 438 f->append_pos = *length; 439 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "added file %s length=%ju\n", f->name, f->length); 440 441 spdk_bs_md_iter_next(fs->bs, &blob, iter_cb, req); 442 } 443 444 static void 445 load_cb(void *ctx, struct spdk_blob_store *bs, int bserrno) 446 { 447 struct spdk_fs_request *req = ctx; 448 struct spdk_fs_cb_args *args = &req->args; 449 struct spdk_filesystem *fs = args->fs; 450 451 if (bserrno != 0) { 452 args->fn.fs_op_with_handle(args->arg, NULL, bserrno); 453 free_fs_request(req); 454 free(fs); 455 return; 456 } 457 458 common_fs_bs_init(fs, bs); 459 spdk_bs_md_iter_first(fs->bs, iter_cb, req); 460 } 461 462 void 463 spdk_fs_load(struct spdk_bs_dev *dev, fs_send_request_fn send_request_fn, 464 spdk_fs_op_with_handle_complete cb_fn, void *cb_arg) 465 { 466 struct spdk_filesystem *fs; 467 struct spdk_fs_cb_args *args; 468 struct spdk_fs_request *req; 469 470 fs = fs_alloc(dev, send_request_fn); 471 if (fs == NULL) { 472 cb_fn(cb_arg, NULL, -ENOMEM); 473 return; 474 } 475 476 req = alloc_fs_request(fs->md_fs_channel); 477 if (req == NULL) { 478 cb_fn(cb_arg, NULL, -ENOMEM); 479 return; 480 } 481 482 args = &req->args; 483 args->fn.fs_op_with_handle = cb_fn; 484 args->arg = cb_arg; 485 args->fs = fs; 486 487 spdk_bs_load(dev, load_cb, req); 488 } 489 490 static void 491 unload_cb(void *ctx, int bserrno) 492 { 493 struct spdk_fs_request *req = ctx; 494 struct spdk_fs_cb_args *args = &req->args; 495 struct spdk_filesystem *fs = args->fs; 496 497 args->fn.fs_op(args->arg, bserrno); 498 free(req); 499 spdk_io_device_unregister(fs); 500 free(fs); 501 } 502 503 void 504 spdk_fs_unload(struct spdk_filesystem *fs, spdk_fs_op_complete cb_fn, void *cb_arg) 505 { 506 struct spdk_fs_request *req; 507 struct spdk_fs_cb_args *args; 508 509 /* 510 * We must free the md_channel before unloading the blobstore, so just 511 * allocate this request from the general heap. 512 */ 513 req = calloc(1, sizeof(*req)); 514 if (req == NULL) { 515 cb_fn(cb_arg, -ENOMEM); 516 return; 517 } 518 519 args = &req->args; 520 args->fn.fs_op = cb_fn; 521 args->arg = cb_arg; 522 args->fs = fs; 523 524 spdk_fs_free_io_channel(fs->md_io_channel); 525 spdk_fs_free_io_channel(fs->sync_io_channel); 526 spdk_bs_unload(fs->bs, unload_cb, req); 527 } 528 529 static struct spdk_file * 530 fs_find_file(struct spdk_filesystem *fs, const char *name) 531 { 532 struct spdk_file *file; 533 534 TAILQ_FOREACH(file, &fs->files, tailq) { 535 if (!strncmp(name, file->name, SPDK_FILE_NAME_MAX)) { 536 return file; 537 } 538 } 539 540 return NULL; 541 } 542 543 void 544 spdk_fs_file_stat_async(struct spdk_filesystem *fs, const char *name, 545 spdk_file_stat_op_complete cb_fn, void *cb_arg) 546 { 547 struct spdk_file_stat stat; 548 struct spdk_file *f = NULL; 549 550 if (strnlen(name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 551 cb_fn(cb_arg, NULL, -ENAMETOOLONG); 552 return; 553 } 554 555 f = fs_find_file(fs, name); 556 if (f != NULL) { 557 stat.blobid = f->blobid; 558 stat.size = f->length; 559 cb_fn(cb_arg, &stat, 0); 560 return; 561 } 562 563 cb_fn(cb_arg, NULL, -ENOENT); 564 } 565 566 static void 567 __copy_stat(void *arg, struct spdk_file_stat *stat, int fserrno) 568 { 569 struct spdk_fs_request *req = arg; 570 struct spdk_fs_cb_args *args = &req->args; 571 572 args->rc = fserrno; 573 if (fserrno == 0) { 574 memcpy(args->arg, stat, sizeof(*stat)); 575 } 576 sem_post(args->sem); 577 } 578 579 static void 580 __file_stat(void *arg) 581 { 582 struct spdk_fs_request *req = arg; 583 struct spdk_fs_cb_args *args = &req->args; 584 585 spdk_fs_file_stat_async(args->fs, args->op.stat.name, 586 args->fn.stat_op, req); 587 } 588 589 int 590 spdk_fs_file_stat(struct spdk_filesystem *fs, struct spdk_io_channel *_channel, 591 const char *name, struct spdk_file_stat *stat) 592 { 593 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 594 struct spdk_fs_request *req; 595 int rc; 596 597 req = alloc_fs_request(channel); 598 assert(req != NULL); 599 600 req->args.fs = fs; 601 req->args.op.stat.name = name; 602 req->args.fn.stat_op = __copy_stat; 603 req->args.arg = stat; 604 req->args.sem = &channel->sem; 605 channel->send_request(__file_stat, req); 606 sem_wait(&channel->sem); 607 608 rc = req->args.rc; 609 free_fs_request(req); 610 611 return rc; 612 } 613 614 static void 615 fs_create_blob_close_cb(void *ctx, int bserrno) 616 { 617 struct spdk_fs_request *req = ctx; 618 struct spdk_fs_cb_args *args = &req->args; 619 620 args->fn.file_op(args->arg, bserrno); 621 free_fs_request(req); 622 } 623 624 static void 625 fs_create_blob_open_cb(void *ctx, struct spdk_blob *blob, int bserrno) 626 { 627 struct spdk_fs_request *req = ctx; 628 struct spdk_fs_cb_args *args = &req->args; 629 struct spdk_file *f = args->file; 630 uint64_t length = 0; 631 632 f->blob = blob; 633 spdk_bs_md_resize_blob(blob, 1); 634 spdk_blob_md_set_xattr(blob, "name", f->name, strlen(f->name) + 1); 635 spdk_blob_md_set_xattr(blob, "length", &length, sizeof(length)); 636 637 spdk_bs_md_close_blob(&f->blob, fs_create_blob_close_cb, args); 638 } 639 640 static void 641 fs_create_blob_create_cb(void *ctx, spdk_blob_id blobid, int bserrno) 642 { 643 struct spdk_fs_request *req = ctx; 644 struct spdk_fs_cb_args *args = &req->args; 645 struct spdk_file *f = args->file; 646 647 f->blobid = blobid; 648 spdk_bs_md_open_blob(f->fs->bs, blobid, fs_create_blob_open_cb, req); 649 } 650 651 void 652 spdk_fs_create_file_async(struct spdk_filesystem *fs, const char *name, 653 spdk_file_op_complete cb_fn, void *cb_arg) 654 { 655 struct spdk_file *file; 656 struct spdk_fs_request *req; 657 struct spdk_fs_cb_args *args; 658 659 if (strnlen(name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 660 cb_fn(cb_arg, -ENAMETOOLONG); 661 return; 662 } 663 664 file = fs_find_file(fs, name); 665 if (file != NULL) { 666 cb_fn(cb_arg, -EEXIST); 667 return; 668 } 669 670 file = file_alloc(fs); 671 if (file == NULL) { 672 cb_fn(cb_arg, -ENOMEM); 673 return; 674 } 675 676 req = alloc_fs_request(fs->md_fs_channel); 677 if (req == NULL) { 678 cb_fn(cb_arg, -ENOMEM); 679 return; 680 } 681 682 args = &req->args; 683 args->file = file; 684 args->fn.file_op = cb_fn; 685 args->arg = cb_arg; 686 687 file->name = strdup(name); 688 spdk_bs_md_create_blob(fs->bs, fs_create_blob_create_cb, args); 689 } 690 691 static void 692 __fs_create_file_done(void *arg, int fserrno) 693 { 694 struct spdk_fs_request *req = arg; 695 struct spdk_fs_cb_args *args = &req->args; 696 697 args->rc = fserrno; 698 sem_post(args->sem); 699 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s\n", args->op.create.name); 700 } 701 702 static void 703 __fs_create_file(void *arg) 704 { 705 struct spdk_fs_request *req = arg; 706 struct spdk_fs_cb_args *args = &req->args; 707 708 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s\n", args->op.create.name); 709 spdk_fs_create_file_async(args->fs, args->op.create.name, __fs_create_file_done, req); 710 } 711 712 int 713 spdk_fs_create_file(struct spdk_filesystem *fs, struct spdk_io_channel *_channel, const char *name) 714 { 715 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 716 struct spdk_fs_request *req; 717 struct spdk_fs_cb_args *args; 718 int rc; 719 720 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s\n", name); 721 722 req = alloc_fs_request(channel); 723 assert(req != NULL); 724 725 args = &req->args; 726 args->fs = fs; 727 args->op.create.name = name; 728 args->sem = &channel->sem; 729 fs->send_request(__fs_create_file, req); 730 sem_wait(&channel->sem); 731 rc = args->rc; 732 free_fs_request(req); 733 734 return rc; 735 } 736 737 static void 738 fs_open_blob_done(void *ctx, struct spdk_blob *blob, int bserrno) 739 { 740 struct spdk_fs_request *req = ctx; 741 struct spdk_fs_cb_args *args = &req->args; 742 struct spdk_file *f = args->file; 743 744 f->blob = blob; 745 while (!TAILQ_EMPTY(&f->open_requests)) { 746 req = TAILQ_FIRST(&f->open_requests); 747 args = &req->args; 748 TAILQ_REMOVE(&f->open_requests, req, args.op.open.tailq); 749 args->fn.file_op_with_handle(args->arg, f, bserrno); 750 free_fs_request(req); 751 } 752 } 753 754 static void 755 fs_open_blob_create_cb(void *ctx, int bserrno) 756 { 757 struct spdk_fs_request *req = ctx; 758 struct spdk_fs_cb_args *args = &req->args; 759 struct spdk_file *file = args->file; 760 struct spdk_filesystem *fs = args->fs; 761 762 if (file == NULL) { 763 file = fs_find_file(fs, args->op.open.name); 764 args->file = file; 765 } 766 767 file->ref_count++; 768 TAILQ_INSERT_TAIL(&file->open_requests, req, args.op.open.tailq); 769 if (file->ref_count == 1) { 770 assert(file->blob == NULL); 771 spdk_bs_md_open_blob(fs->bs, file->blobid, fs_open_blob_done, req); 772 } else if (file->blob != NULL) { 773 fs_open_blob_done(req, file->blob, 0); 774 } else { 775 /* 776 * The blob open for this file is in progress due to a previous 777 * open request. When that open completes, it will invoke the 778 * open callback for this request. 779 */ 780 } 781 } 782 783 void 784 spdk_fs_open_file_async(struct spdk_filesystem *fs, const char *name, uint32_t flags, 785 spdk_file_op_with_handle_complete cb_fn, void *cb_arg) 786 { 787 struct spdk_file *f = NULL; 788 struct spdk_fs_request *req; 789 struct spdk_fs_cb_args *args; 790 791 if (strnlen(name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 792 cb_fn(cb_arg, NULL, -ENAMETOOLONG); 793 return; 794 } 795 796 f = fs_find_file(fs, name); 797 if (f == NULL && !(flags & SPDK_BLOBFS_OPEN_CREATE)) { 798 cb_fn(cb_arg, NULL, -ENOENT); 799 return; 800 } 801 802 req = alloc_fs_request(fs->md_fs_channel); 803 if (req == NULL) { 804 cb_fn(cb_arg, NULL, -ENOMEM); 805 return; 806 } 807 808 args = &req->args; 809 args->fn.file_op_with_handle = cb_fn; 810 args->arg = cb_arg; 811 args->file = f; 812 args->fs = fs; 813 args->op.open.name = name; 814 815 if (f == NULL) { 816 spdk_fs_create_file_async(fs, name, fs_open_blob_create_cb, req); 817 } else { 818 fs_open_blob_create_cb(req, 0); 819 } 820 } 821 822 static void 823 __fs_open_file_done(void *arg, struct spdk_file *file, int bserrno) 824 { 825 struct spdk_fs_request *req = arg; 826 struct spdk_fs_cb_args *args = &req->args; 827 828 args->file = file; 829 args->rc = bserrno; 830 sem_post(args->sem); 831 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s\n", args->op.open.name); 832 } 833 834 static void 835 __fs_open_file(void *arg) 836 { 837 struct spdk_fs_request *req = arg; 838 struct spdk_fs_cb_args *args = &req->args; 839 840 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s\n", args->op.open.name); 841 spdk_fs_open_file_async(args->fs, args->op.open.name, args->op.open.flags, 842 __fs_open_file_done, req); 843 } 844 845 int 846 spdk_fs_open_file(struct spdk_filesystem *fs, struct spdk_io_channel *_channel, 847 const char *name, uint32_t flags, struct spdk_file **file) 848 { 849 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 850 struct spdk_fs_request *req; 851 struct spdk_fs_cb_args *args; 852 int rc; 853 854 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s\n", name); 855 856 req = alloc_fs_request(channel); 857 assert(req != NULL); 858 859 args = &req->args; 860 args->fs = fs; 861 args->op.open.name = name; 862 args->op.open.flags = flags; 863 args->sem = &channel->sem; 864 fs->send_request(__fs_open_file, req); 865 sem_wait(&channel->sem); 866 rc = args->rc; 867 if (rc == 0) { 868 *file = args->file; 869 } else { 870 *file = NULL; 871 } 872 free_fs_request(req); 873 874 return rc; 875 } 876 877 static void 878 fs_rename_blob_close_cb(void *ctx, int bserrno) 879 { 880 struct spdk_fs_request *req = ctx; 881 struct spdk_fs_cb_args *args = &req->args; 882 883 args->fn.fs_op(args->arg, bserrno); 884 free_fs_request(req); 885 } 886 887 static void 888 fs_rename_blob_open_cb(void *ctx, struct spdk_blob *blob, int bserrno) 889 { 890 struct spdk_fs_request *req = ctx; 891 struct spdk_fs_cb_args *args = &req->args; 892 struct spdk_file *f = args->file; 893 const char *new_name = args->op.rename.new_name; 894 895 f->blob = blob; 896 spdk_blob_md_set_xattr(blob, "name", new_name, strlen(new_name) + 1); 897 spdk_bs_md_close_blob(&f->blob, fs_rename_blob_close_cb, req); 898 } 899 900 static void 901 __spdk_fs_md_rename_file(struct spdk_fs_request *req) 902 { 903 struct spdk_fs_cb_args *args = &req->args; 904 struct spdk_file *f; 905 906 f = fs_find_file(args->fs, args->op.rename.old_name); 907 if (f == NULL) { 908 args->fn.fs_op(args->arg, -ENOENT); 909 free_fs_request(req); 910 return; 911 } 912 913 free(f->name); 914 f->name = strdup(args->op.rename.new_name); 915 args->file = f; 916 spdk_bs_md_open_blob(args->fs->bs, f->blobid, fs_rename_blob_open_cb, req); 917 } 918 919 static void 920 fs_rename_delete_done(void *arg, int fserrno) 921 { 922 __spdk_fs_md_rename_file(arg); 923 } 924 925 void 926 spdk_fs_rename_file_async(struct spdk_filesystem *fs, 927 const char *old_name, const char *new_name, 928 spdk_file_op_complete cb_fn, void *cb_arg) 929 { 930 struct spdk_file *f; 931 struct spdk_fs_request *req; 932 struct spdk_fs_cb_args *args; 933 934 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "old=%s new=%s\n", old_name, new_name); 935 if (strnlen(new_name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 936 cb_fn(cb_arg, -ENAMETOOLONG); 937 return; 938 } 939 940 req = alloc_fs_request(fs->md_fs_channel); 941 if (req == NULL) { 942 cb_fn(cb_arg, -ENOMEM); 943 return; 944 } 945 946 args = &req->args; 947 args->fn.fs_op = cb_fn; 948 args->fs = fs; 949 args->arg = cb_arg; 950 args->op.rename.old_name = old_name; 951 args->op.rename.new_name = new_name; 952 953 f = fs_find_file(fs, new_name); 954 if (f == NULL) { 955 __spdk_fs_md_rename_file(req); 956 return; 957 } 958 959 /* 960 * The rename overwrites an existing file. So delete the existing file, then 961 * do the actual rename. 962 */ 963 spdk_fs_delete_file_async(fs, new_name, fs_rename_delete_done, req); 964 } 965 966 static void 967 __fs_rename_file_done(void *arg, int fserrno) 968 { 969 struct spdk_fs_request *req = arg; 970 struct spdk_fs_cb_args *args = &req->args; 971 972 args->rc = fserrno; 973 sem_post(args->sem); 974 } 975 976 static void 977 __fs_rename_file(void *arg) 978 { 979 struct spdk_fs_request *req = arg; 980 struct spdk_fs_cb_args *args = &req->args; 981 982 spdk_fs_rename_file_async(args->fs, args->op.rename.old_name, args->op.rename.new_name, 983 __fs_rename_file_done, req); 984 } 985 986 int 987 spdk_fs_rename_file(struct spdk_filesystem *fs, struct spdk_io_channel *_channel, 988 const char *old_name, const char *new_name) 989 { 990 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 991 struct spdk_fs_request *req; 992 struct spdk_fs_cb_args *args; 993 int rc; 994 995 req = alloc_fs_request(channel); 996 assert(req != NULL); 997 998 args = &req->args; 999 1000 args->fs = fs; 1001 args->op.rename.old_name = old_name; 1002 args->op.rename.new_name = new_name; 1003 args->sem = &channel->sem; 1004 fs->send_request(__fs_rename_file, req); 1005 sem_wait(&channel->sem); 1006 rc = args->rc; 1007 free_fs_request(req); 1008 return rc; 1009 } 1010 1011 static void 1012 blob_delete_cb(void *ctx, int bserrno) 1013 { 1014 struct spdk_fs_request *req = ctx; 1015 struct spdk_fs_cb_args *args = &req->args; 1016 1017 args->fn.file_op(args->arg, bserrno); 1018 free_fs_request(req); 1019 } 1020 1021 void 1022 spdk_fs_delete_file_async(struct spdk_filesystem *fs, const char *name, 1023 spdk_file_op_complete cb_fn, void *cb_arg) 1024 { 1025 struct spdk_file *f; 1026 spdk_blob_id blobid; 1027 struct spdk_fs_request *req; 1028 struct spdk_fs_cb_args *args; 1029 1030 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s\n", name); 1031 1032 if (strnlen(name, SPDK_FILE_NAME_MAX + 1) == SPDK_FILE_NAME_MAX + 1) { 1033 cb_fn(cb_arg, -ENAMETOOLONG); 1034 return; 1035 } 1036 1037 f = fs_find_file(fs, name); 1038 if (f == NULL) { 1039 cb_fn(cb_arg, -ENOENT); 1040 return; 1041 } 1042 1043 if (f->ref_count > 0) { 1044 /* For now, do not allow deleting files with open references. */ 1045 cb_fn(cb_arg, -EBUSY); 1046 return; 1047 } 1048 1049 req = alloc_fs_request(fs->md_fs_channel); 1050 if (req == NULL) { 1051 cb_fn(cb_arg, -ENOMEM); 1052 return; 1053 } 1054 1055 TAILQ_REMOVE(&fs->files, f, tailq); 1056 1057 cache_free_buffers(f); 1058 1059 blobid = f->blobid; 1060 1061 free(f->name); 1062 free(f->tree); 1063 free(f); 1064 1065 args = &req->args; 1066 args->fn.file_op = cb_fn; 1067 args->arg = cb_arg; 1068 spdk_bs_md_delete_blob(fs->bs, blobid, blob_delete_cb, req); 1069 } 1070 1071 static void 1072 __fs_delete_file_done(void *arg, int fserrno) 1073 { 1074 struct spdk_fs_request *req = arg; 1075 struct spdk_fs_cb_args *args = &req->args; 1076 1077 args->rc = fserrno; 1078 sem_post(args->sem); 1079 } 1080 1081 static void 1082 __fs_delete_file(void *arg) 1083 { 1084 struct spdk_fs_request *req = arg; 1085 struct spdk_fs_cb_args *args = &req->args; 1086 1087 spdk_fs_delete_file_async(args->fs, args->op.delete.name, __fs_delete_file_done, req); 1088 } 1089 1090 int 1091 spdk_fs_delete_file(struct spdk_filesystem *fs, struct spdk_io_channel *_channel, 1092 const char *name) 1093 { 1094 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 1095 struct spdk_fs_request *req; 1096 struct spdk_fs_cb_args *args; 1097 int rc; 1098 1099 req = alloc_fs_request(channel); 1100 assert(req != NULL); 1101 1102 args = &req->args; 1103 args->fs = fs; 1104 args->op.delete.name = name; 1105 args->sem = &channel->sem; 1106 fs->send_request(__fs_delete_file, req); 1107 sem_wait(&channel->sem); 1108 rc = args->rc; 1109 free_fs_request(req); 1110 1111 return rc; 1112 } 1113 1114 spdk_fs_iter 1115 spdk_fs_iter_first(struct spdk_filesystem *fs) 1116 { 1117 struct spdk_file *f; 1118 1119 f = TAILQ_FIRST(&fs->files); 1120 return f; 1121 } 1122 1123 spdk_fs_iter 1124 spdk_fs_iter_next(spdk_fs_iter iter) 1125 { 1126 struct spdk_file *f = iter; 1127 1128 if (f == NULL) { 1129 return NULL; 1130 } 1131 1132 f = TAILQ_NEXT(f, tailq); 1133 return f; 1134 } 1135 1136 const char * 1137 spdk_file_get_name(struct spdk_file *file) 1138 { 1139 return file->name; 1140 } 1141 1142 uint64_t 1143 spdk_file_get_length(struct spdk_file *file) 1144 { 1145 assert(file != NULL); 1146 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s length=0x%jx\n", file->name, file->length); 1147 return file->length; 1148 } 1149 1150 static void 1151 fs_truncate_complete_cb(void *ctx, int bserrno) 1152 { 1153 struct spdk_fs_request *req = ctx; 1154 struct spdk_fs_cb_args *args = &req->args; 1155 1156 args->fn.file_op(args->arg, bserrno); 1157 free_fs_request(req); 1158 } 1159 1160 static uint64_t 1161 __bytes_to_clusters(uint64_t length, uint64_t cluster_sz) 1162 { 1163 return (length + cluster_sz - 1) / cluster_sz; 1164 } 1165 1166 void 1167 spdk_file_truncate_async(struct spdk_file *file, uint64_t length, 1168 spdk_file_op_complete cb_fn, void *cb_arg) 1169 { 1170 struct spdk_filesystem *fs; 1171 size_t num_clusters; 1172 struct spdk_fs_request *req; 1173 struct spdk_fs_cb_args *args; 1174 1175 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s old=0x%jx new=0x%jx\n", file->name, file->length, length); 1176 if (length == file->length) { 1177 cb_fn(cb_arg, 0); 1178 return; 1179 } 1180 1181 req = alloc_fs_request(file->fs->md_fs_channel); 1182 if (req == NULL) { 1183 cb_fn(cb_arg, -ENOMEM); 1184 return; 1185 } 1186 1187 args = &req->args; 1188 args->fn.file_op = cb_fn; 1189 args->arg = cb_arg; 1190 args->file = file; 1191 fs = file->fs; 1192 1193 num_clusters = __bytes_to_clusters(length, fs->bs_opts.cluster_sz); 1194 1195 spdk_bs_md_resize_blob(file->blob, num_clusters); 1196 spdk_blob_md_set_xattr(file->blob, "length", &length, sizeof(length)); 1197 1198 file->length = length; 1199 if (file->append_pos > file->length) { 1200 file->append_pos = file->length; 1201 } 1202 1203 spdk_bs_md_sync_blob(file->blob, fs_truncate_complete_cb, args); 1204 } 1205 1206 static void 1207 __truncate(void *arg) 1208 { 1209 struct spdk_fs_request *req = arg; 1210 struct spdk_fs_cb_args *args = &req->args; 1211 1212 spdk_file_truncate_async(args->file, args->op.truncate.length, 1213 args->fn.file_op, args->arg); 1214 } 1215 1216 void 1217 spdk_file_truncate(struct spdk_file *file, struct spdk_io_channel *_channel, 1218 uint64_t length) 1219 { 1220 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 1221 struct spdk_fs_request *req; 1222 struct spdk_fs_cb_args *args; 1223 1224 req = alloc_fs_request(channel); 1225 assert(req != NULL); 1226 1227 args = &req->args; 1228 1229 args->file = file; 1230 args->op.truncate.length = length; 1231 args->fn.file_op = __sem_post; 1232 args->arg = &channel->sem; 1233 1234 channel->send_request(__truncate, req); 1235 sem_wait(&channel->sem); 1236 free_fs_request(req); 1237 } 1238 1239 static void 1240 __rw_done(void *ctx, int bserrno) 1241 { 1242 struct spdk_fs_request *req = ctx; 1243 struct spdk_fs_cb_args *args = &req->args; 1244 1245 spdk_free(args->op.rw.pin_buf); 1246 args->fn.file_op(args->arg, bserrno); 1247 free_fs_request(req); 1248 } 1249 1250 static void 1251 __read_done(void *ctx, int bserrno) 1252 { 1253 struct spdk_fs_request *req = ctx; 1254 struct spdk_fs_cb_args *args = &req->args; 1255 1256 if (args->op.rw.is_read) { 1257 memcpy(args->op.rw.user_buf, 1258 args->op.rw.pin_buf + (args->op.rw.offset & 0xFFF), 1259 args->op.rw.length); 1260 __rw_done(req, 0); 1261 } else { 1262 memcpy(args->op.rw.pin_buf + (args->op.rw.offset & 0xFFF), 1263 args->op.rw.user_buf, 1264 args->op.rw.length); 1265 spdk_bs_io_write_blob(args->file->blob, args->op.rw.channel, 1266 args->op.rw.pin_buf, 1267 args->op.rw.start_page, args->op.rw.num_pages, 1268 __rw_done, req); 1269 } 1270 } 1271 1272 static void 1273 __do_blob_read(void *ctx, int fserrno) 1274 { 1275 struct spdk_fs_request *req = ctx; 1276 struct spdk_fs_cb_args *args = &req->args; 1277 1278 spdk_bs_io_read_blob(args->file->blob, args->op.rw.channel, 1279 args->op.rw.pin_buf, 1280 args->op.rw.start_page, args->op.rw.num_pages, 1281 __read_done, req); 1282 } 1283 1284 static void 1285 __get_page_parameters(struct spdk_file *file, uint64_t offset, uint64_t length, 1286 uint64_t *start_page, uint32_t *page_size, uint64_t *num_pages) 1287 { 1288 uint64_t end_page; 1289 1290 *page_size = spdk_bs_get_page_size(file->fs->bs); 1291 *start_page = offset / *page_size; 1292 end_page = (offset + length - 1) / *page_size; 1293 *num_pages = (end_page - *start_page + 1); 1294 } 1295 1296 static void 1297 __readwrite(struct spdk_file *file, struct spdk_io_channel *_channel, 1298 void *payload, uint64_t offset, uint64_t length, 1299 spdk_file_op_complete cb_fn, void *cb_arg, int is_read) 1300 { 1301 struct spdk_fs_request *req; 1302 struct spdk_fs_cb_args *args; 1303 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 1304 uint64_t start_page, num_pages, pin_buf_length; 1305 uint32_t page_size; 1306 1307 if (is_read && offset + length > file->length) { 1308 cb_fn(cb_arg, -EINVAL); 1309 return; 1310 } 1311 1312 req = alloc_fs_request(channel); 1313 if (req == NULL) { 1314 cb_fn(cb_arg, -ENOMEM); 1315 return; 1316 } 1317 1318 args = &req->args; 1319 args->fn.file_op = cb_fn; 1320 args->arg = cb_arg; 1321 args->file = file; 1322 args->op.rw.channel = channel->bs_channel; 1323 args->op.rw.user_buf = payload; 1324 args->op.rw.is_read = is_read; 1325 args->op.rw.offset = offset; 1326 args->op.rw.length = length; 1327 1328 __get_page_parameters(file, offset, length, &start_page, &page_size, &num_pages); 1329 pin_buf_length = num_pages * page_size; 1330 args->op.rw.pin_buf = spdk_malloc(pin_buf_length, 4096, NULL); 1331 1332 args->op.rw.start_page = start_page; 1333 args->op.rw.num_pages = num_pages; 1334 1335 if (!is_read && file->length < offset + length) { 1336 spdk_file_truncate_async(file, offset + length, __do_blob_read, req); 1337 } else { 1338 __do_blob_read(req, 0); 1339 } 1340 } 1341 1342 void 1343 spdk_file_write_async(struct spdk_file *file, struct spdk_io_channel *channel, 1344 void *payload, uint64_t offset, uint64_t length, 1345 spdk_file_op_complete cb_fn, void *cb_arg) 1346 { 1347 __readwrite(file, channel, payload, offset, length, cb_fn, cb_arg, 0); 1348 } 1349 1350 void 1351 spdk_file_read_async(struct spdk_file *file, struct spdk_io_channel *channel, 1352 void *payload, uint64_t offset, uint64_t length, 1353 spdk_file_op_complete cb_fn, void *cb_arg) 1354 { 1355 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "file=%s offset=%jx length=%jx\n", 1356 file->name, offset, length); 1357 __readwrite(file, channel, payload, offset, length, cb_fn, cb_arg, 1); 1358 } 1359 1360 struct spdk_io_channel * 1361 spdk_fs_alloc_io_channel(struct spdk_filesystem *fs, uint32_t priority) 1362 { 1363 struct spdk_io_channel *io_channel; 1364 struct spdk_fs_channel *fs_channel; 1365 uint32_t max_ops = 512; 1366 1367 io_channel = spdk_get_io_channel(fs, priority, true, (void *)&max_ops); 1368 fs_channel = spdk_io_channel_get_ctx(io_channel); 1369 fs_channel->bs_channel = spdk_bs_alloc_io_channel(fs->bs, SPDK_IO_PRIORITY_DEFAULT, 512); 1370 fs_channel->send_request = __send_request_direct; 1371 1372 return io_channel; 1373 } 1374 1375 struct spdk_io_channel * 1376 spdk_fs_alloc_io_channel_sync(struct spdk_filesystem *fs, uint32_t priority) 1377 { 1378 struct spdk_io_channel *io_channel; 1379 struct spdk_fs_channel *fs_channel; 1380 uint32_t max_ops = 16; 1381 1382 io_channel = spdk_get_io_channel(fs, priority, true, (void *)&max_ops); 1383 fs_channel = spdk_io_channel_get_ctx(io_channel); 1384 fs_channel->send_request = fs->send_request; 1385 1386 return io_channel; 1387 } 1388 1389 void 1390 spdk_fs_free_io_channel(struct spdk_io_channel *channel) 1391 { 1392 spdk_put_io_channel(channel); 1393 } 1394 1395 void 1396 spdk_fs_set_cache_size(uint64_t size_in_mb) 1397 { 1398 g_fs_cache_size = size_in_mb * 1024 * 1024; 1399 } 1400 1401 uint64_t 1402 spdk_fs_get_cache_size(void) 1403 { 1404 return g_fs_cache_size / (1024 * 1024); 1405 } 1406 1407 static void __file_flush(void *_args); 1408 1409 static void * 1410 alloc_cache_memory_buffer(struct spdk_file *context) 1411 { 1412 struct spdk_file *file; 1413 void *buf; 1414 1415 buf = spdk_mempool_get(g_cache_pool); 1416 if (buf != NULL) { 1417 return buf; 1418 } 1419 1420 pthread_spin_lock(&g_caches_lock); 1421 TAILQ_FOREACH(file, &g_caches, cache_tailq) { 1422 if (!file->open_for_writing && 1423 file->priority == SPDK_FILE_PRIORITY_LOW && 1424 file != context) { 1425 TAILQ_REMOVE(&g_caches, file, cache_tailq); 1426 TAILQ_INSERT_TAIL(&g_caches, file, cache_tailq); 1427 break; 1428 } 1429 } 1430 pthread_spin_unlock(&g_caches_lock); 1431 if (file != NULL) { 1432 cache_free_buffers(file); 1433 buf = spdk_mempool_get(g_cache_pool); 1434 if (buf != NULL) { 1435 return buf; 1436 } 1437 } 1438 1439 pthread_spin_lock(&g_caches_lock); 1440 TAILQ_FOREACH(file, &g_caches, cache_tailq) { 1441 if (!file->open_for_writing && file != context) { 1442 TAILQ_REMOVE(&g_caches, file, cache_tailq); 1443 TAILQ_INSERT_TAIL(&g_caches, file, cache_tailq); 1444 break; 1445 } 1446 } 1447 pthread_spin_unlock(&g_caches_lock); 1448 if (file != NULL) { 1449 cache_free_buffers(file); 1450 buf = spdk_mempool_get(g_cache_pool); 1451 if (buf != NULL) { 1452 return buf; 1453 } 1454 } 1455 1456 pthread_spin_lock(&g_caches_lock); 1457 TAILQ_FOREACH(file, &g_caches, cache_tailq) { 1458 if (file != context) { 1459 TAILQ_REMOVE(&g_caches, file, cache_tailq); 1460 TAILQ_INSERT_TAIL(&g_caches, file, cache_tailq); 1461 break; 1462 } 1463 } 1464 pthread_spin_unlock(&g_caches_lock); 1465 if (file != NULL) { 1466 cache_free_buffers(file); 1467 buf = spdk_mempool_get(g_cache_pool); 1468 if (buf != NULL) { 1469 return buf; 1470 } 1471 } 1472 1473 assert(false); 1474 return NULL; 1475 } 1476 1477 static struct cache_buffer * 1478 cache_insert_buffer(struct spdk_file *file, uint64_t offset) 1479 { 1480 struct cache_buffer *buf; 1481 int count = 0; 1482 1483 buf = calloc(1, sizeof(*buf)); 1484 if (buf == NULL) { 1485 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "calloc failed\n"); 1486 return NULL; 1487 } 1488 1489 buf->buf = alloc_cache_memory_buffer(file); 1490 if (buf->buf == NULL) { 1491 while (buf->buf == NULL) { 1492 count++; 1493 buf->buf = alloc_cache_memory_buffer(file); 1494 /* 1495 * TODO: __free_oldest_cache() should eventually free some buffers. 1496 * Should have a more sophisticated check here, instead of just 1497 * bailing if 100 tries does not result in getting a free buffer. 1498 */ 1499 if (count == 100) { 1500 SPDK_ERRLOG("could not allocate cache buffer\n"); 1501 assert(false); 1502 return NULL; 1503 } 1504 } 1505 } 1506 1507 buf->buf_size = CACHE_BUFFER_SIZE; 1508 buf->offset = offset; 1509 1510 pthread_spin_lock(&g_caches_lock); 1511 if (file->tree->present_mask == 0) { 1512 TAILQ_INSERT_TAIL(&g_caches, file, cache_tailq); 1513 } 1514 file->tree = spdk_tree_insert_buffer(file->tree, buf); 1515 pthread_spin_unlock(&g_caches_lock); 1516 1517 return buf; 1518 } 1519 1520 static struct cache_buffer * 1521 cache_append_buffer(struct spdk_file *file) 1522 { 1523 struct cache_buffer *last; 1524 1525 assert(file->last == NULL || file->last->bytes_filled == file->last->buf_size); 1526 assert((file->append_pos % CACHE_BUFFER_SIZE) == 0); 1527 1528 last = cache_insert_buffer(file, file->append_pos); 1529 if (last == NULL) { 1530 SPDK_TRACELOG(SPDK_TRACE_BLOBFS, "cache_insert_buffer failed\n"); 1531 return NULL; 1532 } 1533 1534 if (file->last != NULL) { 1535 file->last->next = last; 1536 } 1537 file->last = last; 1538 1539 return last; 1540 } 1541 1542 static void 1543 __wake_caller(struct spdk_fs_cb_args *args) 1544 { 1545 sem_post(args->sem); 1546 } 1547 1548 static void 1549 __file_cache_finish_sync(struct spdk_file *file) 1550 { 1551 struct spdk_fs_request *sync_req; 1552 struct spdk_fs_cb_args *sync_args; 1553 1554 pthread_spin_lock(&file->lock); 1555 while (!TAILQ_EMPTY(&file->sync_requests)) { 1556 sync_req = TAILQ_FIRST(&file->sync_requests); 1557 sync_args = &sync_req->args; 1558 if (sync_args->op.sync.offset > file->length_flushed) { 1559 break; 1560 } 1561 BLOBFS_TRACE(file, "sync done offset=%jx\n", sync_args->op.sync.offset); 1562 TAILQ_REMOVE(&file->sync_requests, sync_req, args.op.sync.tailq); 1563 pthread_spin_unlock(&file->lock); 1564 sync_args->fn.file_op(sync_args->arg, 0); 1565 pthread_spin_lock(&file->lock); 1566 free_fs_request(sync_req); 1567 } 1568 pthread_spin_unlock(&file->lock); 1569 } 1570 1571 static void 1572 __file_cache_finish_sync_bs_cb(void *ctx, int bserrno) 1573 { 1574 struct spdk_file *file = ctx; 1575 1576 __file_cache_finish_sync(file); 1577 } 1578 1579 static void 1580 __free_args(struct spdk_fs_cb_args *args) 1581 { 1582 struct spdk_fs_request *req; 1583 1584 if (!args->from_request) { 1585 free(args); 1586 } else { 1587 /* Depends on args being at the start of the spdk_fs_request structure. */ 1588 req = (struct spdk_fs_request *)args; 1589 free_fs_request(req); 1590 } 1591 } 1592 1593 static void 1594 __file_flush_done(void *arg, int bserrno) 1595 { 1596 struct spdk_fs_cb_args *args = arg; 1597 struct spdk_fs_request *sync_req; 1598 struct spdk_file *file = args->file; 1599 struct cache_buffer *next = args->op.flush.cache_buffer; 1600 1601 BLOBFS_TRACE(file, "length=%jx\n", args->op.flush.length); 1602 1603 pthread_spin_lock(&file->lock); 1604 next->in_progress = false; 1605 next->bytes_flushed += args->op.flush.length; 1606 file->length_flushed += args->op.flush.length; 1607 if (file->length_flushed > file->length) { 1608 file->length = file->length_flushed; 1609 } 1610 if (next->bytes_flushed == next->buf_size) { 1611 BLOBFS_TRACE(file, "write buffer fully flushed 0x%jx\n", file->length_flushed); 1612 next = spdk_tree_find_buffer(file->tree, file->length_flushed); 1613 } 1614 1615 TAILQ_FOREACH_REVERSE(sync_req, &file->sync_requests, sync_requests_head, args.op.sync.tailq) { 1616 if (sync_req->args.op.sync.offset <= file->length_flushed) { 1617 break; 1618 } 1619 } 1620 1621 if (sync_req != NULL) { 1622 BLOBFS_TRACE(file, "set xattr length 0x%jx\n", file->length_flushed); 1623 spdk_blob_md_set_xattr(file->blob, "length", &file->length_flushed, 1624 sizeof(file->length_flushed)); 1625 1626 pthread_spin_unlock(&file->lock); 1627 spdk_bs_md_sync_blob(file->blob, __file_cache_finish_sync_bs_cb, file); 1628 } else { 1629 pthread_spin_unlock(&file->lock); 1630 __file_cache_finish_sync(file); 1631 } 1632 1633 /* 1634 * Assert that there is no cached data that extends past the end of the underlying 1635 * blob. 1636 */ 1637 assert(next == NULL || next->offset < __file_get_blob_size(file) || 1638 next->bytes_filled == 0); 1639 1640 __file_flush(args); 1641 } 1642 1643 static void 1644 __file_flush(void *_args) 1645 { 1646 struct spdk_fs_cb_args *args = _args; 1647 struct spdk_file *file = args->file; 1648 struct cache_buffer *next; 1649 uint64_t offset, length, start_page, num_pages; 1650 uint32_t page_size; 1651 1652 pthread_spin_lock(&file->lock); 1653 next = spdk_tree_find_buffer(file->tree, file->length_flushed); 1654 if (next == NULL || next->in_progress) { 1655 /* 1656 * There is either no data to flush, or a flush I/O is already in 1657 * progress. So return immediately - if a flush I/O is in 1658 * progress we will flush more data after that is completed. 1659 */ 1660 __free_args(args); 1661 pthread_spin_unlock(&file->lock); 1662 return; 1663 } 1664 1665 offset = next->offset + next->bytes_flushed; 1666 length = next->bytes_filled - next->bytes_flushed; 1667 if (length == 0) { 1668 __free_args(args); 1669 pthread_spin_unlock(&file->lock); 1670 return; 1671 } 1672 args->op.flush.length = length; 1673 args->op.flush.cache_buffer = next; 1674 1675 __get_page_parameters(file, offset, length, &start_page, &page_size, &num_pages); 1676 1677 next->in_progress = true; 1678 BLOBFS_TRACE(file, "offset=%jx length=%jx page start=%jx num=%jx\n", 1679 offset, length, start_page, num_pages); 1680 pthread_spin_unlock(&file->lock); 1681 spdk_bs_io_write_blob(file->blob, file->fs->sync_fs_channel->bs_channel, 1682 next->buf + (start_page * page_size) - next->offset, 1683 start_page, num_pages, 1684 __file_flush_done, args); 1685 } 1686 1687 static void 1688 __file_extend_done(void *arg, int bserrno) 1689 { 1690 struct spdk_fs_cb_args *args = arg; 1691 1692 __wake_caller(args); 1693 } 1694 1695 static void 1696 __file_extend_blob(void *_args) 1697 { 1698 struct spdk_fs_cb_args *args = _args; 1699 struct spdk_file *file = args->file; 1700 1701 spdk_bs_md_resize_blob(file->blob, args->op.resize.num_clusters); 1702 1703 spdk_bs_md_sync_blob(file->blob, __file_extend_done, args); 1704 } 1705 1706 static void 1707 __rw_from_file_done(void *arg, int bserrno) 1708 { 1709 struct spdk_fs_cb_args *args = arg; 1710 1711 __wake_caller(args); 1712 __free_args(args); 1713 } 1714 1715 static void 1716 __rw_from_file(void *_args) 1717 { 1718 struct spdk_fs_cb_args *args = _args; 1719 struct spdk_file *file = args->file; 1720 1721 if (args->op.rw.is_read) { 1722 spdk_file_read_async(file, file->fs->sync_io_channel, args->op.rw.user_buf, 1723 args->op.rw.offset, args->op.rw.length, 1724 __rw_from_file_done, args); 1725 } else { 1726 spdk_file_write_async(file, file->fs->sync_io_channel, args->op.rw.user_buf, 1727 args->op.rw.offset, args->op.rw.length, 1728 __rw_from_file_done, args); 1729 } 1730 } 1731 1732 static int 1733 __send_rw_from_file(struct spdk_file *file, sem_t *sem, void *payload, 1734 uint64_t offset, uint64_t length, bool is_read) 1735 { 1736 struct spdk_fs_cb_args *args; 1737 1738 args = calloc(1, sizeof(*args)); 1739 if (args == NULL) { 1740 sem_post(sem); 1741 return -ENOMEM; 1742 } 1743 1744 args->file = file; 1745 args->sem = sem; 1746 args->op.rw.user_buf = payload; 1747 args->op.rw.offset = offset; 1748 args->op.rw.length = length; 1749 args->op.rw.is_read = is_read; 1750 file->fs->send_request(__rw_from_file, args); 1751 return 0; 1752 } 1753 1754 int 1755 spdk_file_write(struct spdk_file *file, struct spdk_io_channel *_channel, 1756 void *payload, uint64_t offset, uint64_t length) 1757 { 1758 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 1759 struct spdk_fs_cb_args *args; 1760 uint64_t rem_length, copy, blob_size, cluster_sz; 1761 uint32_t cache_buffers_filled = 0; 1762 uint8_t *cur_payload; 1763 struct cache_buffer *last; 1764 1765 BLOBFS_TRACE_RW(file, "offset=%jx length=%jx\n", offset, length); 1766 1767 if (length == 0) { 1768 return 0; 1769 } 1770 1771 if (offset != file->append_pos) { 1772 BLOBFS_TRACE(file, " error offset=%jx append_pos=%jx\n", offset, file->append_pos); 1773 return -EINVAL; 1774 } 1775 1776 pthread_spin_lock(&file->lock); 1777 file->open_for_writing = true; 1778 1779 if (file->last == NULL) { 1780 if (file->append_pos % CACHE_BUFFER_SIZE == 0) { 1781 cache_append_buffer(file); 1782 } else { 1783 int rc; 1784 1785 file->append_pos += length; 1786 rc = __send_rw_from_file(file, &channel->sem, payload, 1787 offset, length, false); 1788 pthread_spin_unlock(&file->lock); 1789 sem_wait(&channel->sem); 1790 return rc; 1791 } 1792 } 1793 1794 blob_size = __file_get_blob_size(file); 1795 1796 if ((offset + length) > blob_size) { 1797 struct spdk_fs_cb_args extend_args = {}; 1798 1799 cluster_sz = file->fs->bs_opts.cluster_sz; 1800 extend_args.sem = &channel->sem; 1801 extend_args.op.resize.num_clusters = __bytes_to_clusters((offset + length), cluster_sz); 1802 extend_args.file = file; 1803 BLOBFS_TRACE(file, "start resize to %u clusters\n", extend_args.op.resize.num_clusters); 1804 pthread_spin_unlock(&file->lock); 1805 file->fs->send_request(__file_extend_blob, &extend_args); 1806 sem_wait(&channel->sem); 1807 } 1808 1809 last = file->last; 1810 rem_length = length; 1811 cur_payload = payload; 1812 while (rem_length > 0) { 1813 copy = last->buf_size - last->bytes_filled; 1814 if (copy > rem_length) { 1815 copy = rem_length; 1816 } 1817 BLOBFS_TRACE_RW(file, " fill offset=%jx length=%jx\n", file->append_pos, copy); 1818 memcpy(&last->buf[last->bytes_filled], cur_payload, copy); 1819 file->append_pos += copy; 1820 if (file->length < file->append_pos) { 1821 file->length = file->append_pos; 1822 } 1823 cur_payload += copy; 1824 last->bytes_filled += copy; 1825 rem_length -= copy; 1826 if (last->bytes_filled == last->buf_size) { 1827 cache_buffers_filled++; 1828 last = cache_append_buffer(file); 1829 if (last == NULL) { 1830 BLOBFS_TRACE(file, "nomem\n"); 1831 pthread_spin_unlock(&file->lock); 1832 return -ENOMEM; 1833 } 1834 } 1835 } 1836 1837 if (cache_buffers_filled == 0) { 1838 pthread_spin_unlock(&file->lock); 1839 return 0; 1840 } 1841 1842 args = calloc(1, sizeof(*args)); 1843 if (args == NULL) { 1844 pthread_spin_unlock(&file->lock); 1845 return -ENOMEM; 1846 } 1847 1848 args->file = file; 1849 file->fs->send_request(__file_flush, args); 1850 pthread_spin_unlock(&file->lock); 1851 return 0; 1852 } 1853 1854 static void 1855 __readahead_done(void *arg, int bserrno) 1856 { 1857 struct spdk_fs_cb_args *args = arg; 1858 struct cache_buffer *cache_buffer = args->op.readahead.cache_buffer; 1859 struct spdk_file *file = args->file; 1860 1861 BLOBFS_TRACE(file, "offset=%jx\n", cache_buffer->offset); 1862 1863 pthread_spin_lock(&file->lock); 1864 cache_buffer->bytes_filled = args->op.readahead.length; 1865 cache_buffer->bytes_flushed = args->op.readahead.length; 1866 cache_buffer->in_progress = false; 1867 pthread_spin_unlock(&file->lock); 1868 1869 __free_args(args); 1870 } 1871 1872 static void 1873 __readahead(void *_args) 1874 { 1875 struct spdk_fs_cb_args *args = _args; 1876 struct spdk_file *file = args->file; 1877 uint64_t offset, length, start_page, num_pages; 1878 uint32_t page_size; 1879 1880 offset = args->op.readahead.offset; 1881 length = args->op.readahead.length; 1882 assert(length > 0); 1883 1884 __get_page_parameters(file, offset, length, &start_page, &page_size, &num_pages); 1885 1886 BLOBFS_TRACE(file, "offset=%jx length=%jx page start=%jx num=%jx\n", 1887 offset, length, start_page, num_pages); 1888 spdk_bs_io_read_blob(file->blob, file->fs->sync_fs_channel->bs_channel, 1889 args->op.readahead.cache_buffer->buf, 1890 start_page, num_pages, 1891 __readahead_done, args); 1892 } 1893 1894 static uint64_t 1895 __next_cache_buffer_offset(uint64_t offset) 1896 { 1897 return (offset + CACHE_BUFFER_SIZE) & ~(CACHE_TREE_LEVEL_MASK(0)); 1898 } 1899 1900 static void 1901 check_readahead(struct spdk_file *file, uint64_t offset) 1902 { 1903 struct spdk_fs_cb_args *args; 1904 1905 offset = __next_cache_buffer_offset(offset); 1906 if (spdk_tree_find_buffer(file->tree, offset) != NULL || file->length <= offset) { 1907 return; 1908 } 1909 1910 BLOBFS_TRACE(file, "offset=%jx\n", offset); 1911 args = calloc(1, sizeof(*args)); 1912 args->file = file; 1913 args->op.readahead.offset = offset; 1914 args->op.readahead.cache_buffer = cache_insert_buffer(file, offset); 1915 args->op.readahead.cache_buffer->in_progress = true; 1916 if (file->length < (offset + CACHE_BUFFER_SIZE)) { 1917 args->op.readahead.length = file->length & (CACHE_BUFFER_SIZE - 1); 1918 } else { 1919 args->op.readahead.length = CACHE_BUFFER_SIZE; 1920 } 1921 file->fs->send_request(__readahead, args); 1922 } 1923 1924 static int 1925 __file_read(struct spdk_file *file, void *payload, uint64_t offset, uint64_t length, sem_t *sem) 1926 { 1927 struct cache_buffer *buf; 1928 1929 buf = spdk_tree_find_filled_buffer(file->tree, offset); 1930 if (buf == NULL) { 1931 return __send_rw_from_file(file, sem, payload, offset, length, true); 1932 } 1933 1934 if ((offset + length) > (buf->offset + buf->bytes_filled)) { 1935 length = buf->offset + buf->bytes_filled - offset; 1936 } 1937 BLOBFS_TRACE(file, "read %p offset=%ju length=%ju\n", payload, offset, length); 1938 memcpy(payload, &buf->buf[offset - buf->offset], length); 1939 if ((offset + length) % CACHE_BUFFER_SIZE == 0) { 1940 pthread_spin_lock(&g_caches_lock); 1941 spdk_tree_remove_buffer(file->tree, buf); 1942 if (file->tree->present_mask == 0) { 1943 TAILQ_REMOVE(&g_caches, file, cache_tailq); 1944 } 1945 pthread_spin_unlock(&g_caches_lock); 1946 } 1947 1948 sem_post(sem); 1949 return 0; 1950 } 1951 1952 int64_t 1953 spdk_file_read(struct spdk_file *file, struct spdk_io_channel *_channel, 1954 void *payload, uint64_t offset, uint64_t length) 1955 { 1956 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 1957 uint64_t final_offset, final_length; 1958 uint32_t sub_reads = 0; 1959 int rc = 0; 1960 1961 pthread_spin_lock(&file->lock); 1962 1963 BLOBFS_TRACE_RW(file, "offset=%ju length=%ju\n", offset, length); 1964 1965 file->open_for_writing = false; 1966 1967 if (length == 0 || offset >= file->length) { 1968 pthread_spin_unlock(&file->lock); 1969 return 0; 1970 } 1971 1972 if (offset + length > file->length) { 1973 length = file->length - offset; 1974 } 1975 1976 if (offset != file->next_seq_offset) { 1977 file->seq_byte_count = 0; 1978 } 1979 file->seq_byte_count += length; 1980 file->next_seq_offset = offset + length; 1981 if (file->seq_byte_count >= CACHE_READAHEAD_THRESHOLD) { 1982 check_readahead(file, offset); 1983 check_readahead(file, offset + CACHE_BUFFER_SIZE); 1984 } 1985 1986 final_length = 0; 1987 final_offset = offset + length; 1988 while (offset < final_offset) { 1989 length = NEXT_CACHE_BUFFER_OFFSET(offset) - offset; 1990 if (length > (final_offset - offset)) { 1991 length = final_offset - offset; 1992 } 1993 rc = __file_read(file, payload, offset, length, &channel->sem); 1994 if (rc == 0) { 1995 final_length += length; 1996 } else { 1997 break; 1998 } 1999 payload += length; 2000 offset += length; 2001 sub_reads++; 2002 } 2003 pthread_spin_unlock(&file->lock); 2004 while (sub_reads-- > 0) { 2005 sem_wait(&channel->sem); 2006 } 2007 if (rc == 0) { 2008 return final_length; 2009 } else { 2010 return rc; 2011 } 2012 } 2013 2014 static void 2015 _file_sync(struct spdk_file *file, struct spdk_fs_channel *channel, 2016 spdk_file_op_complete cb_fn, void *cb_arg) 2017 { 2018 struct spdk_fs_request *sync_req; 2019 struct spdk_fs_request *flush_req; 2020 struct spdk_fs_cb_args *sync_args; 2021 struct spdk_fs_cb_args *flush_args; 2022 2023 BLOBFS_TRACE(file, "offset=%jx\n", file->append_pos); 2024 2025 pthread_spin_lock(&file->lock); 2026 if (file->append_pos <= file->length_flushed || file->last == NULL) { 2027 BLOBFS_TRACE(file, "done - no data to flush\n"); 2028 pthread_spin_unlock(&file->lock); 2029 cb_fn(cb_arg, 0); 2030 return; 2031 } 2032 2033 sync_req = alloc_fs_request(channel); 2034 assert(sync_req != NULL); 2035 sync_args = &sync_req->args; 2036 2037 flush_req = alloc_fs_request(channel); 2038 assert(flush_req != NULL); 2039 flush_args = &flush_req->args; 2040 2041 sync_args->file = file; 2042 sync_args->fn.file_op = cb_fn; 2043 sync_args->arg = cb_arg; 2044 sync_args->op.sync.offset = file->append_pos; 2045 TAILQ_INSERT_TAIL(&file->sync_requests, sync_req, args.op.sync.tailq); 2046 pthread_spin_unlock(&file->lock); 2047 2048 flush_args->file = file; 2049 channel->send_request(__file_flush, flush_args); 2050 } 2051 2052 int 2053 spdk_file_sync(struct spdk_file *file, struct spdk_io_channel *_channel) 2054 { 2055 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 2056 2057 _file_sync(file, channel, __sem_post, &channel->sem); 2058 sem_wait(&channel->sem); 2059 2060 return 0; 2061 } 2062 2063 void 2064 spdk_file_sync_async(struct spdk_file *file, struct spdk_io_channel *_channel, 2065 spdk_file_op_complete cb_fn, void *cb_arg) 2066 { 2067 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 2068 2069 _file_sync(file, channel, cb_fn, cb_arg); 2070 } 2071 2072 void 2073 spdk_file_set_priority(struct spdk_file *file, uint32_t priority) 2074 { 2075 BLOBFS_TRACE(file, "priority=%u\n", priority); 2076 file->priority = priority; 2077 2078 } 2079 2080 /* 2081 * Close routines 2082 */ 2083 2084 static void 2085 __file_close_async_done(void *ctx, int bserrno) 2086 { 2087 struct spdk_fs_request *req = ctx; 2088 struct spdk_fs_cb_args *args = &req->args; 2089 2090 args->fn.file_op(args->arg, bserrno); 2091 free_fs_request(req); 2092 } 2093 2094 static void 2095 __file_close_async(struct spdk_file *file, struct spdk_fs_request *req) 2096 { 2097 pthread_spin_lock(&file->lock); 2098 if (file->ref_count == 0) { 2099 pthread_spin_unlock(&file->lock); 2100 __file_close_async_done(req, -EBADF); 2101 return; 2102 } 2103 2104 file->ref_count--; 2105 if (file->ref_count > 0) { 2106 pthread_spin_unlock(&file->lock); 2107 __file_close_async_done(req, 0); 2108 return; 2109 } 2110 2111 pthread_spin_unlock(&file->lock); 2112 2113 spdk_bs_md_close_blob(&file->blob, __file_close_async_done, req); 2114 } 2115 2116 static void 2117 __file_close_async__sync_done(void *arg, int fserrno) 2118 { 2119 struct spdk_fs_request *req = arg; 2120 struct spdk_fs_cb_args *args = &req->args; 2121 2122 __file_close_async(args->file, req); 2123 } 2124 2125 void 2126 spdk_file_close_async(struct spdk_file *file, spdk_file_op_complete cb_fn, void *cb_arg) 2127 { 2128 struct spdk_fs_request *req; 2129 struct spdk_fs_cb_args *args; 2130 2131 req = alloc_fs_request(file->fs->md_fs_channel); 2132 if (req == NULL) { 2133 cb_fn(cb_arg, -ENOMEM); 2134 return; 2135 } 2136 2137 args = &req->args; 2138 args->file = file; 2139 args->fn.file_op = cb_fn; 2140 args->arg = cb_arg; 2141 2142 spdk_file_sync_async(file, file->fs->md_io_channel, __file_close_async__sync_done, req); 2143 } 2144 2145 static void 2146 __file_close_done(void *arg, int fserrno) 2147 { 2148 struct spdk_fs_cb_args *args = arg; 2149 2150 args->rc = fserrno; 2151 sem_post(args->sem); 2152 } 2153 2154 static void 2155 __file_close(void *arg) 2156 { 2157 struct spdk_fs_request *req = arg; 2158 struct spdk_fs_cb_args *args = &req->args; 2159 struct spdk_file *file = args->file; 2160 2161 __file_close_async(file, req); 2162 } 2163 2164 int 2165 spdk_file_close(struct spdk_file *file, struct spdk_io_channel *_channel) 2166 { 2167 struct spdk_fs_channel *channel = spdk_io_channel_get_ctx(_channel); 2168 struct spdk_fs_request *req; 2169 struct spdk_fs_cb_args *args; 2170 2171 req = alloc_fs_request(channel); 2172 assert(req != NULL); 2173 2174 args = &req->args; 2175 2176 spdk_file_sync(file, _channel); 2177 BLOBFS_TRACE(file, "name=%s\n", file->name); 2178 args->file = file; 2179 args->sem = &channel->sem; 2180 args->fn.file_op = __file_close_done; 2181 args->arg = req; 2182 channel->send_request(__file_close, req); 2183 sem_wait(&channel->sem); 2184 2185 return args->rc; 2186 } 2187 2188 static void 2189 cache_free_buffers(struct spdk_file *file) 2190 { 2191 BLOBFS_TRACE(file, "free=%s\n", file->name); 2192 pthread_spin_lock(&file->lock); 2193 pthread_spin_lock(&g_caches_lock); 2194 if (file->tree->present_mask == 0) { 2195 pthread_spin_unlock(&g_caches_lock); 2196 pthread_spin_unlock(&file->lock); 2197 return; 2198 } 2199 spdk_tree_free_buffers(file->tree); 2200 if (file->tree->present_mask == 0) { 2201 TAILQ_REMOVE(&g_caches, file, cache_tailq); 2202 } 2203 file->last = NULL; 2204 pthread_spin_unlock(&g_caches_lock); 2205 pthread_spin_unlock(&file->lock); 2206 } 2207 2208 SPDK_LOG_REGISTER_TRACE_FLAG("blobfs", SPDK_TRACE_BLOBFS); 2209 SPDK_LOG_REGISTER_TRACE_FLAG("blobfs_rw", SPDK_TRACE_BLOBFS_RW); 2210