diff options
Diffstat (limited to 'drivers/md/persistent-data')
| -rw-r--r-- | drivers/md/persistent-data/dm-array.c | 10 | ||||
| -rw-r--r-- | drivers/md/persistent-data/dm-block-manager.c | 6 | ||||
| -rw-r--r-- | drivers/md/persistent-data/dm-block-manager.h | 7 | ||||
| -rw-r--r-- | drivers/md/persistent-data/dm-space-map-common.c | 32 | ||||
| -rw-r--r-- | drivers/md/persistent-data/dm-space-map-metadata.c | 8 |
5 files changed, 48 insertions, 15 deletions
diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c index af96e24ec328..1d75b1dc1e2e 100644 --- a/drivers/md/persistent-data/dm-array.c +++ b/drivers/md/persistent-data/dm-array.c | |||
| @@ -317,8 +317,16 @@ static int shadow_ablock(struct dm_array_info *info, dm_block_t *root, | |||
| 317 | * The shadow op will often be a noop. Only insert if it really | 317 | * The shadow op will often be a noop. Only insert if it really |
| 318 | * copied data. | 318 | * copied data. |
| 319 | */ | 319 | */ |
| 320 | if (dm_block_location(*block) != b) | 320 | if (dm_block_location(*block) != b) { |
| 321 | /* | ||
| 322 | * dm_tm_shadow_block will have already decremented the old | ||
| 323 | * block, but it is still referenced by the btree. We | ||
| 324 | * increment to stop the insert decrementing it below zero | ||
| 325 | * when overwriting the old value. | ||
| 326 | */ | ||
| 327 | dm_tm_inc(info->btree_info.tm, b); | ||
| 321 | r = insert_ablock(info, index, *block, root); | 328 | r = insert_ablock(info, index, *block, root); |
| 329 | } | ||
| 322 | 330 | ||
| 323 | return r; | 331 | return r; |
| 324 | } | 332 | } |
diff --git a/drivers/md/persistent-data/dm-block-manager.c b/drivers/md/persistent-data/dm-block-manager.c index a7e8bf296388..064a3c271baa 100644 --- a/drivers/md/persistent-data/dm-block-manager.c +++ b/drivers/md/persistent-data/dm-block-manager.c | |||
| @@ -626,6 +626,12 @@ void dm_bm_set_read_only(struct dm_block_manager *bm) | |||
| 626 | } | 626 | } |
| 627 | EXPORT_SYMBOL_GPL(dm_bm_set_read_only); | 627 | EXPORT_SYMBOL_GPL(dm_bm_set_read_only); |
| 628 | 628 | ||
| 629 | void dm_bm_set_read_write(struct dm_block_manager *bm) | ||
| 630 | { | ||
| 631 | bm->read_only = false; | ||
| 632 | } | ||
| 633 | EXPORT_SYMBOL_GPL(dm_bm_set_read_write); | ||
| 634 | |||
| 629 | u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor) | 635 | u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor) |
| 630 | { | 636 | { |
| 631 | return crc32c(~(u32) 0, data, len) ^ init_xor; | 637 | return crc32c(~(u32) 0, data, len) ^ init_xor; |
diff --git a/drivers/md/persistent-data/dm-block-manager.h b/drivers/md/persistent-data/dm-block-manager.h index 9a82083a66b6..13cd58e1fe69 100644 --- a/drivers/md/persistent-data/dm-block-manager.h +++ b/drivers/md/persistent-data/dm-block-manager.h | |||
| @@ -108,9 +108,9 @@ int dm_bm_unlock(struct dm_block *b); | |||
| 108 | int dm_bm_flush_and_unlock(struct dm_block_manager *bm, | 108 | int dm_bm_flush_and_unlock(struct dm_block_manager *bm, |
| 109 | struct dm_block *superblock); | 109 | struct dm_block *superblock); |
| 110 | 110 | ||
| 111 | /* | 111 | /* |
| 112 | * Request data be prefetched into the cache. | 112 | * Request data is prefetched into the cache. |
| 113 | */ | 113 | */ |
| 114 | void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b); | 114 | void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b); |
| 115 | 115 | ||
| 116 | /* | 116 | /* |
| @@ -125,6 +125,7 @@ void dm_bm_prefetch(struct dm_block_manager *bm, dm_block_t b); | |||
| 125 | * be returned if you do. | 125 | * be returned if you do. |
| 126 | */ | 126 | */ |
| 127 | void dm_bm_set_read_only(struct dm_block_manager *bm); | 127 | void dm_bm_set_read_only(struct dm_block_manager *bm); |
| 128 | void dm_bm_set_read_write(struct dm_block_manager *bm); | ||
| 128 | 129 | ||
| 129 | u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor); | 130 | u32 dm_bm_checksum(const void *data, size_t len, u32 init_xor); |
| 130 | 131 | ||
diff --git a/drivers/md/persistent-data/dm-space-map-common.c b/drivers/md/persistent-data/dm-space-map-common.c index 6058569fe86c..466a60bbd716 100644 --- a/drivers/md/persistent-data/dm-space-map-common.c +++ b/drivers/md/persistent-data/dm-space-map-common.c | |||
| @@ -381,7 +381,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin, | |||
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, | 383 | static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, |
| 384 | uint32_t (*mutator)(void *context, uint32_t old), | 384 | int (*mutator)(void *context, uint32_t old, uint32_t *new), |
| 385 | void *context, enum allocation_event *ev) | 385 | void *context, enum allocation_event *ev) |
| 386 | { | 386 | { |
| 387 | int r; | 387 | int r; |
| @@ -410,11 +410,17 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, | |||
| 410 | 410 | ||
| 411 | if (old > 2) { | 411 | if (old > 2) { |
| 412 | r = sm_ll_lookup_big_ref_count(ll, b, &old); | 412 | r = sm_ll_lookup_big_ref_count(ll, b, &old); |
| 413 | if (r < 0) | 413 | if (r < 0) { |
| 414 | dm_tm_unlock(ll->tm, nb); | ||
| 414 | return r; | 415 | return r; |
| 416 | } | ||
| 415 | } | 417 | } |
| 416 | 418 | ||
| 417 | ref_count = mutator(context, old); | 419 | r = mutator(context, old, &ref_count); |
| 420 | if (r) { | ||
| 421 | dm_tm_unlock(ll->tm, nb); | ||
| 422 | return r; | ||
| 423 | } | ||
| 418 | 424 | ||
| 419 | if (ref_count <= 2) { | 425 | if (ref_count <= 2) { |
| 420 | sm_set_bitmap(bm_le, bit, ref_count); | 426 | sm_set_bitmap(bm_le, bit, ref_count); |
| @@ -465,9 +471,10 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b, | |||
| 465 | return ll->save_ie(ll, index, &ie_disk); | 471 | return ll->save_ie(ll, index, &ie_disk); |
| 466 | } | 472 | } |
| 467 | 473 | ||
| 468 | static uint32_t set_ref_count(void *context, uint32_t old) | 474 | static int set_ref_count(void *context, uint32_t old, uint32_t *new) |
| 469 | { | 475 | { |
| 470 | return *((uint32_t *) context); | 476 | *new = *((uint32_t *) context); |
| 477 | return 0; | ||
| 471 | } | 478 | } |
| 472 | 479 | ||
| 473 | int sm_ll_insert(struct ll_disk *ll, dm_block_t b, | 480 | int sm_ll_insert(struct ll_disk *ll, dm_block_t b, |
| @@ -476,9 +483,10 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b, | |||
| 476 | return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev); | 483 | return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev); |
| 477 | } | 484 | } |
| 478 | 485 | ||
| 479 | static uint32_t inc_ref_count(void *context, uint32_t old) | 486 | static int inc_ref_count(void *context, uint32_t old, uint32_t *new) |
| 480 | { | 487 | { |
| 481 | return old + 1; | 488 | *new = old + 1; |
| 489 | return 0; | ||
| 482 | } | 490 | } |
| 483 | 491 | ||
| 484 | int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) | 492 | int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) |
| @@ -486,9 +494,15 @@ int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) | |||
| 486 | return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev); | 494 | return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev); |
| 487 | } | 495 | } |
| 488 | 496 | ||
| 489 | static uint32_t dec_ref_count(void *context, uint32_t old) | 497 | static int dec_ref_count(void *context, uint32_t old, uint32_t *new) |
| 490 | { | 498 | { |
| 491 | return old - 1; | 499 | if (!old) { |
| 500 | DMERR_LIMIT("unable to decrement a reference count below 0"); | ||
| 501 | return -EINVAL; | ||
| 502 | } | ||
| 503 | |||
| 504 | *new = old - 1; | ||
| 505 | return 0; | ||
| 492 | } | 506 | } |
| 493 | 507 | ||
| 494 | int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) | 508 | int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev) |
diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 1c959684caef..58fc1eef7499 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c | |||
| @@ -384,12 +384,16 @@ static int sm_metadata_new_block(struct dm_space_map *sm, dm_block_t *b) | |||
| 384 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); | 384 | struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); |
| 385 | 385 | ||
| 386 | int r = sm_metadata_new_block_(sm, b); | 386 | int r = sm_metadata_new_block_(sm, b); |
| 387 | if (r) | 387 | if (r) { |
| 388 | DMERR("unable to allocate new metadata block"); | 388 | DMERR("unable to allocate new metadata block"); |
| 389 | return r; | ||
| 390 | } | ||
| 389 | 391 | ||
| 390 | r = sm_metadata_get_nr_free(sm, &count); | 392 | r = sm_metadata_get_nr_free(sm, &count); |
| 391 | if (r) | 393 | if (r) { |
| 392 | DMERR("couldn't get free block count"); | 394 | DMERR("couldn't get free block count"); |
| 395 | return r; | ||
| 396 | } | ||
| 393 | 397 | ||
| 394 | check_threshold(&smm->threshold, count); | 398 | check_threshold(&smm->threshold, count); |
| 395 | 399 | ||
