Rewrite lbatview_elem_realloc
* Only touch the data we need to touch. * Handle failure gracefully by reverting to old data. * Adjust libcbd check_one_lblk to ignore unused allocs.
This commit is contained in:
parent
5be74b3346
commit
7a743a7e65
|
@ -315,56 +315,64 @@ int
|
|||
lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 req_nalloc;
|
||||
int err;
|
||||
u32 elem_off;
|
||||
u32 elem_len;
|
||||
u32 req_nalloc;
|
||||
u32 cur_nalloc;
|
||||
u32 old_nalloc;
|
||||
u32 off;
|
||||
u32 n;
|
||||
u64 pblk;
|
||||
u32 elem_lelen;
|
||||
u64 elem_lepblk;
|
||||
|
||||
if (len == CBD_UNCOMPRESSED) {
|
||||
req_nalloc = lblk_per_pblk(lv->params);
|
||||
}
|
||||
else {
|
||||
req_nalloc = DIV_ROUND_UP(len, PBLK_SIZE);
|
||||
}
|
||||
mutex_lock(&lv->lock);
|
||||
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, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
|
||||
pblk = __le64_to_cpu(elem_lepblk);
|
||||
if (pblk == 0) {
|
||||
if (n >= req_nalloc) {
|
||||
break;
|
||||
}
|
||||
req_nalloc = (len == CBD_UNCOMPRESSED) ?
|
||||
lblk_per_pblk(lv->params) :
|
||||
DIV_ROUND_UP(len, PBLK_SIZE);
|
||||
elem_lelen = 0;
|
||||
lbatview_rmem(lv, elem_off, lba_elem_len_bytes(lv->params), &elem_lelen);
|
||||
elem_len = __le32_to_cpu(elem_lelen);
|
||||
cur_nalloc = (elem_len == CBD_UNCOMPRESSED) ?
|
||||
lblk_per_pblk(lv->params) :
|
||||
DIV_ROUND_UP(elem_len, PBLK_SIZE);
|
||||
old_nalloc = cur_nalloc;
|
||||
|
||||
while (cur_nalloc < req_nalloc) {
|
||||
off = elem_off + lba_elem_len_bytes(lv->params) +
|
||||
cur_nalloc * lba_elem_pblk_bytes(lv->params);
|
||||
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 */
|
||||
req_nalloc = old_nalloc;
|
||||
goto do_free;
|
||||
}
|
||||
elem_lepblk = __cpu_to_le64(pblk);
|
||||
lbatview_wmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
|
||||
++cur_nalloc;
|
||||
}
|
||||
else {
|
||||
if (n >= req_nalloc) {
|
||||
do_free:
|
||||
while (cur_nalloc > req_nalloc) {
|
||||
--cur_nalloc;
|
||||
off = elem_off + lba_elem_len_bytes(lv->params) +
|
||||
cur_nalloc * lba_elem_pblk_bytes(lv->params);
|
||||
elem_lepblk = 0;
|
||||
lbatview_wmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
|
||||
ret = lbatview_free_pblk(lv, pblk);
|
||||
if (ret) {
|
||||
lbatview_rmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
|
||||
pblk = __le64_to_cpu(elem_lepblk);
|
||||
err = lbatview_free_pblk(lv, pblk);
|
||||
if (err) {
|
||||
printk(KERN_ERR "%s: lbatview_free_pblk failed\n", __func__);
|
||||
goto out; /* XXX: undo */
|
||||
}
|
||||
}
|
||||
ret = err;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (!ret) {
|
||||
elem_lelen = __cpu_to_le32(len);
|
||||
lbatview_wmem(lv, elem_off, lba_elem_len_bytes(lv->params), &elem_lelen);
|
||||
}
|
||||
|
||||
mutex_unlock(&lv->lock);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ check_one_lblk(const struct cbd_params* params,
|
|||
{
|
||||
struct lba* lba;
|
||||
u8* lba_buf;
|
||||
u32 c_len;
|
||||
u32 n_alloc;
|
||||
u32 n;
|
||||
u64 pblk;
|
||||
|
||||
|
@ -87,12 +87,13 @@ check_one_lblk(const struct cbd_params* params,
|
|||
printf(" :E: Length out of bounds\n");
|
||||
return;
|
||||
}
|
||||
c_len = (lba->len == CBD_UNCOMPRESSED) ? PBLK_SIZE * lblk_per_pblk(params) : lba->len;
|
||||
for (n = 0; n < lblk_per_pblk(params); ++n) {
|
||||
pblk = lba->pblk[n];
|
||||
if (c_len > PBLK_SIZE * n) {
|
||||
n_alloc = (lba->len == CBD_UNCOMPRESSED) ?
|
||||
lblk_per_pblk(params) :
|
||||
DIV_ROUND_UP(lba->len, PBLK_SIZE);
|
||||
for (n = 0; n < n_alloc; ++n) {
|
||||
u32 pblk_zone;
|
||||
u32 rel_pblk;
|
||||
pblk = lba->pblk[n];
|
||||
if (pblk < CBD_HEADER_BLOCKS) {
|
||||
printf(" [%u] :E: Alloc in header: %lu\n", n, pblk);
|
||||
continue;
|
||||
|
@ -121,12 +122,6 @@ check_one_lblk(const struct cbd_params* params,
|
|||
}
|
||||
pblk_used[pblk_zone][rel_pblk/8] |= (1 << (rel_pblk % 8));
|
||||
}
|
||||
else {
|
||||
if (pblk) {
|
||||
printf(" [%u] :E: Unexpected pblk alloc: %lu\n", n, pblk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(lba);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue