Changes in uspace/lib/block/libblock.c [c7bbf029:867e2555] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/block/libblock.c
rc7bbf029 r867e2555 2 2 * Copyright (c) 2008 Jakub Jermar 3 3 * Copyright (c) 2008 Martin Decky 4 * Copyright (c) 2011 Martin Sucha 4 5 * All rights reserved. 5 6 * … … 59 60 static FIBRIL_MUTEX_INITIALIZE(dcl_lock); 60 61 /** Device connection list head. */ 61 static LIST_INITIALIZE(dcl _head);62 63 #define CACHE_BUCKETS_LOG2 64 #define CACHE_BUCKETS 62 static LIST_INITIALIZE(dcl); 63 64 #define CACHE_BUCKETS_LOG2 10 65 #define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2) 65 66 66 67 typedef struct { 67 68 fibril_mutex_t lock; 68 size_t lblock_size; 69 unsigned blocks_cluster; 70 unsigned block_count; 71 unsigned blocks_cached; 69 size_t lblock_size; /**< Logical block size. */ 70 unsigned blocks_cluster; /**< Physical blocks per block_t */ 71 unsigned block_count; /**< Total number of blocks. */ 72 unsigned blocks_cached; /**< Number of cached blocks. */ 72 73 hash_table_t block_hash; 73 li nk_t free_head;74 list_t free_list; 74 75 enum cache_mode mode; 75 76 } cache_t; … … 78 79 link_t link; 79 80 devmap_handle_t devmap_handle; 80 int dev_phone;81 async_sess_t *sess; 81 82 fibril_mutex_t comm_area_lock; 82 83 void *comm_area; … … 84 85 void *bb_buf; 85 86 aoff64_t bb_addr; 86 size_t pblock_size; 87 size_t pblock_size; /**< Physical block size. */ 87 88 cache_t *cache; 88 89 } devcon_t; 89 90 90 static int read_blocks(devcon_t * devcon, aoff64_t ba, size_t cnt);91 static int write_blocks(devcon_t * devcon, aoff64_t ba, size_t cnt);92 static int get_block_size( int dev_phone, size_t *bsize);93 static int get_num_blocks( int dev_phone, aoff64_t *nblocks);94 static aoff64_t ba_ltop(devcon_t * devcon, aoff64_t lba);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 *); 95 static aoff64_t ba_ltop(devcon_t *, aoff64_t); 95 96 96 97 static devcon_t *devcon_search(devmap_handle_t devmap_handle) 97 98 { 98 link_t *cur;99 100 99 fibril_mutex_lock(&dcl_lock); 101 for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { 100 101 list_foreach(dcl, cur) { 102 102 devcon_t *devcon = list_get_instance(cur, devcon_t, link); 103 103 if (devcon->devmap_handle == devmap_handle) { … … 106 106 } 107 107 } 108 108 109 fibril_mutex_unlock(&dcl_lock); 109 110 return NULL; 110 111 } 111 112 112 static int devcon_add(devmap_handle_t devmap_handle, int dev_phone, size_t bsize, 113 void *comm_area, size_t comm_size) 114 { 115 link_t *cur; 113 static int devcon_add(devmap_handle_t devmap_handle, async_sess_t *sess, 114 size_t bsize, void *comm_area, size_t comm_size) 115 { 116 116 devcon_t *devcon; 117 117 118 118 if (comm_size < bsize) 119 119 return EINVAL; 120 120 121 121 devcon = malloc(sizeof(devcon_t)); 122 122 if (!devcon) … … 125 125 link_initialize(&devcon->link); 126 126 devcon->devmap_handle = devmap_handle; 127 devcon-> dev_phone = dev_phone;127 devcon->sess = sess; 128 128 fibril_mutex_initialize(&devcon->comm_area_lock); 129 129 devcon->comm_area = comm_area; … … 133 133 devcon->pblock_size = bsize; 134 134 devcon->cache = NULL; 135 135 136 136 fibril_mutex_lock(&dcl_lock); 137 for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) {137 list_foreach(dcl, cur) { 138 138 devcon_t *d = list_get_instance(cur, devcon_t, link); 139 139 if (d->devmap_handle == devmap_handle) { … … 143 143 } 144 144 } 145 list_append(&devcon->link, &dcl _head);145 list_append(&devcon->link, &dcl); 146 146 fibril_mutex_unlock(&dcl_lock); 147 147 return EOK; … … 155 155 } 156 156 157 int block_init(devmap_handle_t devmap_handle, size_t comm_size) 158 { 159 int rc; 160 int dev_phone; 161 void *comm_area; 162 size_t bsize; 163 164 comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE, 157 int block_init(exch_mgmt_t mgmt, devmap_handle_t devmap_handle, 158 size_t comm_size) 159 { 160 void *comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE, 165 161 MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 166 if (!comm_area) {162 if (!comm_area) 167 163 return ENOMEM; 168 }169 170 dev_phone = devmap_device_connect(devmap_handle,IPC_FLAG_BLOCKING);171 if ( dev_phone < 0) {164 165 async_sess_t *sess = devmap_device_connect(mgmt, devmap_handle, 166 IPC_FLAG_BLOCKING); 167 if (!sess) { 172 168 munmap(comm_area, comm_size); 173 return dev_phone; 174 } 175 176 rc = async_share_out_start(dev_phone, comm_area, 169 return ENOENT; 170 } 171 172 async_exch_t *exch = async_exchange_begin(sess); 173 int rc = async_share_out_start(exch, comm_area, 177 174 AS_AREA_READ | AS_AREA_WRITE); 178 if (rc != EOK) { 179 munmap(comm_area, comm_size); 180 async_hangup(dev_phone); 181 return rc; 182 } 183 184 if (get_block_size(dev_phone, &bsize) != EOK) { 185 munmap(comm_area, comm_size); 186 async_hangup(dev_phone); 187 return rc; 188 } 189 190 rc = devcon_add(devmap_handle, dev_phone, bsize, comm_area, comm_size); 175 async_exchange_end(exch); 176 191 177 if (rc != EOK) { 192 178 munmap(comm_area, comm_size); 193 async_hangup( dev_phone);179 async_hangup(sess); 194 180 return rc; 195 181 } 196 182 183 size_t bsize; 184 rc = get_block_size(sess, &bsize); 185 186 if (rc != EOK) { 187 munmap(comm_area, comm_size); 188 async_hangup(sess); 189 return rc; 190 } 191 192 rc = devcon_add(devmap_handle, sess, bsize, comm_area, comm_size); 193 if (rc != EOK) { 194 munmap(comm_area, comm_size); 195 async_hangup(sess); 196 return rc; 197 } 198 197 199 return EOK; 198 200 } … … 205 207 if (devcon->cache) 206 208 (void) block_cache_fini(devmap_handle); 207 209 208 210 devcon_remove(devcon); 209 211 210 212 if (devcon->bb_buf) 211 213 free(devcon->bb_buf); 212 214 213 215 munmap(devcon->comm_area, devcon->comm_size); 214 async_hangup(devcon-> dev_phone);215 216 free(devcon); 216 async_hangup(devcon->sess); 217 218 free(devcon); 217 219 } 218 220 … … 256 258 static hash_index_t cache_hash(unsigned long *key) 257 259 { 258 return *key& (CACHE_BUCKETS - 1);260 return MERGE_LOUP32(key[0], key[1]) & (CACHE_BUCKETS - 1); 259 261 } 260 262 … … 262 264 { 263 265 block_t *b = hash_table_get_instance(item, block_t, hash_link); 264 return b->lba == *key;266 return b->lba == MERGE_LOUP32(key[0], key[1]); 265 267 } 266 268 … … 289 291 290 292 fibril_mutex_initialize(&cache->lock); 291 list_initialize(&cache->free_ head);293 list_initialize(&cache->free_list); 292 294 cache->lblock_size = size; 293 295 cache->block_count = blocks; … … 303 305 cache->blocks_cluster = cache->lblock_size / devcon->pblock_size; 304 306 305 if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 1,307 if (!hash_table_create(&cache->block_hash, CACHE_BUCKETS, 2, 306 308 &cache_ops)) { 307 309 free(cache); … … 330 332 * bother with the cache and block locks because we are single-threaded. 331 333 */ 332 while (!list_empty(&cache->free_ head)) {333 block_t *b = list_get_instance( cache->free_head.next,334 while (!list_empty(&cache->free_list)) { 335 block_t *b = list_get_instance(list_first(&cache->free_list), 334 336 block_t, free_link); 335 337 … … 342 344 } 343 345 344 unsigned long key = b->lba; 345 hash_table_remove(&cache->block_hash, &key, 1); 346 unsigned long key[2] = { 347 LOWER32(b->lba), 348 UPPER32(b->lba) 349 }; 350 hash_table_remove(&cache->block_hash, key, 2); 346 351 347 352 free(b->data); … … 362 367 if (cache->blocks_cached < CACHE_LO_WATERMARK) 363 368 return true; 364 if (!list_empty(&cache->free_ head))369 if (!list_empty(&cache->free_list)) 365 370 return false; 366 371 return true; … … 396 401 block_t *b; 397 402 link_t *l; 398 unsigned long key = ba; 403 unsigned long key[2] = { 404 LOWER32(ba), 405 UPPER32(ba) 406 }; 407 399 408 int rc; 400 409 … … 411 420 412 421 fibril_mutex_lock(&cache->lock); 413 l = hash_table_find(&cache->block_hash, &key);422 l = hash_table_find(&cache->block_hash, key); 414 423 if (l) { 415 424 found: … … 449 458 * Try to recycle a block from the free list. 450 459 */ 451 unsigned long temp_key;452 460 recycle: 453 if (list_empty(&cache->free_ head)) {461 if (list_empty(&cache->free_list)) { 454 462 fibril_mutex_unlock(&cache->lock); 455 463 rc = ENOMEM; 456 464 goto out; 457 465 } 458 l = cache->free_head.next;466 l = list_first(&cache->free_list); 459 467 b = list_get_instance(l, block_t, free_link); 460 468 … … 471 479 */ 472 480 list_remove(&b->free_link); 473 list_append(&b->free_link, &cache->free_ head);481 list_append(&b->free_link, &cache->free_list); 474 482 fibril_mutex_unlock(&cache->lock); 475 483 fibril_mutex_lock(&devcon->comm_area_lock); … … 497 505 goto retry; 498 506 } 499 l = hash_table_find(&cache->block_hash, &key);507 l = hash_table_find(&cache->block_hash, key); 500 508 if (l) { 501 509 /* … … 520 528 */ 521 529 list_remove(&b->free_link); 522 temp_key = b->lba; 523 hash_table_remove(&cache->block_hash, &temp_key, 1); 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); 524 535 } 525 536 … … 529 540 b->lba = ba; 530 541 b->pba = ba_ltop(devcon, b->lba); 531 hash_table_insert(&cache->block_hash, &key, &b->hash_link);542 hash_table_insert(&cache->block_hash, key, &b->hash_link); 532 543 533 544 /* … … 641 652 * Take the block out of the cache and free it. 642 653 */ 643 unsigned long key = block->lba; 644 hash_table_remove(&cache->block_hash, &key, 1); 654 unsigned long key[2] = { 655 LOWER32(block->lba), 656 UPPER32(block->lba) 657 }; 658 hash_table_remove(&cache->block_hash, key, 2); 645 659 fibril_mutex_unlock(&block->lock); 646 660 free(block->data); … … 663 677 goto retry; 664 678 } 665 list_append(&block->free_link, &cache->free_ head);679 list_append(&block->free_link, &cache->free_list); 666 680 } 667 681 fibril_mutex_unlock(&block->lock); … … 807 821 assert(devcon); 808 822 809 return get_block_size(devcon-> dev_phone, bsize);823 return get_block_size(devcon->sess, bsize); 810 824 } 811 825 … … 819 833 int block_get_nblocks(devmap_handle_t devmap_handle, aoff64_t *nblocks) 820 834 { 821 devcon_t *devcon; 822 823 devcon = devcon_search(devmap_handle); 824 assert(devcon); 825 826 return get_num_blocks(devcon->dev_phone, nblocks); 835 devcon_t *devcon = devcon_search(devmap_handle); 836 assert(devcon); 837 838 return get_num_blocks(devcon->sess, nblocks); 839 } 840 841 /** Read bytes directly from the device (bypass cache) 842 * 843 * @param devmap_handle Device handle of the block device. 844 * @param abs_offset Absolute offset in bytes where to start reading 845 * @param bytes Number of bytes to read 846 * @param data Buffer that receives the data 847 * 848 * @return EOK on success or negative error code on failure. 849 */ 850 int block_read_bytes_direct(devmap_handle_t devmap_handle, aoff64_t abs_offset, 851 size_t bytes, void *data) 852 { 853 int rc; 854 size_t phys_block_size; 855 size_t buf_size; 856 void *buffer; 857 aoff64_t first_block; 858 aoff64_t last_block; 859 size_t blocks; 860 size_t offset; 861 862 rc = block_get_bsize(devmap_handle, &phys_block_size); 863 if (rc != EOK) { 864 return rc; 865 } 866 867 /* calculate data position and required space */ 868 first_block = abs_offset / phys_block_size; 869 offset = abs_offset % phys_block_size; 870 last_block = (abs_offset + bytes - 1) / phys_block_size; 871 blocks = last_block - first_block + 1; 872 buf_size = blocks * phys_block_size; 873 874 /* read the data into memory */ 875 buffer = malloc(buf_size); 876 if (buffer == NULL) { 877 return ENOMEM; 878 } 879 880 rc = block_read_direct(devmap_handle, first_block, blocks, buffer); 881 if (rc != EOK) { 882 free(buffer); 883 return rc; 884 } 885 886 /* copy the data from the buffer */ 887 memcpy(data, buffer + offset, bytes); 888 free(buffer); 889 890 return EOK; 827 891 } 828 892 … … 838 902 static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt) 839 903 { 840 int rc;841 842 as sert(devcon);843 rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba),904 assert(devcon); 905 906 async_exch_t *exch = async_exchange_begin(devcon->sess); 907 int rc = async_req_3_0(exch, BD_READ_BLOCKS, LOWER32(ba), 844 908 UPPER32(ba), cnt); 909 async_exchange_end(exch); 910 845 911 if (rc != EOK) { 846 912 printf("Error %d reading %zu blocks starting at block %" PRIuOFF64 … … 851 917 #endif 852 918 } 919 853 920 return rc; 854 921 } … … 865 932 static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt) 866 933 { 867 int rc;868 869 as sert(devcon);870 rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba),934 assert(devcon); 935 936 async_exch_t *exch = async_exchange_begin(devcon->sess); 937 int rc = async_req_3_0(exch, BD_WRITE_BLOCKS, LOWER32(ba), 871 938 UPPER32(ba), cnt); 939 async_exchange_end(exch); 940 872 941 if (rc != EOK) { 873 942 printf("Error %d writing %zu blocks starting at block %" PRIuOFF64 … … 877 946 #endif 878 947 } 948 879 949 return rc; 880 950 } 881 951 882 952 /** Get block size used by the device. */ 883 static int get_block_size( int dev_phone, size_t *bsize)953 static int get_block_size(async_sess_t *sess, size_t *bsize) 884 954 { 885 955 sysarg_t bs; 886 int rc; 887 888 rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs); 956 957 async_exch_t *exch = async_exchange_begin(sess); 958 int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bs); 959 async_exchange_end(exch); 960 889 961 if (rc == EOK) 890 962 *bsize = (size_t) bs; 891 963 892 964 return rc; 893 965 } 894 966 895 967 /** Get total number of blocks on block device. */ 896 static int get_num_blocks(int dev_phone, aoff64_t *nblocks) 897 { 898 sysarg_t nb_l, nb_h; 899 int rc; 900 901 rc = async_req_0_2(dev_phone, BD_GET_NUM_BLOCKS, &nb_l, &nb_h); 902 if (rc == EOK) { 968 static int get_num_blocks(async_sess_t *sess, aoff64_t *nblocks) 969 { 970 sysarg_t nb_l; 971 sysarg_t nb_h; 972 973 async_exch_t *exch = async_exchange_begin(sess); 974 int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h); 975 async_exchange_end(exch); 976 977 if (rc == EOK) 903 978 *nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h); 904 } 905 979 906 980 return rc; 907 981 }
Note:
See TracChangeset
for help on using the changeset viewer.