Changes in uspace/lib/libblock/libblock.c [7a56b1ed:00b1d20e] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libblock/libblock.c
r7a56b1ed r00b1d20e 50 50 #include <adt/list.h> 51 51 #include <adt/hash_table.h> 52 #include <macros.h> 52 53 #include <mem.h> 53 54 … … 62 63 typedef struct { 63 64 fibril_mutex_t lock; 64 size_t block_size; /**< Block size. */65 size_t lblock_size; /**< Logical block size. */ 65 66 unsigned block_count; /**< Total number of blocks. */ 66 67 unsigned blocks_cached; /**< Number of cached blocks. */ … … 74 75 dev_handle_t dev_handle; 75 76 int dev_phone; 76 fibril_mutex_t com _area_lock;77 void *com _area;78 size_t com _size;77 fibril_mutex_t comm_area_lock; 78 void *comm_area; 79 size_t comm_size; 79 80 void *bb_buf; 80 off_t bb_off;81 size_t bb_size;81 bn_t bb_addr; 82 size_t pblock_size; /**< Physical block size. */ 82 83 cache_t *cache; 83 84 } devcon_t; 84 85 85 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size); 86 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size); 86 static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt); 87 static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt); 88 static int get_block_size(int dev_phone, size_t *bsize); 87 89 88 90 static devcon_t *devcon_search(dev_handle_t dev_handle) … … 102 104 } 103 105 104 static int devcon_add(dev_handle_t dev_handle, int dev_phone, void *com_area,105 size_t com_size)106 static int devcon_add(dev_handle_t dev_handle, int dev_phone, size_t bsize, 107 void *comm_area, size_t comm_size) 106 108 { 107 109 link_t *cur; 108 110 devcon_t *devcon; 111 112 if (comm_size < bsize) 113 return EINVAL; 109 114 110 115 devcon = malloc(sizeof(devcon_t)); … … 115 120 devcon->dev_handle = dev_handle; 116 121 devcon->dev_phone = dev_phone; 117 fibril_mutex_initialize(&devcon->com _area_lock);118 devcon->com _area = com_area;119 devcon->com _size = com_size;122 fibril_mutex_initialize(&devcon->comm_area_lock); 123 devcon->comm_area = comm_area; 124 devcon->comm_size = comm_size; 120 125 devcon->bb_buf = NULL; 121 devcon->bb_ off= 0;122 devcon-> bb_size = 0;126 devcon->bb_addr = 0; 127 devcon->pblock_size = bsize; 123 128 devcon->cache = NULL; 124 129 … … 144 149 } 145 150 146 int block_init(dev_handle_t dev_handle, size_t com _size)151 int block_init(dev_handle_t dev_handle, size_t comm_size) 147 152 { 148 153 int rc; 149 154 int dev_phone; 150 void *com_area; 151 152 com_area = mmap(NULL, com_size, PROTO_READ | PROTO_WRITE, 155 void *comm_area; 156 size_t bsize; 157 158 comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE, 153 159 MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 154 if (!com _area) {160 if (!comm_area) { 155 161 return ENOMEM; 156 162 } … … 158 164 dev_phone = devmap_device_connect(dev_handle, IPC_FLAG_BLOCKING); 159 165 if (dev_phone < 0) { 160 munmap(com _area, com_size);166 munmap(comm_area, comm_size); 161 167 return dev_phone; 162 168 } 163 169 164 rc = ipc_share_out_start(dev_phone, com _area,170 rc = ipc_share_out_start(dev_phone, comm_area, 165 171 AS_AREA_READ | AS_AREA_WRITE); 166 172 if (rc != EOK) { 167 munmap(com _area, com_size);173 munmap(comm_area, comm_size); 168 174 ipc_hangup(dev_phone); 169 175 return rc; 170 176 } 171 172 rc = devcon_add(dev_handle, dev_phone, com_area, com_size); 177 178 if (get_block_size(dev_phone, &bsize) != EOK) { 179 munmap(comm_area, comm_size); 180 ipc_hangup(dev_phone); 181 return rc; 182 } 183 184 rc = devcon_add(dev_handle, dev_phone, bsize, comm_area, comm_size); 173 185 if (rc != EOK) { 174 munmap(com _area, com_size);186 munmap(comm_area, comm_size); 175 187 ipc_hangup(dev_phone); 176 188 return rc; … … 195 207 } 196 208 197 munmap(devcon->com _area, devcon->com_size);209 munmap(devcon->comm_area, devcon->comm_size); 198 210 ipc_hangup(devcon->dev_phone); 199 211 … … 201 213 } 202 214 203 int block_bb_read(dev_handle_t dev_handle, off_t off, size_t size)215 int block_bb_read(dev_handle_t dev_handle, bn_t ba) 204 216 { 205 217 void *bb_buf; … … 211 223 if (devcon->bb_buf) 212 224 return EEXIST; 213 bb_buf = malloc( size);225 bb_buf = malloc(devcon->pblock_size); 214 226 if (!bb_buf) 215 227 return ENOMEM; 216 217 fibril_mutex_lock(&devcon->com _area_lock);218 rc = read_block (devcon, 0, size);228 229 fibril_mutex_lock(&devcon->comm_area_lock); 230 rc = read_blocks(devcon, 0, 1); 219 231 if (rc != EOK) { 220 fibril_mutex_unlock(&devcon->com _area_lock);232 fibril_mutex_unlock(&devcon->comm_area_lock); 221 233 free(bb_buf); 222 234 return rc; 223 235 } 224 memcpy(bb_buf, devcon->com _area,size);225 fibril_mutex_unlock(&devcon->com _area_lock);236 memcpy(bb_buf, devcon->comm_area, devcon->pblock_size); 237 fibril_mutex_unlock(&devcon->comm_area_lock); 226 238 227 239 devcon->bb_buf = bb_buf; 228 devcon->bb_off = off; 229 devcon->bb_size = size; 240 devcon->bb_addr = ba; 230 241 231 242 return EOK; … … 275 286 fibril_mutex_initialize(&cache->lock); 276 287 list_initialize(&cache->free_head); 277 cache-> block_size = size;288 cache->lblock_size = size; 278 289 cache->block_count = blocks; 279 290 cache->blocks_cached = 0; 280 291 cache->mode = mode; 292 293 /* No block size translation a.t.m. */ 294 assert(cache->lblock_size == devcon->pblock_size); 281 295 282 296 if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1, … … 331 345 link_t *l; 332 346 unsigned long key = boff; 333 int rc ;347 int rc = EOK; 334 348 335 349 devcon = devcon_search(dev_handle); … … 341 355 342 356 retry: 343 rc = EOK;344 b = NULL;345 346 357 fibril_mutex_lock(&cache->lock); 347 358 l = hash_table_find(&cache->block_hash, &key); … … 371 382 if (!b) 372 383 goto recycle; 373 b->data = malloc(cache-> block_size);384 b->data = malloc(cache->lblock_size); 374 385 if (!b->data) { 375 386 free(b); … … 383 394 unsigned long temp_key; 384 395 recycle: 385 if (list_empty(&cache->free_head)) { 386 fibril_mutex_unlock(&cache->lock); 387 rc = ENOMEM; 388 goto out; 389 } 396 assert(!list_empty(&cache->free_head)); 390 397 l = cache->free_head.next; 391 398 b = list_get_instance(l, block_t, free_link); … … 405 412 list_append(&b->free_link, &cache->free_head); 406 413 fibril_mutex_unlock(&cache->lock); 407 fibril_mutex_lock(&devcon->com_area_lock); 408 memcpy(devcon->com_area, b->data, b->size); 409 rc = write_block(devcon, b->boff, 410 cache->block_size); 411 fibril_mutex_unlock(&devcon->com_area_lock); 414 fibril_mutex_lock(&devcon->comm_area_lock); 415 memcpy(devcon->comm_area, b->data, b->size); 416 rc = write_blocks(devcon, b->boff, 1); 417 fibril_mutex_unlock(&devcon->comm_area_lock); 412 418 if (rc != EOK) { 413 419 /* … … 444 450 block_initialize(b); 445 451 b->dev_handle = dev_handle; 446 b->size = cache-> block_size;452 b->size = cache->lblock_size; 447 453 b->boff = boff; 448 454 hash_table_insert(&cache->block_hash, &key, &b->hash_link); … … 461 467 * the new contents from the device. 462 468 */ 463 fibril_mutex_lock(&devcon->com _area_lock);464 rc = read_block (devcon, b->boff, cache->block_size);465 memcpy(b->data, devcon->com _area, cache->block_size);466 fibril_mutex_unlock(&devcon->com _area_lock);469 fibril_mutex_lock(&devcon->comm_area_lock); 470 rc = read_blocks(devcon, b->boff, 1); 471 memcpy(b->data, devcon->comm_area, cache->lblock_size); 472 fibril_mutex_unlock(&devcon->comm_area_lock); 467 473 if (rc != EOK) 468 474 b->toxic = true; … … 471 477 472 478 fibril_mutex_unlock(&b->lock); 473 }474 out:475 if ((rc != EOK) && b) {476 assert(b->toxic);477 (void) block_put(b);478 b = NULL;479 479 } 480 480 *block = b; … … 521 521 if (block->dirty && (block->refcnt == 1) && 522 522 (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) { 523 fibril_mutex_lock(&devcon->com _area_lock);524 memcpy(devcon->com _area, block->data, block->size);525 rc = write_block (devcon, block->boff, block->size);526 fibril_mutex_unlock(&devcon->com _area_lock);523 fibril_mutex_lock(&devcon->comm_area_lock); 524 memcpy(devcon->comm_area, block->data, block->size); 525 rc = write_blocks(devcon, block->boff, 1); 526 fibril_mutex_unlock(&devcon->comm_area_lock); 527 527 block->dirty = false; 528 528 } … … 601 601 */ 602 602 int block_seqread(dev_handle_t dev_handle, off_t *bufpos, size_t *buflen, 603 off_t *pos, void *dst, size_t size , size_t block_size)603 off_t *pos, void *dst, size_t size) 604 604 { 605 605 off_t offset = 0; 606 606 size_t left = size; 607 devcon_t *devcon = devcon_search(dev_handle); 608 assert(devcon); 609 610 fibril_mutex_lock(&devcon->com_area_lock); 607 size_t block_size; 608 devcon_t *devcon; 609 610 devcon = devcon_search(dev_handle); 611 assert(devcon); 612 block_size = devcon->pblock_size; 613 614 fibril_mutex_lock(&devcon->comm_area_lock); 611 615 while (left > 0) { 612 616 size_t rd; … … 622 626 * destination buffer. 623 627 */ 624 memcpy(dst + offset, devcon->com _area + *bufpos, rd);628 memcpy(dst + offset, devcon->comm_area + *bufpos, rd); 625 629 offset += rd; 626 630 *bufpos += rd; … … 633 637 int rc; 634 638 635 rc = read_block (devcon, *pos / block_size, block_size);639 rc = read_blocks(devcon, *pos / block_size, 1); 636 640 if (rc != EOK) { 637 fibril_mutex_unlock(&devcon->com _area_lock);641 fibril_mutex_unlock(&devcon->comm_area_lock); 638 642 return rc; 639 643 } … … 643 647 } 644 648 } 645 fibril_mutex_unlock(&devcon->com _area_lock);649 fibril_mutex_unlock(&devcon->comm_area_lock); 646 650 647 651 return EOK; 648 652 } 649 653 650 /** Read block from block device. 654 /** Read blocks directly from device (bypass cache). 655 * 656 * @param dev_handle Device handle of the block device. 657 * @param ba Address of first block. 658 * @param cnt Number of blocks. 659 * @param src Buffer for storing the data. 660 * 661 * @return EOK on success or negative error code on failure. 662 */ 663 int block_read_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt, void *buf) 664 { 665 devcon_t *devcon; 666 int rc; 667 668 devcon = devcon_search(dev_handle); 669 assert(devcon); 670 671 fibril_mutex_lock(&devcon->comm_area_lock); 672 673 rc = read_blocks(devcon, ba, cnt); 674 if (rc == EOK) 675 memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt); 676 677 fibril_mutex_unlock(&devcon->comm_area_lock); 678 679 return rc; 680 } 681 682 /** Write blocks directly to device (bypass cache). 683 * 684 * @param dev_handle Device handle of the block device. 685 * @param ba Address of first block. 686 * @param cnt Number of blocks. 687 * @param src The data to be written. 688 * 689 * @return EOK on success or negative error code on failure. 690 */ 691 int block_write_direct(dev_handle_t dev_handle, bn_t ba, size_t cnt, 692 const void *data) 693 { 694 devcon_t *devcon; 695 int rc; 696 697 devcon = devcon_search(dev_handle); 698 assert(devcon); 699 700 fibril_mutex_lock(&devcon->comm_area_lock); 701 702 memcpy(devcon->comm_area, data, devcon->pblock_size * cnt); 703 rc = read_blocks(devcon, ba, cnt); 704 705 fibril_mutex_unlock(&devcon->comm_area_lock); 706 707 return rc; 708 } 709 710 /** Get device block size. 711 * 712 * @param dev_handle Device handle of the block device. 713 * @param bsize Output block size. 714 * 715 * @return EOK on success or negative error code on failure. 716 */ 717 int block_get_bsize(dev_handle_t dev_handle, size_t *bsize) 718 { 719 devcon_t *devcon; 720 721 devcon = devcon_search(dev_handle); 722 assert(devcon); 723 724 return get_block_size(devcon->dev_phone, bsize); 725 } 726 727 /** Read blocks from block device. 651 728 * 652 729 * @param devcon Device connection. 653 * @param b off Block index.654 * @param block_size Block size.730 * @param ba Address of first block. 731 * @param cnt Number of blocks. 655 732 * @param src Buffer for storing the data. 656 733 * 657 734 * @return EOK on success or negative error code on failure. 658 735 */ 659 static int read_block(devcon_t *devcon, bn_t boff, size_t block_size) 660 { 661 ipcarg_t retval; 736 static int read_blocks(devcon_t *devcon, bn_t ba, size_t cnt) 737 { 662 738 int rc; 663 739 664 740 assert(devcon); 665 rc = async_req_2_1(devcon->dev_phone, BD_READ_BLOCK, boff, block_size, 666 &retval); 667 if ((rc != EOK) || (retval != EOK)) 668 return (rc != EOK ? rc : (int) retval); 669 670 return EOK; 741 rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba), 742 UPPER32(ba), cnt); 743 return rc; 671 744 } 672 745 … … 674 747 * 675 748 * @param devcon Device connection. 676 * @param b off Block index.677 * @param block_size Block size.749 * @param ba Address of first block. 750 * @param cnt Number of blocks. 678 751 * @param src Buffer containing the data to write. 679 752 * 680 753 * @return EOK on success or negative error code on failure. 681 754 */ 682 static int write_block(devcon_t *devcon, bn_t boff, size_t block_size) 683 { 684 ipcarg_t retval; 755 static int write_blocks(devcon_t *devcon, bn_t ba, size_t cnt) 756 { 685 757 int rc; 686 758 687 759 assert(devcon); 688 rc = async_req_2_1(devcon->dev_phone, BD_WRITE_BLOCK, boff, block_size, 689 &retval); 690 if ((rc != EOK) || (retval != EOK)) 691 return (rc != EOK ? rc : (int) retval); 692 693 return EOK; 760 rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba), 761 UPPER32(ba), cnt); 762 return rc; 763 } 764 765 /** Get block size used by the device. */ 766 static int get_block_size(int dev_phone, size_t *bsize) 767 { 768 ipcarg_t bs; 769 int rc; 770 771 rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs); 772 if (rc == EOK) 773 *bsize = (size_t) bs; 774 775 return rc; 694 776 } 695 777
Note:
See TracChangeset
for help on using the changeset viewer.