Changeset 8d1aab7 in mainline
- Timestamp:
- 2010-11-24T18:59:47Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f5648d8
- Parents:
- 5bd4f2c
- Location:
- uspace/srv/fs/pipefs
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/fs/pipefs/pipefs.h
r5bd4f2c r8d1aab7 66 66 pipefs_dentry_type_t type; 67 67 unsigned lnkcnt; /**< Link count. */ 68 /* Following is for nodes of type PIPEFS_FILE */ 69 aoff64_t start; /**< File offset where first data block resides */ 68 70 size_t size; /**< File size if type is PIPEFS_FILE. */ 69 void *data; /**< File content's if type is PIPEFS_FILE. */ 70 link_t cs_head; /**< Head of child's siblings list. */ 71 link_t data_head; /**< Head of data blocks list for PIPEFS_FILE. */ 72 /* This is for directory */ 73 link_t cs_head; /**< Head of child's siblings list. */ 71 74 } pipefs_node_t; 75 76 typedef struct pipefs_data_block { 77 link_t link; /**< Linkage for the list of data blocks */ 78 size_t size; /**< Size of this block */ 79 void *data; /**< Data for this block */ 80 } pipefs_data_block_t; 72 81 73 82 extern fs_reg_t pipefs_reg; -
uspace/srv/fs/pipefs/pipefs_ops.c
r5bd4f2c r8d1aab7 190 190 } 191 191 192 if (nodep->data) {192 while (!list_empty(&nodep->data_head)) { 193 193 assert(nodep->type == PIPEFS_FILE); 194 free(nodep->data); 194 195 pipefs_data_block_t *data_block = list_get_instance(nodep->data_head.next, 196 pipefs_data_block_t, link); 197 198 list_remove(&data_block->link); 199 free(data_block->data); 200 free(data_block); 195 201 } 196 202 free(nodep->bp); … … 212 218 nodep->type = PIPEFS_NONE; 213 219 nodep->lnkcnt = 0; 220 nodep->start = 0; 214 221 nodep->size = 0; 215 nodep->data = NULL;222 list_initialize(&nodep->data_head); 216 223 link_initialize(&nodep->nh_link); 217 224 list_initialize(&nodep->cs_head); … … 536 543 size_t bytes; 537 544 if (nodep->type == PIPEFS_FILE) { 538 bytes = min(nodep->size - pos, size); 539 (void) async_data_read_finalize(callid, nodep->data + pos, 540 bytes); 545 /* 546 * Check if we still have the requested data. 547 * This may happen if the client seeked backwards 548 */ 549 if (pos < nodep->start) { 550 ipc_answer_0(callid, ENOTSUP); 551 ipc_answer_0(rid, ENOTSUP); 552 return; 553 } 554 555 /* 556 * Free all data blocks that end before pos. 557 * This is in case the client seeked forward 558 */ 559 while (!list_empty(&nodep->data_head)) { 560 pipefs_data_block_t *data_block = 561 list_get_instance(nodep->data_head.next, 562 pipefs_data_block_t, link); 563 564 aoff64_t block_end = nodep->start + data_block->size; 565 566 if (block_end > pos) { 567 break; 568 } 569 570 list_remove(&data_block->link); 571 free(data_block->data); 572 free(data_block); 573 nodep->start = block_end; 574 } 575 576 if (!list_empty(&nodep->data_head)) { 577 /* We have data block, so let's return its portion after pos */ 578 pipefs_data_block_t *data_block = 579 list_get_instance(nodep->data_head.next, 580 pipefs_data_block_t, link); 581 582 assert(nodep->start <= pos); 583 584 aoff64_t block_end = nodep->start + data_block->size; 585 size_t block_offset = pos - nodep->start; 586 587 assert(block_end > pos); 588 589 bytes = min(block_end - pos, size); 590 (void) async_data_read_finalize(callid, 591 data_block->data + block_offset, 592 bytes); 593 594 if (nodep->start + block_offset + bytes == block_end) { 595 /* Free the data block - it was fully read */ 596 list_remove(&data_block->link); 597 free(data_block->data); 598 free(data_block); 599 nodep->start = block_end; 600 } 601 } 602 else { 603 /* 604 * there is no data 605 * TODO implement waiting for the data 606 * and remove this else clause 607 */ 608 ipc_answer_0(callid, ENOTSUP); 609 ipc_answer_1(rid, ENOTSUP, 0); 610 return; 611 } 541 612 } else { 542 613 pipefs_dentry_t *dentryp; … … 610 681 611 682 /* 612 * Check whether the file needs to grow. 613 */ 614 if (pos + size <= nodep->size) { 615 /* The file size is not changing. */ 616 (void) async_data_write_finalize(callid, nodep->data + pos, size); 617 ipc_answer_2(rid, EOK, size, nodep->size); 618 return; 619 } 620 size_t delta = (pos + size) - nodep->size; 621 /* 622 * At this point, we are deliberately extremely straightforward and 623 * simply realloc the contents of the file on every write that grows the 624 * file. In the end, the situation might not be as bad as it may look: 625 * our heap allocator can save us and just grow the block whenever 626 * possible. 627 */ 628 void *newdata = realloc(nodep->data, nodep->size + delta); 683 * Check whether we are writing to the end 684 */ 685 if (pos != nodep->size) { 686 ipc_answer_0(callid, ENOTSUP); 687 ipc_answer_2(rid, EOK, 0, nodep->size); 688 return; 689 } 690 691 /* 692 * Allocate a buffer for the new data. 693 * Currently we accept any size, create a data block from this 694 * and append it to the end of a file 695 */ 696 void *newdata = malloc(size); 629 697 if (!newdata) { 630 698 ipc_answer_0(callid, ENOMEM); … … 632 700 return; 633 701 } 634 /* Clear any newly allocated memory in order to emulate gaps. */ 635 memset(newdata + nodep->size, 0, delta); 636 nodep->size += delta; 637 nodep->data = newdata; 638 (void) async_data_write_finalize(callid, nodep->data + pos, size); 702 703 pipefs_data_block_t *newblock = malloc(sizeof(pipefs_data_block_t)); 704 705 if (!newblock) { 706 free(newdata); 707 ipc_answer_0(callid, ENOMEM); 708 ipc_answer_2(rid, EOK, 0, nodep->size); 709 return; 710 } 711 712 int rc = async_data_write_finalize(callid, newdata, size); 713 714 if (rc != EOK) { 715 free(newblock); 716 free(newdata); 717 ipc_answer_0(callid, rc); 718 ipc_answer_2(rid, EOK, 0, nodep->size); 719 return; 720 } 721 722 link_initialize(&newblock->link); 723 newblock->size = size; 724 newblock->data = newdata; 725 list_append(&newblock->link, &nodep->data_head); 726 727 nodep->size += size; 728 639 729 ipc_answer_2(rid, EOK, size, nodep->size); 640 730 } … … 642 732 void pipefs_truncate(ipc_callid_t rid, ipc_call_t *request) 643 733 { 644 devmap_handle_t devmap_handle = (devmap_handle_t) IPC_GET_ARG1(*request); 645 fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request); 646 aoff64_t size = 647 (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request)); 648 649 /* 650 * Lookup the respective PIPEFS node. 651 */ 652 unsigned long key[] = { 653 [NODES_KEY_DEV] = devmap_handle, 654 [NODES_KEY_INDEX] = index 655 }; 656 link_t *hlp = hash_table_find(&nodes, key); 657 if (!hlp) { 658 ipc_answer_0(rid, ENOENT); 659 return; 660 } 661 pipefs_node_t *nodep = hash_table_get_instance(hlp, pipefs_node_t, 662 nh_link); 663 664 if (size == nodep->size) { 665 ipc_answer_0(rid, EOK); 666 return; 667 } 668 669 if (size > SIZE_MAX) { 670 ipc_answer_0(rid, ENOMEM); 671 return; 672 } 673 674 void *newdata = realloc(nodep->data, size); 675 if (!newdata) { 676 ipc_answer_0(rid, ENOMEM); 677 return; 678 } 679 680 if (size > nodep->size) { 681 size_t delta = size - nodep->size; 682 memset(newdata + nodep->size, 0, delta); 683 } 684 685 nodep->size = size; 686 nodep->data = newdata; 687 ipc_answer_0(rid, EOK); 734 /* 735 * PIPEFS does not support resizing of files 736 */ 737 ipc_answer_0(rid, ENOTSUP); 688 738 } 689 739
Note:
See TracChangeset
for help on using the changeset viewer.