Changes in uspace/lib/block/libblock.c [79ae36dd:5716e9a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/block/libblock.c
r79ae36dd r5716e9a 2 2 * Copyright (c) 2008 Jakub Jermar 3 3 * Copyright (c) 2008 Martin Decky 4 * Copyright (c) 2011 Martin Sucha5 4 * All rights reserved. 6 5 * … … 52 51 #include <macros.h> 53 52 #include <mem.h> 54 #include <malloc.h>55 #include <stdio.h>56 53 #include <sys/typefmt.h> 57 54 #include <stacktrace.h> … … 62 59 static LIST_INITIALIZE(dcl_head); 63 60 64 #define CACHE_BUCKETS_LOG2 65 #define CACHE_BUCKETS 61 #define CACHE_BUCKETS_LOG2 10 62 #define CACHE_BUCKETS (1 << CACHE_BUCKETS_LOG2) 66 63 67 64 typedef struct { 68 65 fibril_mutex_t lock; 69 size_t lblock_size; 70 unsigned blocks_cluster; 71 unsigned block_count; 72 unsigned blocks_cached; 66 size_t lblock_size; /**< Logical block size. */ 67 unsigned blocks_cluster; /**< Physical blocks per block_t */ 68 unsigned block_count; /**< Total number of blocks. */ 69 unsigned blocks_cached; /**< Number of cached blocks. */ 73 70 hash_table_t block_hash; 74 71 link_t free_head; … … 79 76 link_t link; 80 77 devmap_handle_t devmap_handle; 81 async_sess_t *sess;78 int dev_phone; 82 79 fibril_mutex_t comm_area_lock; 83 80 void *comm_area; … … 85 82 void *bb_buf; 86 83 aoff64_t bb_addr; 87 size_t pblock_size; 84 size_t pblock_size; /**< Physical block size. */ 88 85 cache_t *cache; 89 86 } devcon_t; 90 87 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);88 static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt); 89 static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt); 90 static int get_block_size(int dev_phone, size_t *bsize); 91 static int get_num_blocks(int dev_phone, aoff64_t *nblocks); 92 static aoff64_t ba_ltop(devcon_t *devcon, aoff64_t lba); 96 93 97 94 static devcon_t *devcon_search(devmap_handle_t devmap_handle) 98 95 { 99 96 link_t *cur; 100 97 101 98 fibril_mutex_lock(&dcl_lock); 102 103 99 for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { 104 100 devcon_t *devcon = list_get_instance(cur, devcon_t, link); … … 108 104 } 109 105 } 110 111 106 fibril_mutex_unlock(&dcl_lock); 112 107 return NULL; 113 108 } 114 109 115 static int devcon_add(devmap_handle_t devmap_handle, async_sess_t *sess,116 size_t bsize,void *comm_area, size_t comm_size)110 static int devcon_add(devmap_handle_t devmap_handle, int dev_phone, size_t bsize, 111 void *comm_area, size_t comm_size) 117 112 { 118 113 link_t *cur; 119 114 devcon_t *devcon; 120 115 121 116 if (comm_size < bsize) 122 117 return EINVAL; 123 118 124 119 devcon = malloc(sizeof(devcon_t)); 125 120 if (!devcon) … … 128 123 link_initialize(&devcon->link); 129 124 devcon->devmap_handle = devmap_handle; 130 devcon-> sess = sess;125 devcon->dev_phone = dev_phone; 131 126 fibril_mutex_initialize(&devcon->comm_area_lock); 132 127 devcon->comm_area = comm_area; … … 136 131 devcon->pblock_size = bsize; 137 132 devcon->cache = NULL; 138 133 139 134 fibril_mutex_lock(&dcl_lock); 140 135 for (cur = dcl_head.next; cur != &dcl_head; cur = cur->next) { … … 158 153 } 159 154 160 int block_init(exch_mgmt_t mgmt, devmap_handle_t devmap_handle, 161 size_t comm_size) 162 { 163 void *comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE, 155 int block_init(devmap_handle_t devmap_handle, size_t comm_size) 156 { 157 int rc; 158 int dev_phone; 159 void *comm_area; 160 size_t bsize; 161 162 comm_area = mmap(NULL, comm_size, PROTO_READ | PROTO_WRITE, 164 163 MAP_ANONYMOUS | MAP_PRIVATE, 0, 0); 165 if (!comm_area) 164 if (!comm_area) { 166 165 return ENOMEM; 167 168 async_sess_t *sess = devmap_device_connect(mgmt, devmap_handle, 169 170 if ( !sess) {166 } 167 168 dev_phone = devmap_device_connect(devmap_handle, IPC_FLAG_BLOCKING); 169 if (dev_phone < 0) { 171 170 munmap(comm_area, comm_size); 172 return ENOENT; 173 } 174 175 async_exch_t *exch = async_exchange_begin(sess); 176 int rc = async_share_out_start(exch, comm_area, 171 return dev_phone; 172 } 173 174 rc = async_share_out_start(dev_phone, comm_area, 177 175 AS_AREA_READ | AS_AREA_WRITE); 178 async_exchange_end(exch); 179 176 if (rc != EOK) { 177 munmap(comm_area, comm_size); 178 async_hangup(dev_phone); 179 return rc; 180 } 181 182 if (get_block_size(dev_phone, &bsize) != EOK) { 183 munmap(comm_area, comm_size); 184 async_hangup(dev_phone); 185 return rc; 186 } 187 188 rc = devcon_add(devmap_handle, dev_phone, bsize, comm_area, comm_size); 180 189 if (rc != EOK) { 181 190 munmap(comm_area, comm_size); 182 async_hangup( sess);191 async_hangup(dev_phone); 183 192 return rc; 184 193 } 185 186 size_t bsize; 187 rc = get_block_size(sess, &bsize); 188 189 if (rc != EOK) { 190 munmap(comm_area, comm_size); 191 async_hangup(sess); 192 return rc; 193 } 194 195 rc = devcon_add(devmap_handle, sess, bsize, comm_area, comm_size); 196 if (rc != EOK) { 197 munmap(comm_area, comm_size); 198 async_hangup(sess); 199 return rc; 200 } 201 194 202 195 return EOK; 203 196 } … … 210 203 if (devcon->cache) 211 204 (void) block_cache_fini(devmap_handle); 212 205 213 206 devcon_remove(devcon); 214 207 215 208 if (devcon->bb_buf) 216 209 free(devcon->bb_buf); 217 210 218 211 munmap(devcon->comm_area, devcon->comm_size); 219 async_hangup(devcon-> sess);220 221 free(devcon); 212 async_hangup(devcon->dev_phone); 213 214 free(devcon); 222 215 } 223 216 … … 812 805 assert(devcon); 813 806 814 return get_block_size(devcon-> sess, bsize);807 return get_block_size(devcon->dev_phone, bsize); 815 808 } 816 809 … … 824 817 int block_get_nblocks(devmap_handle_t devmap_handle, aoff64_t *nblocks) 825 818 { 826 devcon_t *devcon = devcon_search(devmap_handle); 827 assert(devcon); 828 829 return get_num_blocks(devcon->sess, nblocks); 830 } 831 832 /** Read bytes directly from the device (bypass cache) 833 * 834 * @param devmap_handle Device handle of the block device. 835 * @param abs_offset Absolute offset in bytes where to start reading 836 * @param bytes Number of bytes to read 837 * @param data Buffer that receives the data 838 * 839 * @return EOK on success or negative error code on failure. 840 */ 841 int block_read_bytes_direct(devmap_handle_t devmap_handle, aoff64_t abs_offset, 842 size_t bytes, void *data) 843 { 844 int rc; 845 size_t phys_block_size; 846 size_t buf_size; 847 void *buffer; 848 aoff64_t first_block; 849 aoff64_t last_block; 850 size_t blocks; 851 size_t offset; 852 853 rc = block_get_bsize(devmap_handle, &phys_block_size); 854 if (rc != EOK) { 855 return rc; 856 } 857 858 /* calculate data position and required space */ 859 first_block = abs_offset / phys_block_size; 860 offset = abs_offset % phys_block_size; 861 last_block = (abs_offset + bytes - 1) / phys_block_size; 862 blocks = last_block - first_block + 1; 863 buf_size = blocks * phys_block_size; 864 865 /* read the data into memory */ 866 buffer = malloc(buf_size); 867 if (buffer == NULL) { 868 return ENOMEM; 869 } 870 871 rc = block_read_direct(devmap_handle, first_block, blocks, buffer); 872 if (rc != EOK) { 873 free(buffer); 874 return rc; 875 } 876 877 /* copy the data from the buffer */ 878 memcpy(data, buffer + offset, bytes); 879 free(buffer); 880 881 return EOK; 819 devcon_t *devcon; 820 821 devcon = devcon_search(devmap_handle); 822 assert(devcon); 823 824 return get_num_blocks(devcon->dev_phone, nblocks); 882 825 } 883 826 … … 893 836 static int read_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt) 894 837 { 895 assert(devcon);896 897 as ync_exch_t *exch = async_exchange_begin(devcon->sess);898 int rc = async_req_3_0(exch, BD_READ_BLOCKS, LOWER32(ba),838 int rc; 839 840 assert(devcon); 841 rc = async_req_3_0(devcon->dev_phone, BD_READ_BLOCKS, LOWER32(ba), 899 842 UPPER32(ba), cnt); 900 async_exchange_end(exch);901 902 843 if (rc != EOK) { 903 844 printf("Error %d reading %zu blocks starting at block %" PRIuOFF64 … … 908 849 #endif 909 850 } 910 911 851 return rc; 912 852 } … … 923 863 static int write_blocks(devcon_t *devcon, aoff64_t ba, size_t cnt) 924 864 { 925 assert(devcon);926 927 as ync_exch_t *exch = async_exchange_begin(devcon->sess);928 int rc = async_req_3_0(exch, BD_WRITE_BLOCKS, LOWER32(ba),865 int rc; 866 867 assert(devcon); 868 rc = async_req_3_0(devcon->dev_phone, BD_WRITE_BLOCKS, LOWER32(ba), 929 869 UPPER32(ba), cnt); 930 async_exchange_end(exch);931 932 870 if (rc != EOK) { 933 871 printf("Error %d writing %zu blocks starting at block %" PRIuOFF64 … … 937 875 #endif 938 876 } 939 940 877 return rc; 941 878 } 942 879 943 880 /** Get block size used by the device. */ 944 static int get_block_size( async_sess_t *sess, size_t *bsize)881 static int get_block_size(int dev_phone, size_t *bsize) 945 882 { 946 883 sysarg_t bs; 947 948 async_exch_t *exch = async_exchange_begin(sess); 949 int rc = async_req_0_1(exch, BD_GET_BLOCK_SIZE, &bs); 950 async_exchange_end(exch); 951 884 int rc; 885 886 rc = async_req_0_1(dev_phone, BD_GET_BLOCK_SIZE, &bs); 952 887 if (rc == EOK) 953 888 *bsize = (size_t) bs; 954 889 955 890 return rc; 956 891 } 957 892 958 893 /** Get total number of blocks on block device. */ 959 static int get_num_blocks(async_sess_t *sess, aoff64_t *nblocks) 960 { 961 sysarg_t nb_l; 962 sysarg_t nb_h; 963 964 async_exch_t *exch = async_exchange_begin(sess); 965 int rc = async_req_0_2(exch, BD_GET_NUM_BLOCKS, &nb_l, &nb_h); 966 async_exchange_end(exch); 967 968 if (rc == EOK) 894 static int get_num_blocks(int dev_phone, aoff64_t *nblocks) 895 { 896 sysarg_t nb_l, nb_h; 897 int rc; 898 899 rc = async_req_0_2(dev_phone, BD_GET_NUM_BLOCKS, &nb_l, &nb_h); 900 if (rc == EOK) { 969 901 *nblocks = (aoff64_t) MERGE_LOUP32(nb_l, nb_h); 970 902 } 903 971 904 return rc; 972 905 }
Note:
See TracChangeset
for help on using the changeset viewer.