|
@@ -292,16 +292,11 @@ int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result)
|
|
|
return dm_tm_unlock(ll->tm, blk);
|
|
|
}
|
|
|
|
|
|
-int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
|
|
|
+static int sm_ll_lookup_big_ref_count(struct ll_disk *ll, dm_block_t b,
|
|
|
+ uint32_t *result)
|
|
|
{
|
|
|
__le32 le_rc;
|
|
|
- int r = sm_ll_lookup_bitmap(ll, b, result);
|
|
|
-
|
|
|
- if (r)
|
|
|
- return r;
|
|
|
-
|
|
|
- if (*result != 3)
|
|
|
- return r;
|
|
|
+ int r;
|
|
|
|
|
|
r = dm_btree_lookup(&ll->ref_count_info, ll->ref_count_root, &b, &le_rc);
|
|
|
if (r < 0)
|
|
@@ -312,6 +307,19 @@ int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
+int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result)
|
|
|
+{
|
|
|
+ int r = sm_ll_lookup_bitmap(ll, b, result);
|
|
|
+
|
|
|
+ if (r)
|
|
|
+ return r;
|
|
|
+
|
|
|
+ if (*result != 3)
|
|
|
+ return r;
|
|
|
+
|
|
|
+ return sm_ll_lookup_big_ref_count(ll, b, result);
|
|
|
+}
|
|
|
+
|
|
|
int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
|
|
|
dm_block_t end, dm_block_t *result)
|
|
|
{
|
|
@@ -372,11 +380,12 @@ int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin,
|
|
|
return -ENOSPC;
|
|
|
}
|
|
|
|
|
|
-int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
|
|
|
- uint32_t ref_count, enum allocation_event *ev)
|
|
|
+static int sm_ll_mutate(struct ll_disk *ll, dm_block_t b,
|
|
|
+ uint32_t (*mutator)(void *context, uint32_t old),
|
|
|
+ void *context, enum allocation_event *ev)
|
|
|
{
|
|
|
int r;
|
|
|
- uint32_t bit, old;
|
|
|
+ uint32_t bit, old, ref_count;
|
|
|
struct dm_block *nb;
|
|
|
dm_block_t index = b;
|
|
|
struct disk_index_entry ie_disk;
|
|
@@ -399,6 +408,14 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
|
|
|
bm_le = dm_bitmap_data(nb);
|
|
|
old = sm_lookup_bitmap(bm_le, bit);
|
|
|
|
|
|
+ if (old > 2) {
|
|
|
+ r = sm_ll_lookup_big_ref_count(ll, b, &old);
|
|
|
+ if (r < 0)
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+
|
|
|
+ ref_count = mutator(context, old);
|
|
|
+
|
|
|
if (ref_count <= 2) {
|
|
|
sm_set_bitmap(bm_le, bit, ref_count);
|
|
|
|
|
@@ -448,31 +465,35 @@ int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
|
|
|
return ll->save_ie(ll, index, &ie_disk);
|
|
|
}
|
|
|
|
|
|
-int sm_ll_inc(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
|
|
|
+static uint32_t set_ref_count(void *context, uint32_t old)
|
|
|
{
|
|
|
- int r;
|
|
|
- uint32_t rc;
|
|
|
-
|
|
|
- r = sm_ll_lookup(ll, b, &rc);
|
|
|
- if (r)
|
|
|
- return r;
|
|
|
+ return *((uint32_t *) context);
|
|
|
+}
|
|
|
|
|
|
- return sm_ll_insert(ll, b, rc + 1, ev);
|
|
|
+int sm_ll_insert(struct ll_disk *ll, dm_block_t b,
|
|
|
+ uint32_t ref_count, enum allocation_event *ev)
|
|
|
+{
|
|
|
+ return sm_ll_mutate(ll, b, set_ref_count, &ref_count, ev);
|
|
|
}
|
|
|
|
|
|
-int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
|
|
|
+static uint32_t inc_ref_count(void *context, uint32_t old)
|
|
|
{
|
|
|
- int r;
|
|
|
- uint32_t rc;
|
|
|
+ return old + 1;
|
|
|
+}
|
|
|
|
|
|
- r = sm_ll_lookup(ll, b, &rc);
|
|
|
- if (r)
|
|
|
- return r;
|
|
|
+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);
|
|
|
+}
|
|
|
|
|
|
- if (!rc)
|
|
|
- return -EINVAL;
|
|
|
+static uint32_t dec_ref_count(void *context, uint32_t old)
|
|
|
+{
|
|
|
+ return old - 1;
|
|
|
+}
|
|
|
|
|
|
- return sm_ll_insert(ll, b, rc - 1, ev);
|
|
|
+int sm_ll_dec(struct ll_disk *ll, dm_block_t b, enum allocation_event *ev)
|
|
|
+{
|
|
|
+ return sm_ll_mutate(ll, b, dec_ref_count, NULL, ev);
|
|
|
}
|
|
|
|
|
|
int sm_ll_commit(struct ll_disk *ll)
|