More improvements, but still failing to clone linux

This commit is contained in:
Tom Marshall 2019-10-24 13:02:03 -07:00
parent 495d191d16
commit 446a4811f6
6 changed files with 248 additions and 157 deletions

View File

@ -72,13 +72,14 @@ lbatpage_dtr(struct lbatpage* lp)
static void
lbatpage_flush_endio(struct bio* bio)
{
struct lbatpage* lp = bio->bi_private;
int ret;
cbd_free_page(bio->bi_io_vec[0].bv_page);
ret = pblk_endio(bio);
if (ret) {
/* XXX: ...? */
printk(KERN_ERR "%s: I/O failed\n", __func__);
lp->state = CACHE_STATE_ERROR;
}
}
@ -90,6 +91,9 @@ lbatpage_flush(struct lbatpage* lp)
mutex_lock(&lp->lock);
if (lp->state != CACHE_STATE_DIRTY) {
if (lp->state == CACHE_STATE_ERROR) {
ret = -EIO;
}
goto out;
}
iopagev[0] = cbd_alloc_page();
@ -113,17 +117,14 @@ lbatpage_read(struct lbatpage* lp)
int ret = 0;
struct page* pagev[1];
ret = lbatpage_flush(lp);
if (ret) {
return ret;
}
mutex_lock(&lp->lock);
if (lp->state == CACHE_STATE_CLEAN) {
if (lp->state != CACHE_STATE_UNCACHED) {
goto out;
}
pagev[0] = lp->page;
ret = pblk_read_wait(lp->params, lp->pblk, 1, pagev);
if (ret) {
printk(KERN_ERR "%s: failed, pblk=%lu\n", __func__, (unsigned long)lp->pblk);
goto out;
}
lp->state = CACHE_STATE_CLEAN;
@ -136,15 +137,17 @@ out:
void
lbatpage_reset(struct lbatpage* lp, u64 pblk)
{
BUG_ON(lp->pblk == pblk);
lp->pblk = pblk;
lp->state = CACHE_STATE_UNCACHED;
if (lp->pblk != pblk) {
lp->pblk = pblk;
lp->state = CACHE_STATE_UNCACHED;
}
}
u8*
lbatpage_get_buf(struct lbatpage* lp, bool rw)
{
mutex_lock(&lp->lock);
BUG_ON(lp->state == CACHE_STATE_UNCACHED);
if (rw) {
lp->state = CACHE_STATE_DIRTY;
}
@ -154,6 +157,7 @@ lbatpage_get_buf(struct lbatpage* lp, bool rw)
void
lbatpage_put_buf(struct lbatpage* lp)
{
BUG_ON(lp->state == CACHE_STATE_UNCACHED);
mutex_unlock(&lp->lock);
}
@ -248,6 +252,9 @@ lbatpagecache_get(struct lbatpagecache* lpc, u64 pblk)
lp = lpc->cache[n];
mutex_lock(&lp->reflock);
if (lp->pblk == pblk) {
if (lp->ref == 0) {
goto found;
}
++lp->ref;
mutex_unlock(&lp->reflock);
goto out;
@ -265,7 +272,7 @@ lbatpagecache_get(struct lbatpagecache* lpc, u64 pblk)
for (n = 0; n < lpc->len; ++n) {
lp = lpc->cache[n];
mutex_lock(&lp->reflock);
if (lp->ref == 0) {
if (lp->ref == 0 && lp->state != CACHE_STATE_ERROR) {
goto found;
}
mutex_unlock(&lp->reflock);

View File

@ -84,22 +84,33 @@ lbatview_flush(struct lbatview* lv)
mutex_lock(&lv->lock);
if (lv->state != CACHE_STATE_DIRTY) {
goto out;
if (lv->state == CACHE_STATE_ERROR) {
ret = -EIO;
goto out;
}
}
BUG_ON(!lv->pages[0]);
BUG_ON(lv->pblk == PBLK_NONE);
if (lv->pages[0]) {
ret = lbatpage_flush(lv->pages[0]);
ret = lbatpagecache_put(lv->lpc, lv->pages[0]);
lv->pages[0] = NULL;
if (ret) {
lv->state = CACHE_STATE_ERROR;
goto out;
}
}
if (lv->pages[1]) {
ret = lbatpage_flush(lv->pages[1]);
ret = lbatpagecache_put(lv->lpc, lv->pages[1]);
lv->pages[1] = NULL;
if (ret) {
lv->state = CACHE_STATE_ERROR;
goto out;
}
}
ret = pbatcache_put(lv->pbatcache, lv->pbat);
lv->pbat = NULL;
if (ret) {
lv->state = CACHE_STATE_ERROR;
goto out;
}
lv->state = CACHE_STATE_CLEAN;
out:
@ -112,11 +123,10 @@ lbatview_read(struct lbatview* lv)
{
int ret = 0;
ret = lbatview_flush(lv);
if (ret) {
return ret;
}
mutex_lock(&lv->lock);
if (lv->state != CACHE_STATE_UNCACHED) {
goto out;
}
if (lv->pages[0]) {
ret = lbatpage_read(lv->pages[0]);
if (ret) {
@ -139,36 +149,33 @@ out:
bool
lbatview_reset(struct lbatview* lv, u64 pblk, u32 count)
{
bool ret = true;
u32 zone = (pblk - CBD_HEADER_BLOCKS) / zone_len(lv->params);
u32 zone;
BUG_ON(lv->pblk == pblk);
lv->pblk = pblk;
lv->state = CACHE_STATE_UNCACHED;
if (pbatcache_put(lv->pbatcache, lv->pbat) != 0) {
printk(KERN_ERR "%s: pbatcache_put failed\n", __func__);
ret = false;
}
if (lv->pbat) { printk(KERN_ERR "%s: pbat leak\n", __func__); }
if (lv->pages[0]) { printk(KERN_ERR "%s: lbatpage leak\n", __func__); }
if (lv->pages[1]) { printk(KERN_ERR "%s: lbatpage leak\n", __func__); }
zone = (pblk - CBD_HEADER_BLOCKS) / zone_len(lv->params);
lv->pbat = pbatcache_get(lv->pbatcache, zone);
if (!lv->pbat) {
ret = false;
return false;
}
if (lbatpagecache_put(lv->lpc, lv->pages[0]) != 0) {
ret = false;
}
lv->pages[0] = NULL;
if (lbatpagecache_put(lv->lpc, lv->pages[1]) != 0) {
ret = false;
}
lv->pages[1] = NULL;
if (count > 0) {
lv->pages[0] = lbatpagecache_get(lv->lpc, pblk + 0);
if (!lv->pages[0]) {
return false;
}
}
if (count > 1) {
lv->pages[1] = lbatpagecache_get(lv->lpc, pblk + 1);
if (!lv->pages[1]) {
return false;
}
}
lv->pblk = pblk;
lv->state = CACHE_STATE_UNCACHED;
return ret;
return true;
}
static u64
@ -184,7 +191,9 @@ lbatview_alloc_pblk(struct lbatview* lv)
printk(KERN_ERR "%s: *** lv->pbat is NULL\n", __func__);
return PBLK_NONE;
}
if (pbat_read(lv->pbat) != 0) {
return PBLK_NONE;
}
pblk = pbat_alloc(lv->pbat);
if (pblk != PBLK_NONE) {
return pblk;
@ -261,14 +270,17 @@ lbatview_free_pblk(struct lbatview* lv, u64 pblk)
printk(KERN_ERR "%s: *** lv->pbat is NULL\n", __func__);
return -EINVAL;
}
ret = pbat_read(lv->pbat);
if (ret) {
return ret;
}
if (pblk < CBD_HEADER_BLOCKS) {
printk(KERN_ERR "%s: pblk index is in header\n", __func__);
printk(KERN_ERR "%s: pblk=%lu: index is in header\n", __func__, (unsigned long)pblk);
return -EINVAL;
}
pblk_zone = (pblk - CBD_HEADER_BLOCKS) / zone_len(lv->params);
if (pblk_zone >= lv->params->nr_zones) {
printk(KERN_ERR "%s: pblk zone out of bounds\n", __func__);
printk(KERN_ERR "%s: pblk=%lu: zone out of bounds\n", __func__, (unsigned long)pblk);
return -EINVAL;
}
pbat = pbatcache_get(lv->pbatcache, pblk_zone);
@ -395,46 +407,50 @@ int
lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len)
{
int ret = 0;
u32 req_nalloc;
u32 elem_off;
u32 off;
u32 n;
u64 pblk;
u32 elem_len_size = (lv->params->lblk_shift + PBLK_SHIFT > 16) ? 4 : 2;
u32 elem_pblk_size = (lv->params->nr_pblk <= 0xffff ? 2 :
(lv->params->nr_pblk <= 0xffffffff ? 4 : 6));
u32 elem_lelen;
u64 elem_lepblk;
mutex_lock(&lv->lock);
off = lbatview_elem_off(lv, lblk);
elem_lelen = __cpu_to_le32(len);
lbatview_wmem(lv, off, elem_len_size, &elem_lelen);
off += elem_len_size;
if (len == CBD_UNCOMPRESSED) {
len = PBLK_SIZE * lblk_per_pblk(lv->params);
req_nalloc = lblk_per_pblk(lv->params);
}
for (n = 0; n < lblk_per_pblk(lv->params); ++n, off += elem_pblk_size) {
else {
req_nalloc = DIV_ROUND_UP(len, PBLK_SIZE);
}
mutex_lock(&lv->lock);
BUG_ON(lv->state == CACHE_STATE_UNCACHED);
elem_off = lbatview_elem_off(lv, lblk);
elem_lelen = __cpu_to_le32(len);
lbatview_wmem(lv, elem_off, lba_elem_len_bytes(lv->params), &elem_lelen);
off = elem_off + lba_elem_len_bytes(lv->params);
for (n = 0; n < lblk_per_pblk(lv->params); ++n, off += lba_elem_pblk_bytes(lv->params)) {
elem_lepblk = 0;
lbatview_rmem(lv, off, elem_pblk_size, &elem_lepblk);
lbatview_rmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
pblk = __le64_to_cpu(elem_lepblk);
if (len > PBLK_SIZE * n) {
if (pblk == 0) {
pblk = lbatview_alloc_pblk(lv);
if (pblk == PBLK_NONE) {
printk(KERN_ERR " lbat_alloc_pblk failed\n");
ret = -ENOSPC;
goto out; /* XXX: undo */
}
elem_lepblk = __cpu_to_le64(pblk);
lbatview_wmem(lv, off, elem_pblk_size, &elem_lepblk);
if (pblk == 0) {
if (n >= req_nalloc) {
break;
}
pblk = lbatview_alloc_pblk(lv);
if (pblk == PBLK_NONE) {
printk(KERN_ERR "%s: lbatview_alloc_pblk failed\n", __func__);
ret = -ENOSPC;
goto out; /* XXX: undo */
}
elem_lepblk = __cpu_to_le64(pblk);
lbatview_wmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
}
else {
if (pblk != 0) {
if (n >= req_nalloc) {
elem_lepblk = 0;
lbatview_wmem(lv, off, elem_pblk_size, &elem_lepblk);
lbatview_wmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
ret = lbatview_free_pblk(lv, pblk);
if (ret) {
printk(KERN_ERR " lbat_free_pblk failed\n");
printk(KERN_ERR "%s: lbatview_free_pblk failed\n", __func__);
goto out; /* XXX: undo */
}
}
@ -450,13 +466,13 @@ u32
lbatview_elem_len(struct lbatview* lv, u64 lblk)
{
u32 off;
u32 elem_len_size = (lv->params->lblk_shift + PBLK_SHIFT > 16) ? 4 : 2;
u32 elem_lelen;
mutex_lock(&lv->lock);
BUG_ON(lv->state == CACHE_STATE_UNCACHED);
off = lbatview_elem_off(lv, lblk);
elem_lelen = 0;
lbatview_rmem(lv, off, elem_len_size, &elem_lelen);
lbatview_rmem(lv, off, lba_elem_len_bytes(lv->params), &elem_lelen);
mutex_unlock(&lv->lock);
return __le32_to_cpu(elem_lelen);
@ -466,19 +482,32 @@ u64
lbatview_elem_pblk(struct lbatview* lv, u64 lblk, u32 idx)
{
u32 off;
u32 elem_len_size = (lv->params->lblk_shift + PBLK_SHIFT > 16) ? 4 : 2;
u32 elem_pblk_size = (lv->params->nr_pblk <= 0xffff ? 2 :
(lv->params->nr_pblk <= 0xffffffff ? 4 : 6));
u64 elem_lepblk;
u64 pblk;
u32 pblk_zone;
mutex_lock(&lv->lock);
BUG_ON(lv->state == CACHE_STATE_UNCACHED);
off = lbatview_elem_off(lv, lblk) +
elem_len_size + idx * elem_pblk_size;
lba_elem_len_bytes(lv->params) +
idx * lba_elem_pblk_bytes(lv->params);
elem_lepblk = 0;
lbatview_rmem(lv, off, elem_pblk_size, &elem_lepblk);
lbatview_rmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
mutex_unlock(&lv->lock);
pblk = __le64_to_cpu(elem_lepblk);
pblk_zone = zone_for_pblk(lv->params, pblk);
if (pblk_zone == ZONE_NONE || pblk_zone >= lv->params->nr_zones) {
printk(KERN_ERR "%s: pblk %lu out of range at lblk=%lu n=%u\n",
__func__, (unsigned long)pblk, (unsigned long)lblk, idx);
return PBLK_NONE;
}
if (pblk < zone_data_off(lv->params, pblk_zone)) {
printk(KERN_ERR "%s: pblk in metadata at lblk=%lu n=%u\n",
__func__, (unsigned long)pblk, idx);
return PBLK_NONE;
}
return __le64_to_cpu(elem_lepblk);
return pblk;
}
struct lbatviewcache {
@ -610,6 +639,9 @@ lbatviewcache_get(struct lbatviewcache* lvc, u64 lblk)
lv = lvc->cache[n];
mutex_lock(&lv->reflock);
if (lv->pblk == pblk) {
if (lv->ref == 0) {
goto found;
}
++lv->ref;
mutex_unlock(&lv->reflock);
goto out;
@ -627,7 +659,7 @@ lbatviewcache_get(struct lbatviewcache* lvc, u64 lblk)
for (n = 0; n < lvc->len; ++n) {
lv = lvc->cache[n];
mutex_lock(&lv->reflock);
if (lv->ref == 0) {
if (lv->ref == 0 && lv->state != CACHE_STATE_ERROR) {
goto found;
}
mutex_unlock(&lv->reflock);
@ -639,6 +671,7 @@ lbatviewcache_get(struct lbatviewcache* lvc, u64 lblk)
lv = NULL;
goto out;
}
printk(KERN_INFO "%s: realloc done, using n=%u\n", __func__, n);
lv = lvc->cache[n];
mutex_lock(&lv->reflock);

View File

@ -189,13 +189,14 @@ lbd_dtr(struct lbd* lbd)
static void
lbd_flush_endio(struct bio* bio)
{
struct lbd* lbd = bio->bi_private;
int ret;
cbd_free_page(bio->bi_io_vec[0].bv_page);
ret = pblk_endio(bio);
if (ret) {
/* XXX: ...? */
printk(KERN_ERR "%s: I/O failed\n", __func__);
lbd->state = CACHE_STATE_ERROR;
}
}
@ -212,7 +213,11 @@ lbd_flush(struct lbd* lbd)
mutex_lock(&lbd->lock);
if (lbd->state != CACHE_STATE_DIRTY) {
goto out;
if (lbd->state == CACHE_STATE_ERROR) {
ret = -EIO;
goto out;
}
goto clean;
}
if (lblk_is_zeros(lbd->params, lbd)) {
@ -243,6 +248,10 @@ lbd_flush(struct lbd* lbd)
}
for (n = 0; n * PBLK_SIZE < c_len; ++n, p += PBLK_SIZE) {
pblk = lbatview_elem_pblk(lbd->lv, lbd->lblk, n);
if (pblk == PBLK_NONE) {
ret = -EIO;
goto out;
}
iopagev[0] = cbd_alloc_page();
if (!iopagev[0]) {
printk(KERN_ERR "%s: out of memory\n", __func__);
@ -252,6 +261,14 @@ lbd_flush(struct lbd* lbd)
memcpy(page_address(iopagev[0]), p, PBLK_SIZE);
pblk_write(lbd->params, pblk, 1, iopagev, lbd_flush_endio, lbd);
}
clean:
ret = lbatviewcache_put(lbd->lvc, lbd->lv);
lbd->lv = NULL;
if (ret) {
lbd->state = CACHE_STATE_ERROR;
goto out;
}
lbd->state = CACHE_STATE_CLEAN;
out:
@ -267,17 +284,12 @@ lbd_read(struct lbd* lbd)
u64 pblk;
struct page* iopagev[1];
ret = lbd_flush(lbd);
if (ret) {
return ret;
}
mutex_lock(&lbd->lock);
if (lbd->state == CACHE_STATE_CLEAN) {
if (lbd->state != CACHE_STATE_UNCACHED) {
goto out;
}
ret = lbatview_read(lbd->lv);
if (ret) {
printk(KERN_ERR "%s: lbat_read failed\n", __func__);
goto out;
}
c_len = lbatview_elem_len(lbd->lv, lbd->lblk);
@ -297,12 +309,11 @@ lbd_read(struct lbd* lbd)
p = lbd->lz4_cbuf;
for (n = 0; n * PBLK_SIZE < c_len; ++n, p += PBLK_SIZE) {
pblk = lbatview_elem_pblk(lbd->lv, lbd->lblk, n);
if (pblk == 0) {
printk(KERN_ERR "%s: pblk is zero at lblk=%lu n=%u\n", __func__,
(unsigned long)lbd->lblk, n);
if (pblk == PBLK_NONE) {
ret = -EIO;
goto out;
}
/* XXX: check pblk not in metadata? */
iopagev[0] = virt_to_page(p);
ret = pblk_read_wait(lbd->params, pblk, 1, iopagev);
if (ret) {
@ -320,6 +331,7 @@ lbd_read(struct lbd* lbd)
memcpy(lbd->buf, lbd->lz4_cbuf, d_len);
}
}
lbd->state = CACHE_STATE_CLEAN;
out:
mutex_unlock(&lbd->lock);
@ -329,22 +341,17 @@ out:
bool
lbd_reset(struct lbd* lbd, u64 lblk)
{
bool ret = true;
if (lbd->lv) { printk(KERN_ERR "%s: lbatview leak\n", __func__); }
BUG_ON(lbd->lblk == lblk);
lbd->lblk = lblk;
lbd->state = CACHE_STATE_UNCACHED;
if (lbatviewcache_put(lbd->lvc, lbd->lv) != 0) {
printk(KERN_ERR "%s: lbatviewcache_put failed\n", __func__);
ret = false;
}
lbd->lv = lbatviewcache_get(lbd->lvc, lblk);
if (!lbd->lv) {
printk(KERN_ERR "%s: lbatviewcache_get failed\n", __func__);
ret = false;
return false;
}
lbd->lblk = lblk;
lbd->state = CACHE_STATE_UNCACHED;
return ret;
return true;
}
void
@ -356,6 +363,7 @@ lbd_data_read(struct lbd* lbd, u32 off, u32 len, u8* buf)
return;
}
mutex_lock(&lbd->lock);
BUG_ON(lbd->state == CACHE_STATE_UNCACHED);
memcpy(buf, lbd->buf + off, len);
mutex_unlock(&lbd->lock);
}
@ -369,6 +377,7 @@ lbd_data_write(struct lbd* lbd, u32 off, u32 len, const u8* buf)
return;
}
mutex_lock(&lbd->lock);
BUG_ON(lbd->state == CACHE_STATE_UNCACHED);
memcpy(lbd->buf + off, buf, len);
lbd->state = CACHE_STATE_DIRTY;
mutex_unlock(&lbd->lock);
@ -437,7 +446,7 @@ lbdcache_ctr(struct lbdcache* lc,
return false;
}
return lbdcache_realloc(lc, 1);
return lbdcache_realloc(lc, 1024);
}
void
@ -477,6 +486,9 @@ lbdcache_get(struct lbdcache* lc, u64 lblk)
lbd = lc->cache[n];
mutex_lock(&lbd->reflock);
if (lbd->lblk == lblk) {
if (lbd->ref == 0) {
goto found;
}
++lbd->ref;
mutex_unlock(&lbd->reflock);
goto out;
@ -494,7 +506,7 @@ lbdcache_get(struct lbdcache* lc, u64 lblk)
for (n = 0; n < lc->len; ++n) {
lbd = lc->cache[n];
mutex_lock(&lbd->reflock);
if (lbd->ref == 0) {
if (lbd->ref == 0 && lbd->state != CACHE_STATE_ERROR) {
goto found;
}
mutex_unlock(&lbd->reflock);
@ -506,6 +518,7 @@ lbdcache_get(struct lbdcache* lc, u64 lblk)
lbd = NULL;
goto out;
}
printk(KERN_INFO "%s: realloc done, using n=%u\n", __func__, n);
lbd = lc->cache[n];
mutex_lock(&lbd->reflock);

View File

@ -73,6 +73,7 @@ pbat_dtr(struct pbat* pbat)
static void
pbat_flush_endio(struct bio* bio)
{
struct pbat* pbat = bio->bi_private;
int ret;
unsigned int n;
@ -81,13 +82,8 @@ pbat_flush_endio(struct bio* bio)
}
ret = pblk_endio(bio);
if (ret) {
/*
* XXX:
* Set dm_compress.io_error?
* Set pbat.io_error?
* Set pbat.zone = ZONE_ERR?
*/
printk(KERN_ERR "%s: XXX: I/O failed\n", __func__);
printk(KERN_ERR "%s: I/O failed\n", __func__);
pbat->state = CACHE_STATE_ERROR;
}
}
@ -103,6 +99,9 @@ pbat_flush(struct pbat* pbat)
mutex_lock(&pbat->lock);
if (pbat->state != CACHE_STATE_DIRTY) {
if (pbat->state == CACHE_STATE_ERROR) {
ret = -EIO;
}
goto out;
}
pblk = pbat_off(pbat->params, pbat->zone);
@ -132,12 +131,8 @@ pbat_read(struct pbat* pbat)
u64 pblk;
u32 n;
ret = pbat_flush(pbat);
if (ret) {
return ret;
}
mutex_lock(&pbat->lock);
if (pbat->state == CACHE_STATE_CLEAN) {
if (pbat->state != CACHE_STATE_UNCACHED) {
goto out;
}
pblk = pbat_off(pbat->params, pbat->zone);
@ -158,9 +153,10 @@ out:
void
pbat_reset(struct pbat* pbat, u32 zone)
{
BUG_ON(pbat->zone == zone);
pbat->zone = zone;
pbat->state = CACHE_STATE_UNCACHED;
if (pbat->zone != zone) {
pbat->zone = zone;
pbat->state = CACHE_STATE_UNCACHED;
}
}
u32
@ -173,19 +169,22 @@ u64
pbat_alloc(struct pbat* pbat)
{
u32 pblk_count = pbat_len(pbat->params) * PBLK_SIZE_BITS;
u64 idx;
u32 idx;
u64 pblk;
mutex_lock(&pbat->lock);
BUG_ON(pbat->state == CACHE_STATE_UNCACHED);
idx = cbd_bitmap_alloc(pbat->buf, pblk_count);
if (idx == pblk_count) {
idx = PBLK_NONE;
pblk = PBLK_NONE;
goto out;
}
pblk = idx + zone_data_off(pbat->params, pbat->zone);
pbat->state = CACHE_STATE_DIRTY;
out:
mutex_unlock(&pbat->lock);
return idx + zone_data_off(pbat->params, pbat->zone);
return pblk;
}
int
@ -205,6 +204,7 @@ pbat_free(struct pbat* pbat, u64 pblk)
idx = pblk - zone_data_off(pbat->params, zone);
BUG_ON(idx >= zone_pblk_count);
mutex_lock(&pbat->lock);
BUG_ON(pbat->state == CACHE_STATE_UNCACHED);
cbd_bitmap_free(pbat->buf, idx);
pbat->state = CACHE_STATE_DIRTY;
mutex_unlock(&pbat->lock);
@ -303,6 +303,9 @@ pbatcache_get(struct pbatcache* pc, u32 zone)
pbat = pc->cache[n];
mutex_lock(&pbat->reflock);
if (pbat->zone == zone) {
if (pbat->ref == 0) {
goto found;
}
++pbat->ref;
mutex_unlock(&pbat->reflock);
goto out;
@ -321,7 +324,7 @@ pbatcache_get(struct pbatcache* pc, u32 zone)
for (n = 0; n < pc->len; ++n) {
pbat = pc->cache[n];
mutex_lock(&pbat->reflock);
if (pbat->ref == 0) {
if (pbat->ref == 0 && pbat->state != CACHE_STATE_ERROR) {
goto found;
}
mutex_unlock(&pbat->reflock);
@ -333,6 +336,7 @@ pbatcache_get(struct pbatcache* pc, u32 zone)
pbat = NULL;
goto out;
}
printk(KERN_INFO "%s: realloc done, using n=%u\n", __func__, n);
pbat = pc->cache[n];
mutex_lock(&pbat->reflock);

View File

@ -134,9 +134,8 @@ pblk_read_wait(struct cbd_params* params,
printk(KERN_ERR "%s: out of memory\n", __func__);
return -ENOMEM;
}
ret = submit_bio_wait(bio);
if (ret != 0) {
if (ret) {
printk(KERN_ERR "%s: submit_bio_wait failed: %d\n", __func__, ret);
}
bio_put(bio);

View File

@ -16,6 +16,10 @@
#define LBLK_SHIFT_MIN 1
#define LBLK_SHIFT_MAX (20 - PBLK_SHIFT)
#define ZONE_NONE (u32)(~0)
#define PBLK_NONE (u64)(~0)
#define LBLK_NONE (u64)(~0)
#define CBD_HEADER_BLOCKS 1
#define CBD_UNCOMPRESSED 1
@ -196,13 +200,24 @@ pbat_len(const struct cbd_params* params)
return 1;
}
static inline u32
lba_elem_len_bytes(const struct cbd_params* params)
{
return (params->lblk_shift + PBLK_SHIFT > 16) ? 4 : 2;
}
static inline u32
lba_elem_pblk_bytes(const struct cbd_params* params)
{
return (params->nr_pblk <= 0xffff ? 2 :
(params->nr_pblk <= 0xffffffff ? 4 : 6));
}
static inline u32
lba_len(const struct cbd_params* params)
{
u32 elem_len_bytes = (params->lblk_shift + PBLK_SHIFT > 16) ? 4 : 2;
u32 elem_pblk_bytes = (params->nr_pblk <= 0xffff ? 2 :
(params->nr_pblk <= 0xffffffff ? 4 : 6));
return elem_len_bytes + (1 << params->lblk_shift) * elem_pblk_bytes;
return lba_elem_len_bytes(params) +
lba_elem_pblk_bytes(params) * (1 << params->lblk_shift);
}
static inline u32
@ -258,6 +273,21 @@ zone_data_off(const struct cbd_params* params, u32 idx)
lbat_len(params);
}
static inline u32
zone_for_pblk(const struct cbd_params* params, u64 pblk)
{
if (pblk < CBD_HEADER_BLOCKS) {
return ZONE_NONE;
}
return (pblk - CBD_HEADER_BLOCKS) / zone_len(params);
}
static inline u32
zone_for_lblk(const struct cbd_params* params, u64 lblk)
{
return (lblk / params->lblk_per_zone);
}
static inline void
cbd_header_get(const u8* buf, struct cbd_header* header)
{
@ -289,22 +319,22 @@ cbd_header_put(u8* buf, const struct cbd_header* header)
static inline u32
lba_len_get(const struct cbd_params* params, const u8* buf)
{
if (params->lblk_shift + PBLK_SHIFT > 16) {
return get32_le(&buf);
if (lba_elem_len_bytes(params) == 2) {
return get16_le(&buf);
}
else {
return get16_le(&buf);
return get32_le(&buf);
}
}
static inline void
lba_len_put(const struct cbd_params* params, u8* buf, u32 val)
{
if (params->lblk_shift + PBLK_SHIFT > 16) {
put32_le(&buf, val);
if (lba_elem_len_bytes(params) == 2) {
put16_le(&buf, val);
}
else {
put16_le(&buf, val);
put32_le(&buf, val);
}
}
@ -312,17 +342,19 @@ static inline u64
lba_pblk_get(const struct cbd_params* params, const u8* buf, u32 idx)
{
const u8* p = buf;
p += (params->lblk_shift + PBLK_SHIFT > 16) ? 4 : 2;
if (params->nr_pblk <= 0xffff) {
p += 2 * idx;
u32 len_bytes = lba_elem_len_bytes(params);
u32 pblk_bytes = lba_elem_pblk_bytes(params);
if (pblk_bytes == 2) {
p += len_bytes + 2 * idx;
return get16_le(&p);
}
else if (params->nr_pblk <= 0xffffffff) {
p += 4 * idx;
else if (pblk_bytes == 4) {
p += len_bytes + 4 * idx;
return get32_le(&p);
}
else {
p += 6 * idx;
p += len_bytes + 6 * idx;
return get48_le(&p);
}
}
@ -331,17 +363,19 @@ static inline void
lba_pblk_put(const struct cbd_params* params, u8* buf, u32 idx, u64 val)
{
u8* p = buf;
p += (params->lblk_shift + PBLK_SHIFT > 16) ? 4 : 2;
if (params->nr_pblk <= 0xffff) {
p += 2 * idx;
u32 len_bytes = lba_elem_len_bytes(params);
u32 pblk_bytes = lba_elem_pblk_bytes(params);
if (pblk_bytes == 2) {
p += len_bytes + 2 * idx;
put16_le(&p, val);
}
else if (params->nr_pblk <= 0xffffffff) {
p += 4 * idx;
else if (pblk_bytes == 4) {
p += len_bytes + 4 * idx;
put32_le(&p, val);
}
else {
p += 6 * idx;
p += len_bytes + 6 * idx;
put48_le(&p, val);
}
}
@ -351,19 +385,21 @@ lba_get(const struct cbd_params* params,
const u8* buf, struct lba* lba)
{
u32 n;
u32 len_bytes = lba_elem_len_bytes(params);
u32 pblk_bytes = lba_elem_pblk_bytes(params);
if (params->lblk_shift + PBLK_SHIFT > 16) {
lba->len = get32_le(&buf);
}
else {
if (len_bytes == 2) {
lba->len = get16_le(&buf);
}
if (params->nr_pblk <= 0xffff) {
else {
lba->len = get32_le(&buf);
}
if (pblk_bytes == 2) {
for (n = 0; n < lblk_per_pblk(params); ++n) {
lba->pblk[n] = get16_le(&buf);
}
}
else if (params->nr_pblk <= 0xffffffff) {
else if (pblk_bytes == 4) {
for (n = 0; n < lblk_per_pblk(params); ++n) {
lba->pblk[n] = get32_le(&buf);
}
@ -380,19 +416,21 @@ lba_put(const struct cbd_params* params,
u8* buf, const struct lba* lba)
{
u32 n;
u32 len_bytes = lba_elem_len_bytes(params);
u32 pblk_bytes = lba_elem_pblk_bytes(params);
if (params->lblk_shift + PBLK_SHIFT > 16) {
put32_le(&buf, lba->len);
}
else {
if (len_bytes == 2) {
put16_le(&buf, lba->len);
}
if (params->nr_pblk <= 0xffff) {
else {
put32_le(&buf, lba->len);
}
if (pblk_bytes == 2) {
for (n = 0; n < lblk_per_pblk(params); ++n) {
put16_le(&buf, lba->pblk[n]);
}
}
else if (params->nr_pblk <= 0xffffffff) {
else if (pblk_bytes == 4) {
for (n = 0; n < lblk_per_pblk(params); ++n) {
put32_le(&buf, lba->pblk[n]);
}
@ -406,14 +444,11 @@ lba_put(const struct cbd_params* params,
#ifdef __KERNEL__
#define ZONE_NONE (u32)(~0)
#define PBLK_NONE (u64)(~0)
#define LBLK_NONE (u64)(~0)
enum cache_state {
CACHE_STATE_UNCACHED,
CACHE_STATE_CLEAN,
CACHE_STATE_DIRTY,
CACHE_STATE_ERROR,
CACHE_STATE_MAX
};