Minimize the amount of pbat reading to find free pblks
* Keep track of full pbats. * Allow specifying whether pbat must be non-full in pbatcache_get().
This commit is contained in:
parent
a2e4f303fd
commit
68956f70e8
|
@ -149,13 +149,7 @@ lbatview_alloc_pblk(struct lbatview* lv)
|
|||
u32 zone_off;
|
||||
struct pbat* pbat;
|
||||
|
||||
if (!lv->pbat) {
|
||||
lv->pbat = pbatcache_get(lv->pbatcache, zone);
|
||||
if (!lv->pbat) {
|
||||
printk(KERN_ERR "%s: pbatcache_get failed\n", __func__);
|
||||
return PBLK_NONE;
|
||||
}
|
||||
}
|
||||
if (lv->pbat) {
|
||||
pblk = pbat_alloc(lv->pbat);
|
||||
if (pblk != PBLK_NONE) {
|
||||
return pblk;
|
||||
|
@ -166,15 +160,26 @@ lbatview_alloc_pblk(struct lbatview* lv)
|
|||
printk(KERN_ERR "%s: pbatcache_put failed\n", __func__);
|
||||
return PBLK_NONE;
|
||||
}
|
||||
}
|
||||
pbat = pbatcache_get(lv->pbatcache, zone, true);
|
||||
if (pbat) {
|
||||
pblk = pbat_alloc(pbat);
|
||||
if (pblk != PBLK_NONE) {
|
||||
lv->pbat = pbat;
|
||||
return pblk;
|
||||
}
|
||||
ret = pbatcache_put(lv->pbatcache, pbat);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s: pbatcache_put failed\n", __func__);
|
||||
return PBLK_NONE;
|
||||
}
|
||||
}
|
||||
for (zone_off = 1;
|
||||
zone_off <= zone || zone + zone_off < lv->params->nr_zones;
|
||||
++zone_off) {
|
||||
if (zone_off <= zone) {
|
||||
pbat = pbatcache_get(lv->pbatcache, zone - zone_off);
|
||||
if (!pbat) {
|
||||
printk(KERN_ERR "%s: pbatcache_get failed\n", __func__);
|
||||
return PBLK_NONE;
|
||||
}
|
||||
pbat = pbatcache_get(lv->pbatcache, zone - zone_off, true);
|
||||
if (pbat) {
|
||||
pblk = pbat_alloc(pbat);
|
||||
if (pblk != PBLK_NONE) {
|
||||
lv->pbat = pbat;
|
||||
|
@ -186,12 +191,10 @@ lbatview_alloc_pblk(struct lbatview* lv)
|
|||
return PBLK_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (zone + zone_off < lv->params->nr_zones) {
|
||||
pbat = pbatcache_get(lv->pbatcache, zone + zone_off);
|
||||
if (!pbat) {
|
||||
printk(KERN_ERR "%s: pbatcache_get failed\n", __func__);
|
||||
return PBLK_NONE;
|
||||
}
|
||||
pbat = pbatcache_get(lv->pbatcache, zone + zone_off, true);
|
||||
if (pbat) {
|
||||
pblk = pbat_alloc(pbat);
|
||||
if (pblk != PBLK_NONE) {
|
||||
lv->pbat = pbat;
|
||||
|
@ -204,6 +207,7 @@ lbatview_alloc_pblk(struct lbatview* lv)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printk(KERN_ERR "%s: fail, all zones full\n", __func__);
|
||||
|
||||
return PBLK_NONE;
|
||||
|
@ -222,7 +226,7 @@ lbatview_free_pblk(struct lbatview* lv, u64 pblk)
|
|||
printk(KERN_ERR "%s: pblk=%lu: zone out of bounds\n", __func__, (unsigned long)pblk);
|
||||
return -EINVAL;
|
||||
}
|
||||
pbat = pbatcache_get(lv->pbatcache, pblk_zone);
|
||||
pbat = pbatcache_get(lv->pbatcache, pblk_zone, false);
|
||||
if (!pbat) {
|
||||
printk(KERN_ERR "%s: pbatcache_get failed\n", __func__);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -233,6 +233,7 @@ struct pbatcache {
|
|||
struct list_head cache_head;
|
||||
unsigned int cache_len;
|
||||
struct pbat* cache;
|
||||
u8* full;
|
||||
};
|
||||
|
||||
size_t
|
||||
|
@ -273,6 +274,7 @@ pbatcache_ctr(struct pbatcache* pc,
|
|||
}
|
||||
list_add_tail(&cache[n].list, &pc->cache_head);
|
||||
}
|
||||
pc->full = kzalloc(DIV_ROUND_UP(params->nr_zones, BITS_PER_BYTE), GFP_KERNEL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -283,6 +285,7 @@ pbatcache_dtr(struct pbatcache* pc)
|
|||
unsigned int n;
|
||||
struct pbat* pbat;
|
||||
|
||||
kfree(pc->full);
|
||||
for (n = 0; n < pc->cache_len; ++n) {
|
||||
pbat = &pc->cache[n];
|
||||
if (!pbat) {
|
||||
|
@ -301,11 +304,15 @@ pbatcache_dtr(struct pbatcache* pc)
|
|||
}
|
||||
|
||||
struct pbat*
|
||||
pbatcache_get(struct pbatcache* pc, u32 zone)
|
||||
pbatcache_get(struct pbatcache* pc, u32 zone, bool avail)
|
||||
{
|
||||
struct pbat* pbat;
|
||||
|
||||
mutex_lock(&pc->lock);
|
||||
if (avail && cbd_bitmap_isset(pc->full, zone)) {
|
||||
mutex_unlock(&pc->lock);
|
||||
return NULL;
|
||||
}
|
||||
list_for_each_entry(pbat, &pc->cache_head, list) {
|
||||
mutex_lock(&pbat->reflock);
|
||||
if (pbat->zone == zone) {
|
||||
|
@ -362,6 +369,12 @@ pbatcache_put(struct pbatcache* pc, struct pbat* pbat)
|
|||
if (ret) {
|
||||
printk(KERN_ERR "%s: pbat_flush failed\n", __func__);
|
||||
}
|
||||
if (pbat->full) {
|
||||
cbd_bitmap_set(pc->full, pbat->zone);
|
||||
}
|
||||
else {
|
||||
cbd_bitmap_reset(pc->full, pbat->zone);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&pbat->reflock);
|
||||
|
||||
|
|
|
@ -206,6 +206,33 @@ cbd_bitmap_free(u8* buf, u32 idx)
|
|||
buf[off] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
static inline void
|
||||
cbd_bitmap_set(u8* buf, u32 idx)
|
||||
{
|
||||
u32 off = idx / BITS_PER_BYTE;
|
||||
u32 bit = idx % BITS_PER_BYTE;
|
||||
|
||||
buf[off] |= (1 << bit);
|
||||
}
|
||||
|
||||
static inline void
|
||||
cbd_bitmap_reset(u8* buf, u32 idx)
|
||||
{
|
||||
u32 off = idx / BITS_PER_BYTE;
|
||||
u32 bit = idx % BITS_PER_BYTE;
|
||||
|
||||
buf[off] &= ~(1 << bit);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
cbd_bitmap_isset(u8* buf, u32 idx)
|
||||
{
|
||||
u32 off = idx / BITS_PER_BYTE;
|
||||
u32 bit = idx % BITS_PER_BYTE;
|
||||
|
||||
return buf[off] & (1 << bit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static inline u32
|
||||
|
@ -512,7 +539,7 @@ bool pbatcache_ctr(struct pbatcache* pbatcache,
|
|||
struct cbd_params* params, u32 cache_pages);
|
||||
void pbatcache_dtr(struct pbatcache* pbatcache);
|
||||
struct pbat*
|
||||
pbatcache_get(struct pbatcache* pbatcache, u32 zone);
|
||||
pbatcache_get(struct pbatcache* pbatcache, u32 zone, bool avail);
|
||||
int pbatcache_put(struct pbatcache* pbatcache, struct pbat* pbat);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue