Changeset efdfebc in mainline for uspace/lib/block/block.c
- Timestamp:
- 2012-11-06T21:03:44Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 338810f
- Parents:
- de73242 (diff), 94795812 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/block/block.c
rde73242 refdfebc 37 37 */ 38 38 39 #include "libblock.h"40 39 #include "../../srv/vfs/vfs.h" 41 40 #include <ipc/loc.h> 42 #include <ipc/bd.h>43 41 #include <ipc/services.h> 44 42 #include <errno.h> … … 47 45 #include <as.h> 48 46 #include <assert.h> 47 #include <bd.h> 49 48 #include <fibril_synch.h> 50 49 #include <adt/list.h> … … 56 55 #include <sys/typefmt.h> 57 56 #include <stacktrace.h> 57 #include "block.h" 58 58 59 59 /** Lock protecting the device connection list */ … … 62 62 static LIST_INITIALIZE(dcl); 63 63 64 #define CACHE_BUCKETS_LOG2 1065 #define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2)66 64 67 65 typedef struct { … … 80 78 service_id_t service_id; 81 79 async_sess_t *sess; 82 fibril_mutex_t comm_area_lock; 83 void *comm_area; 84 size_t comm_size; 80 bd_t *bd; 85 81 void *bb_buf; 86 82 aoff64_t bb_addr; … … 89 85 } devcon_t; 90 86 91 static int read_blocks(devcon_t *, aoff64_t, size_t); 92 static int write_blocks(devcon_t *, aoff64_t, size_t); 93 static int get_block_size(async_sess_t *, size_t *); 94 static int get_num_blocks(async_sess_t *, aoff64_t *); 87 static int read_blocks(devcon_t *, aoff64_t, size_t, void *, size_t); 88 static int write_blocks(devcon_t *, aoff64_t, size_t, void *, size_t); 95 89 static aoff64_t ba_ltop(devcon_t *, aoff64_t); 96 90 … … 112 106 113 107 static int devcon_add(service_id_t service_id, async_sess_t *sess, 114 size_t bsize, void *comm_area, size_t comm_size)108 size_t bsize, bd_t *bd) 115 109 { 116 110 devcon_t *devcon; 117 118 if (comm_size < bsize)119 return EINVAL;120 111 121 112 devcon = malloc(sizeof(devcon_t)); … … 126 117 devcon->service_id = service_id; 127 118 devcon->sess = sess; 128 fibril_mutex_initialize(&devcon->comm_area_lock); 129 devcon->comm_area = comm_area; 130 devcon->comm_size = comm_size; 119 devcon->bd = bd; 131 120 devcon->bb_buf = NULL; 132 121 devcon->bb_addr = 0; … … 158 147 size_t comm_size) 159 148 { 160 void *comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE, 161 MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 162 if (!comm_area) 163 return ENOMEM; 164 149 bd_t *bd; 150 165 151 async_sess_t *sess = loc_service_connect(mgmt, service_id, 166 152 IPC_FLAG_BLOCKING); 167 153 if (!sess) { 168 munmap(comm_area, comm_size);169 154 return ENOENT; 170 155 } 171 156 172 async_exch_t *exch = async_exchange_begin(sess); 173 int rc = async_share_out_start(exch, comm_area, 174 AS_AREA_READ | AS_AREA_WRITE); 175 async_exchange_end(exch); 176 157 int rc = bd_open(sess, &bd); 177 158 if (rc != EOK) { 178 munmap(comm_area, comm_size);179 159 async_hangup(sess); 180 160 return rc; … … 182 162 183 163 size_t bsize; 184 rc = get_block_size(sess, &bsize); 185 164 rc = bd_get_block_size(bd, &bsize); 186 165 if (rc != EOK) { 187 munmap(comm_area, comm_size);166 bd_close(bd); 188 167 async_hangup(sess); 189 168 return rc; 190 169 } 191 170 192 rc = devcon_add(service_id, sess, bsize, comm_area, comm_size);171 rc = devcon_add(service_id, sess, bsize, bd); 193 172 if (rc != EOK) { 194 munmap(comm_area, comm_size);173 bd_close(bd); 195 174 async_hangup(sess); 196 175 return rc; … … 213 192 free(devcon->bb_buf); 214 193 215 munmap(devcon->comm_area, devcon->comm_size);194 bd_close(devcon->bd); 216 195 async_hangup(devcon->sess); 217 196 … … 233 212 return ENOMEM; 234 213 235 fibril_mutex_lock(&devcon->comm_area_lock); 236 rc = read_blocks(devcon, 0, 1); 214 rc = read_blocks(devcon, 0, 1, bb_buf, devcon->pblock_size); 237 215 if (rc != EOK) { 238 fibril_mutex_unlock(&devcon->comm_area_lock);239 216 free(bb_buf); 240 217 return rc; 241 218 } 242 memcpy(bb_buf, devcon->comm_area, devcon->pblock_size);243 fibril_mutex_unlock(&devcon->comm_area_lock);244 219 245 220 devcon->bb_buf = bb_buf; … … 256 231 } 257 232 258 static hash_index_t cache_hash(unsigned long *key) 259 { 260 return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1); 261 } 262 263 static int cache_compare(unsigned long *key, hash_count_t keys, link_t *item) 264 { 265 block_t *b = hash_table_get_instance(item, block_t, hash_link); 266 return b->lba == MERGE_LOUP32(key[0], key[1]); 267 } 268 269 static void cache_remove_callback(link_t *item) 270 { 271 } 272 273 static hash_table_operations_t cache_ops = { 233 static size_t cache_key_hash(void *key) 234 { 235 aoff64_t *lba = (aoff64_t*)key; 236 return *lba; 237 } 238 239 static size_t cache_hash(const ht_link_t *item) 240 { 241 block_t *b = hash_table_get_inst(item, block_t, hash_link); 242 return b->lba; 243 } 244 245 static bool cache_key_equal(void *key, const ht_link_t *item) 246 { 247 aoff64_t *lba = (aoff64_t*)key; 248 block_t *b = hash_table_get_inst(item, block_t, hash_link); 249 return b->lba == *lba; 250 } 251 252 253 static hash_table_ops_t cache_ops = { 274 254 .hash = cache_hash, 275 .compare = cache_compare, 276 .remove_callback = cache_remove_callback 255 .key_hash = cache_key_hash, 256 .key_equal = cache_key_equal, 257 .equal = NULL, 258 .remove_callback = NULL 277 259 }; 278 260 … … 305 287 cache->blocks_cluster = cache->lblock_size / devcon->pblock_size; 306 288 307 if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2, 308 &cache_ops)) { 289 if (!hash_table_create(&cache->block_hash, 0, 0, &cache_ops)) { 309 290 free(cache); 310 291 return ENOMEM; … … 338 319 list_remove(&b->free_link); 339 320 if (b->dirty) { 340 memcpy(devcon->comm_area, b->data, b->size);341 rc = write_blocks(devcon, b->pba, cache->blocks_cluster);321 rc = write_blocks(devcon, b->pba, cache->blocks_cluster, 322 b->data, b->size); 342 323 if (rc != EOK) 343 324 return rc; 344 325 } 345 326 346 unsigned long key[2] = { 347 LOWER32(b->lba), 348 UPPER32(b->lba) 349 }; 350 hash_table_remove(&cache->block_hash, key, 2); 327 hash_table_remove_item(&cache->block_hash, &b->hash_link); 351 328 352 329 free(b->data); … … 380 357 fibril_rwlock_initialize(&b->contents_lock); 381 358 link_initialize(&b->free_link); 382 link_initialize(&b->hash_link);383 359 } 384 360 … … 400 376 cache_t *cache; 401 377 block_t *b; 402 link_t *l; 403 unsigned long key[2] = { 404 LOWER32(ba), 405 UPPER32(ba) 406 }; 378 link_t *link; 407 379 408 380 int rc; … … 420 392 421 393 fibril_mutex_lock(&cache->lock); 422 l = hash_table_find(&cache->block_hash, key);423 if ( l) {394 ht_link_t *hlink = hash_table_find(&cache->block_hash, &ba); 395 if (hlink) { 424 396 found: 425 397 /* 426 398 * We found the block in the cache. 427 399 */ 428 b = hash_table_get_inst ance(l, block_t, hash_link);400 b = hash_table_get_inst(hlink, block_t, hash_link); 429 401 fibril_mutex_lock(&b->lock); 430 402 if (b->refcnt++ == 0) … … 464 436 goto out; 465 437 } 466 l = list_first(&cache->free_list);467 b = list_get_instance(l , block_t, free_link);438 link = list_first(&cache->free_list); 439 b = list_get_instance(link, block_t, free_link); 468 440 469 441 fibril_mutex_lock(&b->lock); … … 481 453 list_append(&b->free_link, &cache->free_list); 482 454 fibril_mutex_unlock(&cache->lock); 483 fibril_mutex_lock(&devcon->comm_area_lock);484 memcpy(devcon->comm_area, b->data, b->size);485 455 rc = write_blocks(devcon, b->pba, 486 cache->blocks_cluster); 487 fibril_mutex_unlock(&devcon->comm_area_lock); 456 cache->blocks_cluster, b->data, b->size); 488 457 if (rc != EOK) { 489 458 /* … … 505 474 goto retry; 506 475 } 507 l = hash_table_find(&cache->block_hash, key);508 if ( l) {476 hlink = hash_table_find(&cache->block_hash, &ba); 477 if (hlink) { 509 478 /* 510 479 * Someone else must have already … … 528 497 */ 529 498 list_remove(&b->free_link); 530 unsigned long temp_key[2] = { 531 LOWER32(b->lba), 532 UPPER32(b->lba) 533 }; 534 hash_table_remove(&cache->block_hash, temp_key, 2); 499 hash_table_remove_item(&cache->block_hash, &b->hash_link); 535 500 } 536 501 … … 540 505 b->lba = ba; 541 506 b->pba = ba_ltop(devcon, b->lba); 542 hash_table_insert(&cache->block_hash, key,&b->hash_link);507 hash_table_insert(&cache->block_hash, &b->hash_link); 543 508 544 509 /* … … 555 520 * the new contents from the device. 556 521 */ 557 fibril_mutex_lock(&devcon->comm_area_lock); 558 rc = read_blocks(devcon, b->pba, cache->blocks_cluster); 559 memcpy(b->data, devcon->comm_area, cache->lblock_size); 560 fibril_mutex_unlock(&devcon->comm_area_lock); 522 rc = read_blocks(devcon, b->pba, cache->blocks_cluster, 523 b->data, cache->lblock_size); 561 524 if (rc != EOK) 562 525 b->toxic = true; … … 616 579 if (block->dirty && (block->refcnt == 1) && 617 580 (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) { 618 fibril_mutex_lock(&devcon->comm_area_lock); 619 memcpy(devcon->comm_area, block->data, block->size); 620 rc = write_blocks(devcon, block->pba, cache->blocks_cluster); 621 fibril_mutex_unlock(&devcon->comm_area_lock); 581 rc = write_blocks(devcon, block->pba, cache->blocks_cluster, 582 block->data, block->size); 622 583 block->dirty = false; 623 584 } … … 652 613 * Take the block out of the cache and free it. 653 614 */ 654 unsigned long key[2] = { 655 LOWER32(block->lba), 656 UPPER32(block->lba) 657 }; 658 hash_table_remove(&cache->block_hash, key, 2); 615 hash_table_remove_item(&cache->block_hash, &block->hash_link); 659 616 fibril_mutex_unlock(&block->lock); 660 617 free(block->data); … … 688 645 * 689 646 * @param service_id Service ID of the block device. 647 * @param buf Buffer for holding one block 690 648 * @param bufpos Pointer to the first unread valid offset within the 691 649 * communication buffer. … … 699 657 * @return EOK on success or a negative return code on failure. 700 658 */ 701 int block_seqread(service_id_t service_id, size_t *bufpos, size_t *buflen,702 aoff64_t *pos, void *dst, size_t size)659 int block_seqread(service_id_t service_id, void *buf, size_t *bufpos, 660 size_t *buflen, aoff64_t *pos, void *dst, size_t size) 703 661 { 704 662 size_t offset = 0; … … 711 669 block_size = devcon->pblock_size; 712 670 713 fibril_mutex_lock(&devcon->comm_area_lock);714 671 while (left > 0) { 715 672 size_t rd; … … 725 682 * destination buffer. 726 683 */ 727 memcpy(dst + offset, devcon->comm_area+ *bufpos, rd);684 memcpy(dst + offset, buf + *bufpos, rd); 728 685 offset += rd; 729 686 *bufpos += rd; … … 736 693 int rc; 737 694 738 rc = read_blocks(devcon, *pos / block_size, 1); 695 rc = read_blocks(devcon, *pos / block_size, 1, buf, 696 devcon->pblock_size); 739 697 if (rc != EOK) { 740 fibril_mutex_unlock(&devcon->comm_area_lock);741 698 return rc; 742 699 } … … 746 703 } 747 704 } 748 fibril_mutex_unlock(&devcon->comm_area_lock);749 705 750 706 return EOK; … … 763 719 { 764 720 devcon_t *devcon; 765 int rc;766 721 767 722 devcon = devcon_search(service_id); 768 723 assert(devcon); 769 770 fibril_mutex_lock(&devcon->comm_area_lock); 771 772 rc = read_blocks(devcon, ba, cnt); 773 if (rc == EOK) 774 memcpy(buf, devcon->comm_area, devcon->pblock_size * cnt); 775 776 fibril_mutex_unlock(&devcon->comm_area_lock); 777 778 return rc; 724 725 return read_blocks(devcon, ba, cnt, buf, devcon->pblock_size * cnt); 779 726 } 780 727 … … 792 739 { 793 740 devcon_t *devcon; 794 int rc;795 741 796 742 devcon = devcon_search(service_id); 797 743 assert(devcon); 798 799 fibril_mutex_lock(&devcon->comm_area_lock); 800 801 memcpy(devcon->comm_area, data, devcon->pblock_size * cnt); 802 rc = write_blocks(devcon, ba, cnt); 803 804 fibril_mutex_unlock(&devcon->comm_area_lock); 805 806 return rc; 744 745 return write_blocks(devcon, ba, cnt, (void *)data, devcon->pblock_size * cnt); 807 746 } 808 747 … … 820 759 devcon = devcon_search(service_id); 821 760 assert(devcon); 822 823 return get_block_size(devcon->sess, bsize);761 762 return bd_get_block_size(devcon->bd, bsize); 824 763 } 825 764 … … 836 775 assert(devcon); 837 776 838 return get_num_blocks(devcon->sess, nblocks);777 return bd_get_num_blocks(devcon->bd, nblocks); 839 778 } 840 779 … … 903 842 { 904 843 devcon_t *devcon = devcon_search(service_id); 905 assert(devcon);906 907 844 toc_block_t *toc = NULL; 908 909 fibril_mutex_lock(&devcon->comm_area_lock); 910 911 async_exch_t *exch = async_exchange_begin(devcon->sess); 912 int rc = async_req_1_0(exch, BD_READ_TOC, session); 913 async_exchange_end(exch); 914 915 if (rc == EOK) { 916 toc = (toc_block_t *) malloc(sizeof(toc_block_t)); 917 if (toc != NULL) { 918 memset(toc, 0, sizeof(toc_block_t)); 919 memcpy(toc, devcon->comm_area, 920 min(devcon->pblock_size, sizeof(toc_block_t))); 921 } 922 } 923 924 925 fibril_mutex_unlock(&devcon->comm_area_lock); 845 int rc; 846 847 assert(devcon); 848 849 toc = (toc_block_t *) malloc(sizeof(toc_block_t)); 850 if (toc == NULL) 851 return NULL; 852 853 rc = bd_read_toc(devcon->bd, session, toc, sizeof(toc_block_t)); 854 if (rc != EOK) { 855 free(toc); 856 return NULL; 857 } 926 858 927 859 return toc; … … 937 869 * @return EOK on success or negative error code on failure. 938 870 */ 939 static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt) 940 { 941 assert(devcon); 942 943 async_exch_t *exch = async_exchange_begin(devcon->sess); 944 int rc = async_req_3_0(exch, BD_READ_BLOCKS, LOWER32(ba), 945 UPPER32(ba), cnt); 946 async_exchange_end(exch); 947 871 static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt, void *buf, 872 size_t size) 873 { 874 assert(devcon); 875 876 int rc = bd_read_blocks(devcon->bd, ba, cnt, buf, size); 948 877 if (rc != EOK) { 949 878 printf("Error %d reading %zu blocks starting at block %" PRIuOFF64 … … 967 896 * @return EOK on success or negative error code on failure. 968 897 */ 969 static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt) 970 { 971 assert(devcon); 972 973 async_exch_t *exch = async_exchange_begin(devcon->sess); 974 int rc = async_req_3_0(exch, BD_WRITE_BLOCKS, LOWER32(ba), 975 UPPER32(ba), cnt); 976 async_exchange_end(exch); 977 898 static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt, void *data, 899 size_t size) 900 { 901 assert(devcon); 902 903 int rc = bd_write_blocks(devcon->bd, ba, cnt, data, size); 978 904 if (rc != EOK) { 979 905 printf("Error %d writing %zu blocks starting at block %" PRIuOFF64 … … 987 913 } 988 914 989 /** Get block size used by the device. */990 static int get_block_size(async_sess_t *sess, size_t *bsize)991 {992 sysarg_t bs;993 994 async_exch_t *exch = async_exchange_begin(sess);995 int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bs);996 async_exchange_end(exch);997 998 if (rc == EOK)999 *bsize = (size_t) bs;1000 1001 return rc;1002 }1003 1004 /** Get total number of blocks on block device. */1005 static int get_num_blocks(async_sess_t *sess, aoff64_t *nblocks)1006 {1007 sysarg_t nb_l;1008 sysarg_t nb_h;1009 1010 async_exch_t *exch = async_exchange_begin(sess);1011 int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h);1012 async_exchange_end(exch);1013 1014 if (rc == EOK)1015 *nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h);1016 1017 return rc;1018 }1019 1020 915 /** Convert logical block address to physical block address. */ 1021 916 static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba)
Note:
See TracChangeset
for help on using the changeset viewer.