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)
|
lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 req_nalloc;
|
int err;
|
||||||
u32 elem_off;
|
u32 elem_off;
|
||||||
|
u32 elem_len;
|
||||||
|
u32 req_nalloc;
|
||||||
|
u32 cur_nalloc;
|
||||||
|
u32 old_nalloc;
|
||||||
u32 off;
|
u32 off;
|
||||||
u32 n;
|
|
||||||
u64 pblk;
|
u64 pblk;
|
||||||
u32 elem_lelen;
|
u32 elem_lelen;
|
||||||
u64 elem_lepblk;
|
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);
|
mutex_lock(&lv->lock);
|
||||||
elem_off = lbatview_elem_off(lv, lblk);
|
elem_off = lbatview_elem_off(lv, lblk);
|
||||||
elem_lelen = __cpu_to_le32(len);
|
req_nalloc = (len == CBD_UNCOMPRESSED) ?
|
||||||
lbatview_wmem(lv, elem_off, lba_elem_len_bytes(lv->params), &elem_lelen);
|
lblk_per_pblk(lv->params) :
|
||||||
off = elem_off + lba_elem_len_bytes(lv->params);
|
DIV_ROUND_UP(len, PBLK_SIZE);
|
||||||
for (n = 0; n < lblk_per_pblk(lv->params); ++n, off += lba_elem_pblk_bytes(lv->params)) {
|
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;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
elem_lepblk = 0;
|
||||||
lbatview_rmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
|
lbatview_rmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
|
||||||
pblk = __le64_to_cpu(elem_lepblk);
|
pblk = __le64_to_cpu(elem_lepblk);
|
||||||
if (pblk == 0) {
|
err = lbatview_free_pblk(lv, pblk);
|
||||||
if (n >= req_nalloc) {
|
if (err) {
|
||||||
break;
|
printk(KERN_ERR "%s: lbatview_free_pblk failed\n", __func__);
|
||||||
}
|
ret = err;
|
||||||
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 (n >= req_nalloc) {
|
|
||||||
elem_lepblk = 0;
|
|
||||||
lbatview_wmem(lv, off, lba_elem_pblk_bytes(lv->params), &elem_lepblk);
|
|
||||||
ret = lbatview_free_pblk(lv, pblk);
|
|
||||||
if (ret) {
|
|
||||||
printk(KERN_ERR "%s: lbatview_free_pblk failed\n", __func__);
|
|
||||||
goto out; /* XXX: undo */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
mutex_unlock(&lv->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ check_one_lblk(const struct cbd_params* params,
|
||||||
{
|
{
|
||||||
struct lba* lba;
|
struct lba* lba;
|
||||||
u8* lba_buf;
|
u8* lba_buf;
|
||||||
u32 c_len;
|
u32 n_alloc;
|
||||||
u32 n;
|
u32 n;
|
||||||
u64 pblk;
|
u64 pblk;
|
||||||
|
|
||||||
|
@ -87,45 +87,40 @@ check_one_lblk(const struct cbd_params* params,
|
||||||
printf(" :E: Length out of bounds\n");
|
printf(" :E: Length out of bounds\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
c_len = (lba->len == CBD_UNCOMPRESSED) ? PBLK_SIZE * lblk_per_pblk(params) : lba->len;
|
n_alloc = (lba->len == CBD_UNCOMPRESSED) ?
|
||||||
for (n = 0; n < lblk_per_pblk(params); ++n) {
|
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];
|
pblk = lba->pblk[n];
|
||||||
if (c_len > PBLK_SIZE * n) {
|
if (pblk < CBD_HEADER_BLOCKS) {
|
||||||
u32 pblk_zone;
|
printf(" [%u] :E: Alloc in header: %lu\n", n, pblk);
|
||||||
u32 rel_pblk;
|
continue;
|
||||||
if (pblk < CBD_HEADER_BLOCKS) {
|
|
||||||
printf(" [%u] :E: Alloc in header: %lu\n", n, pblk);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pblk_zone = (pblk - CBD_HEADER_BLOCKS) / zone_len(params);
|
|
||||||
if (pblk_zone >= params->nr_zones) {
|
|
||||||
printf(" [%u] :E: Alloc beyond end: %lu\n", n, pblk);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (pblk < zone_data_off(params, pblk_zone)) {
|
|
||||||
printf(" [%u] :E: Alloc in metadata: %lu\n", n, pblk);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
rel_pblk = pblk - zone_data_off(params, pblk_zone);
|
|
||||||
/* XXX: Cannot happen? */
|
|
||||||
if (rel_pblk >= pbat_len(params) * PBLK_SIZE_BITS) {
|
|
||||||
printf(" [%u] :E: Alloc out of zone: %lu\n", n, pblk);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
printf(" [%u] pblk=%lu pblk_zone=%u rel_pblk=%u\n", n,
|
|
||||||
(unsigned long)pblk, pblk_zone, rel_pblk);
|
|
||||||
if (pblk_used[pblk_zone][rel_pblk/8] & (1 << (rel_pblk % 8))) {
|
|
||||||
printf(" [%u] :E: Duplicate allocation for zone %u block %u\n",
|
|
||||||
n, pblk_zone, rel_pblk);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
pblk_used[pblk_zone][rel_pblk/8] |= (1 << (rel_pblk % 8));
|
|
||||||
}
|
}
|
||||||
else {
|
pblk_zone = (pblk - CBD_HEADER_BLOCKS) / zone_len(params);
|
||||||
if (pblk) {
|
if (pblk_zone >= params->nr_zones) {
|
||||||
printf(" [%u] :E: Unexpected pblk alloc: %lu\n", n, pblk);
|
printf(" [%u] :E: Alloc beyond end: %lu\n", n, pblk);
|
||||||
}
|
continue;
|
||||||
}
|
}
|
||||||
|
if (pblk < zone_data_off(params, pblk_zone)) {
|
||||||
|
printf(" [%u] :E: Alloc in metadata: %lu\n", n, pblk);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rel_pblk = pblk - zone_data_off(params, pblk_zone);
|
||||||
|
/* XXX: Cannot happen? */
|
||||||
|
if (rel_pblk >= pbat_len(params) * PBLK_SIZE_BITS) {
|
||||||
|
printf(" [%u] :E: Alloc out of zone: %lu\n", n, pblk);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf(" [%u] pblk=%lu pblk_zone=%u rel_pblk=%u\n", n,
|
||||||
|
(unsigned long)pblk, pblk_zone, rel_pblk);
|
||||||
|
if (pblk_used[pblk_zone][rel_pblk/8] & (1 << (rel_pblk % 8))) {
|
||||||
|
printf(" [%u] :E: Duplicate allocation for zone %u block %u\n",
|
||||||
|
n, pblk_zone, rel_pblk);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pblk_used[pblk_zone][rel_pblk/8] |= (1 << (rel_pblk % 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
free(lba);
|
free(lba);
|
||||||
|
|
Loading…
Reference in New Issue