Changeset 04803bf in mainline for uspace/srv/bd/file_bd/file_bd.c
- Timestamp:
- 2011-03-21T22:00:17Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 143932e
- Parents:
- b50b5af2 (diff), 7308e84 (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 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/bd/file_bd/file_bd.c
rb50b5af2 r04803bf 41 41 #include <stdio.h> 42 42 #include <unistd.h> 43 #include <ipc/ipc.h>44 43 #include <ipc/bd.h> 45 44 #include <async.h> 46 45 #include <as.h> 47 #include <fibril_sync .h>46 #include <fibril_synch.h> 48 47 #include <devmap.h> 49 48 #include <sys/types.h> 49 #include <sys/typefmt.h> 50 50 #include <errno.h> 51 51 #include <bool.h> 52 52 #include <task.h> 53 #include <macros.h> 53 54 54 55 #define NAME "file_bd" 55 56 56 static size_t comm_size; 57 #define DEFAULT_BLOCK_SIZE 512 58 59 static size_t block_size; 60 static aoff64_t num_blocks; 57 61 static FILE *img; 58 62 59 static dev _handle_t dev_handle;63 static devmap_handle_t devmap_handle; 60 64 static fibril_mutex_t dev_lock; 61 65 66 static void print_usage(void); 62 67 static int file_bd_init(const char *fname); 63 68 static void file_bd_connection(ipc_callid_t iid, ipc_call_t *icall); 64 static int file_bd_read (off_t blk_idx, size_t size, void *buf);65 static int file_bd_write (off_t blk_idx, size_t size,void *buf);69 static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf); 70 static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf); 66 71 67 72 int main(int argc, char **argv) 68 73 { 69 74 int rc; 75 char *image_name; 76 char *device_name; 70 77 71 78 printf(NAME ": File-backed block device driver\n"); 72 79 73 if (argc != 3) { 74 printf("Expected two arguments (image name, device name).\n"); 80 block_size = DEFAULT_BLOCK_SIZE; 81 82 ++argv; --argc; 83 while (*argv != NULL && (*argv)[0] == '-') { 84 /* Option */ 85 if (str_cmp(*argv, "-b") == 0) { 86 if (argc < 2) { 87 printf("Argument missing.\n"); 88 print_usage(); 89 return -1; 90 } 91 92 rc = str_size_t(argv[1], NULL, 10, true, &block_size); 93 if (rc != EOK || block_size == 0) { 94 printf("Invalid block size '%s'.\n", argv[1]); 95 print_usage(); 96 return -1; 97 } 98 ++argv; --argc; 99 } else { 100 printf("Invalid option '%s'.\n", *argv); 101 print_usage(); 102 return -1; 103 } 104 ++argv; --argc; 105 } 106 107 if (argc < 2) { 108 printf("Missing arguments.\n"); 109 print_usage(); 75 110 return -1; 76 111 } 77 112 78 if (file_bd_init(argv[1]) != EOK) 113 image_name = argv[0]; 114 device_name = argv[1]; 115 116 if (file_bd_init(image_name) != EOK) 79 117 return -1; 80 118 81 rc = devmap_device_register( argv[2], &dev_handle);119 rc = devmap_device_register(device_name, &devmap_handle); 82 120 if (rc != EOK) { 83 devmap_hangup_phone(DEVMAP_DRIVER); 84 printf(NAME ": Unable to register device %s.\n", 85 argv[2]); 121 printf(NAME ": Unable to register device '%s'.\n", 122 device_name); 86 123 return rc; 87 124 } … … 95 132 } 96 133 134 static void print_usage(void) 135 { 136 printf("Usage: " NAME " [-b <block_size>] <image_file> <device_name>\n"); 137 } 138 97 139 static int file_bd_init(const char *fname) 98 140 { 99 141 int rc; 142 long img_size; 100 143 101 144 rc = devmap_driver_register(NAME, file_bd_connection); … … 109 152 return EINVAL; 110 153 154 if (fseek(img, 0, SEEK_END) != 0) { 155 fclose(img); 156 return EIO; 157 } 158 159 img_size = ftell(img); 160 if (img_size < 0) { 161 fclose(img); 162 return EIO; 163 } 164 165 num_blocks = img_size / block_size; 166 111 167 fibril_mutex_initialize(&dev_lock); 112 168 … … 119 175 ipc_callid_t callid; 120 176 ipc_call_t call; 121 ipcarg_t method; 122 int flags; 177 sysarg_t method; 178 size_t comm_size; 179 unsigned int flags; 123 180 int retval; 124 off_t idx;125 size_t size;181 uint64_t ba; 182 size_t cnt; 126 183 127 184 /* Answer the IPC_M_CONNECT_ME_TO call. */ 128 ipc_answer_0(iid, EOK);129 130 if (! ipc_share_out_receive(&callid, &comm_size, &flags)) {131 ipc_answer_0(callid, EHANGUP);185 async_answer_0(iid, EOK); 186 187 if (!async_share_out_receive(&callid, &comm_size, &flags)) { 188 async_answer_0(callid, EHANGUP); 132 189 return; 133 190 } … … 135 192 fs_va = as_get_mappable_page(comm_size); 136 193 if (fs_va == NULL) { 137 ipc_answer_0(callid, EHANGUP);194 async_answer_0(callid, EHANGUP); 138 195 return; 139 196 } 140 197 141 (void) ipc_share_out_finalize(callid, fs_va);198 (void) async_share_out_finalize(callid, fs_va); 142 199 143 200 while (1) { 144 201 callid = async_get_call(&call); 145 method = IPC_GET_ METHOD(call);202 method = IPC_GET_IMETHOD(call); 146 203 switch (method) { 147 204 case IPC_M_PHONE_HUNGUP: 148 205 /* The other side has hung up. */ 149 ipc_answer_0(callid, EOK);206 async_answer_0(callid, EOK); 150 207 return; 151 case BD_READ_BLOCK :152 case BD_WRITE_BLOCK:153 idx = IPC_GET_ARG1(call);154 size = IPC_GET_ARG2(call);155 if ( size > comm_size) {156 retval = E INVAL;208 case BD_READ_BLOCKS: 209 ba = MERGE_LOUP32(IPC_GET_ARG1(call), 210 IPC_GET_ARG2(call)); 211 cnt = IPC_GET_ARG3(call); 212 if (cnt * block_size > comm_size) { 213 retval = ELIMIT; 157 214 break; 158 215 } 159 if (method == BD_READ_BLOCK) 160 retval = file_bd_read(idx, size, fs_va); 161 else 162 retval = file_bd_write(idx, size, fs_va); 216 retval = file_bd_read_blocks(ba, cnt, fs_va); 163 217 break; 218 case BD_WRITE_BLOCKS: 219 ba = MERGE_LOUP32(IPC_GET_ARG1(call), 220 IPC_GET_ARG2(call)); 221 cnt = IPC_GET_ARG3(call); 222 if (cnt * block_size > comm_size) { 223 retval = ELIMIT; 224 break; 225 } 226 retval = file_bd_write_blocks(ba, cnt, fs_va); 227 break; 228 case BD_GET_BLOCK_SIZE: 229 async_answer_1(callid, EOK, block_size); 230 continue; 231 case BD_GET_NUM_BLOCKS: 232 async_answer_2(callid, EOK, LOWER32(num_blocks), 233 UPPER32(num_blocks)); 234 continue; 164 235 default: 165 236 retval = EINVAL; 166 237 break; 167 238 } 168 ipc_answer_0(callid, retval); 169 } 170 } 171 172 static int file_bd_read(off_t blk_idx, size_t size, void *buf) 239 async_answer_0(callid, retval); 240 } 241 } 242 243 /** Read blocks from the device. */ 244 static int file_bd_read_blocks(uint64_t ba, size_t cnt, void *buf) 173 245 { 174 246 size_t n_rd; 247 int rc; 248 249 /* Check whether access is within device address bounds. */ 250 if (ba + cnt > num_blocks) { 251 printf(NAME ": Accessed blocks %" PRIuOFF64 "-%" PRIuOFF64 ", while " 252 "max block number is %" PRIuOFF64 ".\n", ba, ba + cnt - 1, 253 num_blocks - 1); 254 return ELIMIT; 255 } 175 256 176 257 fibril_mutex_lock(&dev_lock); 177 258 178 fseek(img, blk_idx * size, SEEK_SET); 179 n_rd = fread(buf, 1, size, img); 259 clearerr(img); 260 rc = fseek(img, ba * block_size, SEEK_SET); 261 if (rc < 0) { 262 fibril_mutex_unlock(&dev_lock); 263 return EIO; 264 } 265 266 n_rd = fread(buf, block_size, cnt, img); 180 267 181 268 if (ferror(img)) { … … 186 273 fibril_mutex_unlock(&dev_lock); 187 274 188 if (n_rd < size)189 return EINVAL; /* Read beyond end of d isk*/275 if (n_rd < cnt) 276 return EINVAL; /* Read beyond end of device */ 190 277 191 278 return EOK; 192 279 } 193 280 194 static int file_bd_write(off_t blk_idx, size_t size, void *buf) 281 /** Write blocks to the device. */ 282 static int file_bd_write_blocks(uint64_t ba, size_t cnt, const void *buf) 195 283 { 196 284 size_t n_wr; 285 int rc; 286 287 /* Check whether access is within device address bounds. */ 288 if (ba + cnt > num_blocks) { 289 printf(NAME ": Accessed blocks %" PRIuOFF64 "-%" PRIuOFF64 ", while " 290 "max block number is %" PRIuOFF64 ".\n", ba, ba + cnt - 1, 291 num_blocks - 1); 292 return ELIMIT; 293 } 197 294 198 295 fibril_mutex_lock(&dev_lock); 199 296 200 fseek(img, blk_idx * size, SEEK_SET); 201 n_wr = fread(buf, 1, size, img); 202 203 if (ferror(img) || n_wr < size) { 297 clearerr(img); 298 rc = fseek(img, ba * block_size, SEEK_SET); 299 if (rc < 0) { 300 fibril_mutex_unlock(&dev_lock); 301 return EIO; 302 } 303 304 n_wr = fwrite(buf, block_size, cnt, img); 305 306 if (ferror(img) || n_wr < cnt) { 204 307 fibril_mutex_unlock(&dev_lock); 205 308 return EIO; /* Write error */ 309 } 310 311 if (fflush(img) != 0) { 312 fibril_mutex_unlock(&dev_lock); 313 return EIO; 206 314 } 207 315
Note:
See TracChangeset
for help on using the changeset viewer.