More improvements, but still failing to clone linux
This commit is contained in:
parent
495d191d16
commit
446a4811f6
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue