|
@@ -381,7 +381,7 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
|
|
|
}
|
|
|
|
|
|
static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
|
|
|
- uint32_t (*mutator)(void *context, uint32_t old),
|
|
|
+ int (*mutator)(void *context, uint32_t old, uint32_t *new),
|
|
|
void *context, enum allocation_event *ev)
|
|
|
{
|
|
|
int r;
|
|
@@ -410,11 +410,17 @@ static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
|
|
|
|
|
|
if (old > 2) {
|
|
|
r = sm_ll_lookup_big_ref_count(ll, b, &old);
|
|
|
- if (r < 0)
|
|
|
+ if (r < 0) {
|
|
|
+ dm_tm_unlock(ll->tm, nb);
|
|
|
return r;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- ref_count = mutator(context, old);
|
|
|
+ r = mutator(context, old, &ref_count);
|
|
|
+ if (r) {
|
|
|
+ dm_tm_unlock(ll->tm, nb);
|
|
|
+ return r;
|
|
|
+ }
|
|
|
|
|
|
if (ref_count <= 2) {
|
|
|
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,
|
|
|
return ll->save_ie(ll, index, &ie_disk);
|
|
|
}
|
|
|
|
|
|
-static uint32_t set_ref_count(void *context, uint32_t old)
|
|
|
+static int set_ref_count(void *context, uint32_t old, uint32_t *new)
|
|
|
{
|
|
|
- return *((uint32_t *) context);
|
|
|
+ *new = *((uint32_t *) context);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
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,
|
|
|
return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev);
|
|
|
}
|
|
|
|
|
|
-static uint32_t inc_ref_count(void *context, uint32_t old)
|
|
|
+static int inc_ref_count(void *context, uint32_t old, uint32_t *new)
|
|
|
{
|
|
|
- return old + 1;
|
|
|
+ *new = old + 1;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
return sm_ll_mutate(ll, b, inc_ref_count, NULL, ev);
|
|
|
}
|
|
|
|
|
|
-static uint32_t dec_ref_count(void *context, uint32_t old)
|
|
|
+static int dec_ref_count(void *context, uint32_t old, uint32_t *new)
|
|
|
{
|
|
|
- return old - 1;
|
|
|
+ if (!old) {
|
|
|
+ DMERR_LIMIT("unable to decrement a reference count below 0");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ *new = old - 1;
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
|