Implement bi-directional page alloc scanning

This commit is contained in:
Tom Marshall 2019-10-10 19:40:00 -07:00
parent c1ec406a00
commit b80d80215b
1 changed files with 53 additions and 26 deletions

View File

@ -328,6 +328,25 @@ pblk_alloc_read(struct dm_compress* dc, struct zone_cache* zc)
return 0;
}
static u64
__pblk_alloc_get(struct dm_compress* dc, struct zone_cache* zc)
{
u32 pblk_count = pblk_alloc_len(&dc->params) * PBLK_SIZE_BITS;
u32 idx;
if (pblk_alloc_read(dc, zc) != 0) {
printk(KERN_ERR "%s: pblk_alloc_read failed\n", __func__);
return PBLK_NONE;
}
idx = cbd_bitmap_alloc(zc->pblk_alloc, pblk_count);
if (idx == pblk_count) {
return PBLK_NONE;
}
zc->pblk_alloc_dirty = true;
return idx;
}
/*
* Get (allocate) one pblk from the currently cached zone pblk alloc bitmap.
* XXX: get rid of this function and use pblk_alloc directly in lblk_write().
@ -335,37 +354,45 @@ pblk_alloc_read(struct dm_compress* dc, struct zone_cache* zc)
static u64
pblk_alloc_get(struct dm_compress* dc, struct zone_cache* zc_hint)
{
u32 zone_pblk_count = pblk_alloc_len(&dc->params) * PBLK_SIZE_BITS;
u64 pblk;
u32 zone_off;
struct zone_cache* zc;
u32 zone;
u32 idx;
zc = zc_hint;
zone = zc->zone;
/* XXX: check both forward and backward */
do {
if (pblk_alloc_read(dc, zc) != 0) {
printk(KERN_ERR " pblk_alloc_read failed\n");
return 0;
}
idx = cbd_bitmap_alloc(zc->pblk_alloc, zone_pblk_count);
if (idx != zone_pblk_count) {
zc->pblk_alloc_dirty = true;
if (zc != zc_hint) {
zone_cache_put(dc, zc);
}
return zone_data_off(&dc->params, zone) + idx;
}
++zone;
if (zone == dc->params.nr_zones) {
zone = 0;
}
zc = zone_cache_get(dc, zone);
pblk = __pblk_alloc_get(dc, zc_hint);
if (pblk != PBLK_NONE) {
return zone_data_off(&dc->params, zc_hint->zone) + pblk;
}
for (zone_off = 1;
zone_off <= zc_hint->zone || zc_hint->zone + zone_off < dc->params.nr_zones;
++zone_off) {
if (zone_off <= zc_hint->zone) {
zc = zone_cache_get(dc, zc_hint->zone - zone_off);
if (zc) {
pblk = __pblk_alloc_get(dc, zc);
if (zone_cache_put(dc, zc) != 0) {
return PBLK_NONE;
}
if (pblk != PBLK_NONE) {
return zone_data_off(&dc->params, zc->zone) + pblk;
}
}
}
if (zc_hint->zone + zone_off < dc->params.nr_zones) {
zc = zone_cache_get(dc, zc_hint->zone + zone_off);
if (zc) {
pblk = __pblk_alloc_get(dc, zc);
if (zone_cache_put(dc, zc) != 0) {
return PBLK_NONE;
}
if (pblk != PBLK_NONE) {
return zone_data_off(&dc->params, zc->zone) + pblk;
}
}
}
}
while (zc != zc_hint);
printk(KERN_ERR "%s: fail, all zones full\n", __func__);
return 0;
return PBLK_NONE;
}
/*