Changes in / [f2f89315:ff62c6d] in mainline
- Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/cmds/modules/bdd/bdd.c
rf2f89315 rff62c6d 40 40 #include <devmap.h> 41 41 #include <errno.h> 42 #include <assert.h> 42 43 43 44 #define BLOCK_SIZE 512 … … 110 111 111 112 while (size > 0) { 112 block = block_get(handle, boff, 0); 113 rc = block_get(&block, handle, boff, 0); 114 assert(rc == EOK); 113 115 blk = (uint8_t *) block->data; 114 116 … … 139 141 } 140 142 141 block_put(block); 143 rc = block_put(block); 144 assert(rc == EOK); 142 145 143 146 if (size > rows * BPR) -
uspace/lib/libblock/libblock.c
rf2f89315 rff62c6d 306 306 b->refcnt = 1; 307 307 b->dirty = false; 308 b->toxic = false; 308 309 fibril_rwlock_initialize(&b->contents_lock); 309 310 link_initialize(&b->free_link); … … 313 314 /** Instantiate a block in memory and get a reference to it. 314 315 * 316 * @param block Pointer to where the function will store the 317 * block pointer on success. 315 318 * @param dev_handle Device handle of the block device. 316 319 * @param boff Block offset. … … 319 322 * device. 320 323 * 321 * @return Block structure.322 */ 323 block_t *block_get(dev_handle_t dev_handle, bn_t boff, int flags)324 * @return EOK on success or a negative error code. 325 */ 326 int block_get(block_t **block, dev_handle_t dev_handle, bn_t boff, int flags) 324 327 { 325 328 devcon_t *devcon; … … 328 331 link_t *l; 329 332 unsigned long key = boff; 330 bn_t oboff;333 int rc = EOK; 331 334 332 335 devcon = devcon_search(dev_handle); … … 336 339 337 340 cache = devcon->cache; 341 342 retry: 338 343 fibril_mutex_lock(&cache->lock); 339 344 l = hash_table_find(&cache->block_hash, &key); … … 346 351 if (b->refcnt++ == 0) 347 352 list_remove(&b->free_link); 353 if (b->toxic) 354 rc = EIO; 348 355 fibril_mutex_unlock(&b->lock); 349 356 fibril_mutex_unlock(&cache->lock); … … 352 359 * The block was not found in the cache. 353 360 */ 354 int rc;355 bool sync = false;356 357 361 if (cache_can_grow(cache)) { 358 362 /* … … 378 382 assert(!list_empty(&cache->free_head)); 379 383 l = cache->free_head.next; 380 list_remove(l);381 384 b = list_get_instance(l, block_t, free_link); 382 sync = b->dirty; 383 oboff = b->boff; 385 386 fibril_mutex_lock(&b->lock); 387 if (b->dirty) { 388 /* 389 * The block needs to be written back to the 390 * device before it changes identity. Do this 391 * while not holding the cache lock so that 392 * concurrency is not impeded. Also move the 393 * block to the end of the free list so that we 394 * do not slow down other instances of 395 * block_get() draining the free list. 396 */ 397 list_remove(&b->free_link); 398 list_append(&b->free_link, &cache->free_head); 399 fibril_mutex_unlock(&cache->lock); 400 fibril_mutex_lock(&devcon->com_area_lock); 401 memcpy(devcon->com_area, b->data, b->size); 402 rc = write_block(devcon, b->boff, 403 cache->block_size); 404 fibril_mutex_unlock(&devcon->com_area_lock); 405 if (rc != EOK) { 406 /* 407 * We did not manage to write the block 408 * to the device. Keep it around for 409 * another try. Hopefully, we will grab 410 * another block next time. 411 */ 412 fibril_mutex_unlock(&b->lock); 413 goto retry; 414 } 415 b->dirty = false; 416 if (!fibril_mutex_trylock(&cache->lock)) { 417 /* 418 * Somebody is probably racing with us. 419 * Unlock the block and retry. 420 */ 421 fibril_mutex_unlock(&b->lock); 422 goto retry; 423 } 424 425 } 426 fibril_mutex_unlock(&b->lock); 427 428 /* 429 * Unlink the block from the free list and the hash 430 * table. 431 */ 432 list_remove(&b->free_link); 384 433 temp_key = b->boff; 385 434 hash_table_remove(&cache->block_hash, &temp_key, 1); … … 394 443 /* 395 444 * Lock the block before releasing the cache lock. Thus we don't 396 * kill concur ent operations on the cache while doing I/O on the397 * block.445 * kill concurrent operations on the cache while doing I/O on 446 * the block. 398 447 */ 399 448 fibril_mutex_lock(&b->lock); 400 449 fibril_mutex_unlock(&cache->lock); 401 450 402 if (sync) {403 /*404 * The block is dirty and needs to be written back to405 * the device before we can read in the new contents.406 */407 fibril_mutex_lock(&devcon->com_area_lock);408 memcpy(devcon->com_area, b->data, b->size);409 rc = write_block(devcon, oboff, cache->block_size);410 assert(rc == EOK);411 fibril_mutex_unlock(&devcon->com_area_lock);412 }413 451 if (!(flags & BLOCK_FLAGS_NOREAD)) { 414 452 /* … … 418 456 fibril_mutex_lock(&devcon->com_area_lock); 419 457 rc = read_block(devcon, b->boff, cache->block_size); 420 assert(rc == EOK);421 458 memcpy(b->data, devcon->com_area, cache->block_size); 422 459 fibril_mutex_unlock(&devcon->com_area_lock); 423 } 460 if (rc != EOK) 461 b->toxic = true; 462 } else 463 rc = EOK; 424 464 425 465 fibril_mutex_unlock(&b->lock); 426 466 } 427 return b; 467 *block = b; 468 return rc; 428 469 } 429 470 … … 433 474 * 434 475 * @param block Block of which a reference is to be released. 435 */ 436 void block_put(block_t *block) 476 * 477 * @return EOK on success or a negative error code. 478 */ 479 int block_put(block_t *block) 437 480 { 438 481 devcon_t *devcon = devcon_search(block->dev_handle); 439 482 cache_t *cache; 440 int rc; 483 unsigned blocks_cached; 484 enum cache_mode mode; 485 int rc = EOK; 441 486 442 487 assert(devcon); … … 444 489 445 490 cache = devcon->cache; 491 492 retry: 493 fibril_mutex_lock(&cache->lock); 494 blocks_cached = cache->blocks_cached; 495 mode = cache->mode; 496 fibril_mutex_unlock(&cache->lock); 497 498 /* 499 * Determine whether to sync the block. Syncing the block is best done 500 * when not holding the cache lock as it does not impede concurrency. 501 * Since the situation may have changed when we unlocked the cache, the 502 * blocks_cached and mode variables are mere hints. We will recheck the 503 * conditions later when the cache lock is held again. 504 */ 505 fibril_mutex_lock(&block->lock); 506 if (block->toxic) 507 block->dirty = false; /* will not write back toxic block */ 508 if (block->dirty && (block->refcnt == 1) && 509 (blocks_cached > CACHE_HI_WATERMARK || mode != CACHE_MODE_WB)) { 510 fibril_mutex_lock(&devcon->com_area_lock); 511 memcpy(devcon->com_area, block->data, block->size); 512 rc = write_block(devcon, block->boff, block->size); 513 fibril_mutex_unlock(&devcon->com_area_lock); 514 block->dirty = false; 515 } 516 fibril_mutex_unlock(&block->lock); 517 446 518 fibril_mutex_lock(&cache->lock); 447 519 fibril_mutex_lock(&block->lock); … … 449 521 /* 450 522 * Last reference to the block was dropped. Either free the 451 * block or put it on the free list. 523 * block or put it on the free list. In case of an I/O error, 524 * free the block. 452 525 */ 453 if (cache->blocks_cached > CACHE_HI_WATERMARK) { 454 /* 455 * Currently there are too many cached blocks. 526 if ((cache->blocks_cached > CACHE_HI_WATERMARK) || 527 (rc != EOK)) { 528 /* 529 * Currently there are too many cached blocks or there 530 * was an I/O error when writing the block back to the 531 * device. 456 532 */ 457 533 if (block->dirty) { 458 fibril_mutex_lock(&devcon->com_area_lock); 459 memcpy(devcon->com_area, block->data, 460 block->size); 461 rc = write_block(devcon, block->boff, 462 block->size); 463 assert(rc == EOK); 464 fibril_mutex_unlock(&devcon->com_area_lock); 534 /* 535 * We cannot sync the block while holding the 536 * cache lock. Release everything and retry. 537 */ 538 block->refcnt++; 539 fibril_mutex_unlock(&block->lock); 540 fibril_mutex_unlock(&cache->lock); 541 goto retry; 465 542 } 466 543 /* … … 473 550 cache->blocks_cached--; 474 551 fibril_mutex_unlock(&cache->lock); 475 return ;552 return rc; 476 553 } 477 554 /* 478 555 * Put the block on the free list. 479 556 */ 557 if (cache->mode != CACHE_MODE_WB && block->dirty) { 558 /* 559 * We cannot sync the block while holding the cache 560 * lock. Release everything and retry. 561 */ 562 block->refcnt++; 563 fibril_mutex_unlock(&block->lock); 564 fibril_mutex_unlock(&cache->lock); 565 goto retry; 566 } 480 567 list_append(&block->free_link, &cache->free_head); 481 if (cache->mode != CACHE_MODE_WB && block->dirty) {482 fibril_mutex_lock(&devcon->com_area_lock);483 memcpy(devcon->com_area, block->data, block->size);484 rc = write_block(devcon, block->boff, block->size);485 assert(rc == EOK);486 fibril_mutex_unlock(&devcon->com_area_lock);487 488 block->dirty = false;489 }490 568 } 491 569 fibril_mutex_unlock(&block->lock); 492 570 fibril_mutex_unlock(&cache->lock); 571 572 return rc; 493 573 } 494 574 -
uspace/lib/libblock/libblock.h
rf2f89315 rff62c6d 69 69 /** If true, the block needs to be written back to the block device. */ 70 70 bool dirty; 71 /** If true, the blcok does not contain valid data. */ 72 bool toxic; 71 73 /** Readers / Writer lock protecting the contents of the block. */ 72 74 fibril_rwlock_t contents_lock; … … 101 103 extern int block_cache_init(dev_handle_t, size_t, unsigned, enum cache_mode); 102 104 103 extern block_t *block_get(dev_handle_t, bn_t, int);104 extern voidblock_put(block_t *);105 extern int block_get(block_t **, dev_handle_t, bn_t, int); 106 extern int block_put(block_t *); 105 107 106 108 extern int block_seqread(dev_handle_t, off_t *, size_t *, off_t *, void *, -
uspace/srv/fs/fat/fat_fat.c
rf2f89315 rff62c6d 75 75 uint16_t clusters = 0; 76 76 fat_cluster_t clst = firstc; 77 int rc; 77 78 78 79 bps = uint16_t_le2host(bs->bps); … … 96 97 fidx = clst % (bps / sizeof(fat_cluster_t)); 97 98 /* read FAT1 */ 98 b = block_get(dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE); 99 rc = block_get(&b, dev_handle, rscnt + fsec, BLOCK_FLAGS_NONE); 100 assert(rc == EOK); 99 101 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]); 100 102 assert(clst != FAT_CLST_BAD); 101 block_put(b); 103 rc = block_put(b); 104 assert(rc == EOK); 102 105 clusters++; 103 106 } … … 133 136 unsigned clusters, max_clusters; 134 137 fat_cluster_t lastc; 138 int rc; 135 139 136 140 bps = uint16_t_le2host(bs->bps); … … 146 150 /* root directory special case */ 147 151 assert(bn < rds); 148 b = block_get(dev_handle, rscnt + bs->fatcnt * sf + bn, flags); 152 rc = block_get(&b, dev_handle, rscnt + bs->fatcnt * sf + bn, 153 flags); 154 assert(rc == EOK); 149 155 return b; 150 156 } … … 155 161 assert(clusters == max_clusters); 156 162 157 b = block_get(dev_handle, ssa + (lastc - FAT_CLST_FIRST) * bs->spc + 158 bn % bs->spc, flags); 163 rc = block_get(&b, dev_handle, ssa + 164 (lastc - FAT_CLST_FIRST) * bs->spc + bn % bs->spc, flags); 165 assert(rc == EOK); 159 166 160 167 return b; … … 177 184 block_t *b; 178 185 off_t o, boundary; 186 int rc; 179 187 180 188 bps = uint16_t_le2host(bs->bps); … … 191 199 memset(b->data + o % bps, 0, bps - o % bps); 192 200 b->dirty = true; /* need to sync node */ 193 block_put(b); 201 rc = block_put(b); 202 assert(rc == EOK); 194 203 } 195 204 … … 203 212 memset(b->data, 0, min(bps, pos - o)); 204 213 b->dirty = true; /* need to sync node */ 205 block_put(b); 214 rc = block_put(b); 215 assert(rc == EOK); 206 216 } 207 217 } … … 222 232 uint16_t rscnt; 223 233 fat_cluster_t *cp, value; 234 int rc; 224 235 225 236 bps = uint16_t_le2host(bs->bps); 226 237 rscnt = uint16_t_le2host(bs->rscnt); 227 238 228 b = block_get(dev_handle, rscnt + (clst * sizeof(fat_cluster_t)) / bps, 229 BLOCK_FLAGS_NONE); 239 rc = block_get(&b, dev_handle, rscnt + 240 (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE); 241 assert(rc == EOK); 230 242 cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); 231 243 value = uint16_t_le2host(*cp); 232 block_put(b); 244 rc = block_put(b); 245 assert(rc == EOK); 233 246 234 247 return value; … … 252 265 uint16_t sf; 253 266 fat_cluster_t *cp; 267 int rc; 254 268 255 269 bps = uint16_t_le2host(bs->bps); … … 258 272 259 273 assert(fatno < bs->fatcnt); 260 b = block_get(dev_handle, rscnt + sf * fatno +274 rc = block_get(&b, dev_handle, rscnt + sf * fatno + 261 275 (clst * sizeof(fat_cluster_t)) / bps, BLOCK_FLAGS_NONE); 276 assert(rc == EOK); 262 277 cp = (fat_cluster_t *)b->data + clst % (bps / sizeof(fat_cluster_t)); 263 278 *cp = host2uint16_t_le(value); 264 279 b->dirty = true; /* need to sync block */ 265 block_put(b); 280 rc = block_put(b); 281 assert(rc == EOK); 266 282 } 267 283 … … 315 331 unsigned found = 0; /* top of the free cluster number stack */ 316 332 unsigned b, c, cl; 333 int rc; 317 334 318 335 lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t)); … … 329 346 fibril_mutex_lock(&fat_alloc_lock); 330 347 for (b = 0, cl = 0; b < sf; b++) { 331 blk = block_get(dev_handle, rscnt + b, BLOCK_FLAGS_NONE);348 rc = block_get(&blk, dev_handle, rscnt + b, BLOCK_FLAGS_NONE); 332 349 for (c = 0; c < bps / sizeof(fat_cluster_t); c++, cl++) { 333 350 fat_cluster_t *clst = (fat_cluster_t *)blk->data + c; … … 344 361 if (++found == nclsts) { 345 362 /* we are almost done */ 346 block_put(blk); 363 rc = block_put(blk); 364 assert(rc == EOK); 347 365 /* update the shadow copies of FAT */ 348 366 fat_alloc_shadow_clusters(bs, … … 356 374 } 357 375 } 358 block_put(blk); 376 rc = block_put(blk); 377 assert(rc == EOK); 359 378 } 360 379 fibril_mutex_unlock(&fat_alloc_lock); … … 457 476 block_t *b; 458 477 unsigned bps; 478 int rc; 459 479 460 480 bps = uint16_t_le2host(bs->bps); … … 464 484 memset(b->data, 0, bps); 465 485 b->dirty = true; 466 block_put(b); 486 rc = block_put(b); 487 assert(rc == EOK); 467 488 } 468 489 } -
uspace/srv/fs/fat/fat_ops.c
rf2f89315 rff62c6d 85 85 uint16_t bps; 86 86 unsigned dps; 87 int rc; 87 88 88 89 assert(node->dirty); … … 108 109 109 110 b->dirty = true; /* need to sync block */ 110 block_put(b); 111 rc = block_put(b); 112 assert(rc == EOK); 111 113 } 112 114 … … 170 172 unsigned spc; 171 173 unsigned dps; 174 int rc; 172 175 173 176 if (idxp->nodep) { … … 226 229 nodep->refcnt = 1; 227 230 228 block_put(b); 231 rc = block_put(b); 232 assert(rc == EOK); 229 233 230 234 /* Link the idx structure with the node structure. */ … … 443 447 } 444 448 } 445 block_put(b); 449 rc = block_put(b); 450 assert(rc == EOK); 446 451 } 447 452 j = 0; … … 477 482 fat_dentry_name_set(d, name); 478 483 b->dirty = true; /* need to sync block */ 479 block_put(b); 484 rc = block_put(b); 485 assert(rc == EOK); 480 486 fibril_mutex_unlock(&parentp->idx->lock); 481 487 … … 512 518 } 513 519 b->dirty = true; /* need to sync block */ 514 block_put(b); 520 rc = block_put(b); 521 assert(rc == EOK); 515 522 516 523 childp->idx->pfc = parentp->firstc; … … 539 546 uint16_t bps; 540 547 block_t *b; 548 int rc; 541 549 542 550 if (!parentp) … … 561 569 d->name[0] = FAT_DENTRY_ERASED; 562 570 b->dirty = true; /* need to sync block */ 563 block_put(b); 571 rc = block_put(b); 572 assert(rc == EOK); 564 573 565 574 /* remove the index structure from the position hash */ … … 588 597 fat_dentry_t *d; 589 598 block_t *b; 599 int rc; 590 600 591 601 fibril_mutex_lock(&parentp->idx->lock); … … 603 613 continue; 604 614 case FAT_DENTRY_LAST: 605 block_put(b); 615 rc = block_put(b); 616 assert(rc == EOK); 606 617 fibril_mutex_unlock(&parentp->idx->lock); 607 618 return NULL; … … 629 640 * run out of 32-bit indices. 630 641 */ 631 block_put(b); 642 rc = block_put(b); 643 assert(rc == EOK); 632 644 return NULL; 633 645 } 634 646 nodep = fat_node_get_core(idx); 635 647 fibril_mutex_unlock(&idx->lock); 636 block_put(b); 648 rc = block_put(b); 649 assert(rc == EOK); 637 650 return FS_NODE(nodep); 638 651 } 639 652 } 640 block_put(b); 653 rc = block_put(b); 654 assert(rc == EOK); 641 655 } 642 656 … … 669 683 block_t *b; 670 684 unsigned i, j; 685 int rc; 671 686 672 687 if (nodep->type != FAT_DIRECTORY) … … 691 706 continue; 692 707 case FAT_DENTRY_LAST: 693 block_put(b); 708 rc = block_put(b); 709 assert(rc == EOK); 694 710 fibril_mutex_unlock(&nodep->idx->lock); 695 711 return false; 696 712 default: 697 713 case FAT_DENTRY_VALID: 698 block_put(b); 714 rc = block_put(b); 715 assert(rc == EOK); 699 716 fibril_mutex_unlock(&nodep->idx->lock); 700 717 return true; 701 718 } 702 block_put(b); 719 rc = block_put(b); 720 assert(rc == EOK); 703 721 fibril_mutex_unlock(&nodep->idx->lock); 704 722 return true; 705 723 } 706 block_put(b); 724 rc = block_put(b); 725 assert(rc == EOK); 707 726 } 708 727 … … 901 920 size_t bytes; 902 921 block_t *b; 922 int rc; 903 923 904 924 if (!fn) { … … 937 957 (void) ipc_data_read_finalize(callid, b->data + pos % bps, 938 958 bytes); 939 block_put(b); 959 rc = block_put(b); 960 assert(rc == EOK); 940 961 } 941 962 } else { … … 969 990 continue; 970 991 case FAT_DENTRY_LAST: 971 block_put(b); 992 rc = block_put(b); 993 assert(rc == EOK); 972 994 goto miss; 973 995 default: 974 996 case FAT_DENTRY_VALID: 975 997 fat_dentry_name_get(d, name); 976 block_put(b); 998 rc == block_put(b); 999 assert(rc == EOK); 977 1000 goto hit; 978 1001 } 979 1002 } 980 block_put(b); 1003 rc = block_put(b); 1004 assert(rc == EOK); 981 1005 bnum++; 982 1006 } … … 1010 1034 off_t boundary; 1011 1035 int flags = BLOCK_FLAGS_NONE; 1036 int rc; 1012 1037 1013 1038 if (!fn) { … … 1055 1080 bytes); 1056 1081 b->dirty = true; /* need to sync block */ 1057 block_put(b); 1082 rc = block_put(b); 1083 assert(rc == EOK); 1058 1084 if (pos + bytes > nodep->size) { 1059 1085 nodep->size = pos + bytes; … … 1089 1115 bytes); 1090 1116 b->dirty = true; /* need to sync block */ 1091 block_put(b); 1117 rc = block_put(b); 1118 assert(rc == EOK); 1092 1119 /* 1093 1120 * Append the cluster chain starting in mcl to the end of the
Note:
See TracChangeset
for help on using the changeset viewer.