Optimize lblk handling
This commit is contained in:
parent
a5cc0f2e81
commit
7326fe2e14
|
@ -40,6 +40,7 @@
|
||||||
#define USE_WORKQUEUE 1
|
#define USE_WORKQUEUE 1
|
||||||
|
|
||||||
#define ZONE_NONE (u32)(~0)
|
#define ZONE_NONE (u32)(~0)
|
||||||
|
#define PBLK_NONE (u64)(~0)
|
||||||
#define LBLK_NONE (u64)(~0)
|
#define LBLK_NONE (u64)(~0)
|
||||||
|
|
||||||
/* per bio private data */
|
/* per bio private data */
|
||||||
|
@ -69,13 +70,15 @@ struct dm_compress
|
||||||
void* pblk_alloc;
|
void* pblk_alloc;
|
||||||
|
|
||||||
/* Currently cached zone lblk alloc info (if any) */
|
/* Currently cached zone lblk alloc info (if any) */
|
||||||
u32 lblk_alloc_idx;
|
u64 lblk_alloc_pblk;
|
||||||
|
u32 lblk_alloc_len;
|
||||||
void* lblk_alloc;
|
void* lblk_alloc;
|
||||||
|
u64 lblk_alloc_elem_lblk;
|
||||||
|
struct lblk_alloc_elem* lblk_alloc_elem;
|
||||||
|
|
||||||
/* Currently cached lblk data (if any) */
|
/* Currently cached lblk data (if any) */
|
||||||
u64 lblk_num;
|
u64 lblk_num;
|
||||||
bool lblk_dirty;
|
bool lblk_dirty;
|
||||||
struct lblk_alloc_elem* lblk_alloc_elem;
|
|
||||||
|
|
||||||
void* lblk;
|
void* lblk;
|
||||||
|
|
||||||
|
@ -339,54 +342,75 @@ pblk_alloc_put(struct dm_compress* dc, u64 pblk)
|
||||||
**************************************/
|
**************************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lblk_alloc_write(struct dm_compress* dc)
|
lblk_alloc_elem_write(struct dm_compress* dc)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u64 pblk;
|
u32 zone;
|
||||||
|
u32 zone_lblk;
|
||||||
|
u32 elem_off;
|
||||||
|
u32 elem_end;
|
||||||
|
u32 rel_pblk;
|
||||||
u32 count;
|
u32 count;
|
||||||
|
u64 pblk;
|
||||||
|
u8* buf;
|
||||||
|
|
||||||
if (!dc->lblk_alloc) {
|
BUG_ON(dc->lblk_alloc_elem_lblk == LBLK_NONE);
|
||||||
printk(KERN_ERR "%s: lblk_alloc is NULL\n", __func__);
|
BUG_ON(dc->lblk_alloc_pblk == PBLK_NONE);
|
||||||
return -EINVAL;
|
BUG_ON(dc->lblk_alloc_len == 0);
|
||||||
|
|
||||||
|
zone = dc->lblk_alloc_elem_lblk / dc->params.lblk_per_zone;
|
||||||
|
zone_lblk = dc->lblk_alloc_elem_lblk - (zone * dc->params.lblk_per_zone);
|
||||||
|
elem_off = lblk_alloc_elem_len(&dc->params) * zone_lblk;
|
||||||
|
elem_end = elem_off + lblk_alloc_elem_len(&dc->params);
|
||||||
|
rel_pblk = elem_off / PBLK_SIZE;
|
||||||
|
count = dc->lblk_alloc_len;
|
||||||
|
pblk = dc->lblk_alloc_pblk;
|
||||||
|
buf = dc->lblk_alloc + (elem_off - rel_pblk * PBLK_SIZE);
|
||||||
|
lblk_alloc_elem_put(&dc->params, buf, dc->lblk_alloc_elem);
|
||||||
|
ret = blkdev_pblk_write(dc->dev->bdev, pblk, count, dc->lblk_alloc);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
lblk_alloc_elem_read(struct dm_compress* dc, u64 lblk)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 zone;
|
||||||
|
u32 zone_lblk;
|
||||||
|
u32 elem_off;
|
||||||
|
u32 elem_end;
|
||||||
|
u32 rel_pblk;
|
||||||
|
u32 count;
|
||||||
|
u64 pblk;
|
||||||
|
u8* buf;
|
||||||
|
|
||||||
|
if (dc->lblk_alloc_elem_lblk == lblk) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BUG_ON(dc->lblk_alloc_idx == ZONE_NONE);
|
zone = lblk / dc->params.lblk_per_zone;
|
||||||
pblk = lblk_alloc_off(&dc->params, dc->lblk_alloc_idx);
|
zone_lblk = lblk - (zone * dc->params.lblk_per_zone);
|
||||||
count = lblk_alloc_len(&dc->params);
|
elem_off = lblk_alloc_elem_len(&dc->params) * zone_lblk;
|
||||||
|
elem_end = elem_off + lblk_alloc_elem_len(&dc->params);
|
||||||
ret = blkdev_pblk_write(dc->dev->bdev, pblk, count, dc->lblk_alloc);
|
rel_pblk = elem_off / PBLK_SIZE;
|
||||||
|
count = 1 + (elem_end - 1) / PBLK_SIZE - (elem_off / PBLK_SIZE);
|
||||||
|
pblk = lblk_alloc_off(&dc->params, zone) + rel_pblk;
|
||||||
|
if (dc->lblk_alloc_pblk != pblk || dc->lblk_alloc_len < count) {
|
||||||
|
ret = blkdev_pblk_read(dc->dev->bdev, pblk, count, dc->lblk_alloc);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
dc->lblk_alloc_pblk = pblk;
|
||||||
|
dc->lblk_alloc_len = count;
|
||||||
|
}
|
||||||
|
buf = dc->lblk_alloc + (elem_off - rel_pblk * PBLK_SIZE);
|
||||||
|
lblk_alloc_elem_get(&dc->params, buf, dc->lblk_alloc_elem);
|
||||||
|
dc->lblk_alloc_elem_lblk = lblk;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX: Another opportunity to choose speed vs. space: only allocate two
|
|
||||||
* pages for lblk_alloc_elem buffer instead of the entire lblk_alloc.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
lblk_alloc_read(struct dm_compress* dc, u32 idx)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
u64 pblk;
|
|
||||||
u32 count;
|
|
||||||
|
|
||||||
if (dc->lblk_alloc_idx == idx) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pblk = lblk_alloc_off(&dc->params, idx);
|
|
||||||
count = lblk_alloc_len(&dc->params);
|
|
||||||
ret = blkdev_pblk_read(dc->dev->bdev, pblk, count, dc->lblk_alloc);
|
|
||||||
if (ret == 0) {
|
|
||||||
dc->lblk_alloc_idx = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
* Logical block functions
|
* Logical block functions
|
||||||
**************************************/
|
**************************************/
|
||||||
|
@ -452,15 +476,8 @@ lblk_write(struct dm_compress* dc)
|
||||||
zone_lblk = dc->lblk_num - (zone * dc->params.lblk_per_zone);
|
zone_lblk = dc->lblk_num - (zone * dc->params.lblk_per_zone);
|
||||||
elem_buf = dc->lblk_alloc + zone_lblk * lblk_alloc_elem_len(&dc->params);
|
elem_buf = dc->lblk_alloc + zone_lblk * lblk_alloc_elem_len(&dc->params);
|
||||||
|
|
||||||
/*
|
/* We must have a cached lblk elem */
|
||||||
* We must have dc->lblk_alloc and dc->lblk_alloc_elem cached by
|
BUG_ON(dc->lblk_alloc_elem_lblk == LBLK_NONE);
|
||||||
* the previous lblk_read().
|
|
||||||
*/
|
|
||||||
if (dc->lblk_alloc_idx != zone) {
|
|
||||||
printk(KERN_ERR "*** lblk_alloc not cached: %lu vs %lu\n", (unsigned long)dc->lblk_alloc_idx, (unsigned long)zone);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
BUG_ON(dc->lblk_alloc_idx != zone);
|
|
||||||
|
|
||||||
d_len = PBLK_SIZE * lblk_per_pblk(&dc->params);
|
d_len = PBLK_SIZE * lblk_per_pblk(&dc->params);
|
||||||
#ifdef CBD_DETECT_ZERO_BLOCKS
|
#ifdef CBD_DETECT_ZERO_BLOCKS
|
||||||
|
@ -512,10 +529,9 @@ lblk_write(struct dm_compress* dc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lblk_alloc_elem_put(&dc->params, elem_buf, dc->lblk_alloc_elem);
|
ret = lblk_alloc_elem_write(dc);
|
||||||
ret = lblk_alloc_write(dc);
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printk(KERN_ERR " lblk_alloc_write failed\n");
|
printk(KERN_ERR " lblk_alloc_elem_write failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret = pblk_alloc_flush(dc);
|
ret = pblk_alloc_flush(dc);
|
||||||
|
@ -566,12 +582,11 @@ lblk_read(struct dm_compress* dc, u64 idx)
|
||||||
zone_lblk = idx - (zone * dc->params.lblk_per_zone);
|
zone_lblk = idx - (zone * dc->params.lblk_per_zone);
|
||||||
elem_buf = dc->lblk_alloc + zone_lblk * lblk_alloc_elem_len(&dc->params);
|
elem_buf = dc->lblk_alloc + zone_lblk * lblk_alloc_elem_len(&dc->params);
|
||||||
|
|
||||||
ret = lblk_alloc_read(dc, zone);
|
ret = lblk_alloc_elem_read(dc, idx);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printk(KERN_ERR " lblk_alloc_read failed\n");
|
printk(KERN_ERR " lblk_alloc_elem_read failed\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
lblk_alloc_elem_get(&dc->params, elem_buf, dc->lblk_alloc_elem);
|
|
||||||
|
|
||||||
c_len = dc->lblk_alloc_elem->len;
|
c_len = dc->lblk_alloc_elem->len;
|
||||||
if (c_len == 0) {
|
if (c_len == 0) {
|
||||||
|
@ -671,7 +686,7 @@ compress_free_buffers(struct dm_compress* dc)
|
||||||
kfree(dc->lblk_alloc_elem);
|
kfree(dc->lblk_alloc_elem);
|
||||||
dc->lblk_alloc_elem = NULL;
|
dc->lblk_alloc_elem = NULL;
|
||||||
|
|
||||||
compress_free_pages(dc->lblk_alloc, PBLK_SIZE * lblk_alloc_len(&dc->params));
|
compress_free_pages(dc->lblk_alloc, PBLK_SIZE * 2);
|
||||||
dc->lblk_alloc = NULL;
|
dc->lblk_alloc = NULL;
|
||||||
|
|
||||||
compress_free_pages(dc->pblk_alloc, PBLK_SIZE * pblk_alloc_len(&dc->params));
|
compress_free_pages(dc->pblk_alloc, PBLK_SIZE * pblk_alloc_len(&dc->params));
|
||||||
|
@ -709,19 +724,21 @@ compress_alloc_buffers(struct dm_compress* dc)
|
||||||
printk(KERN_ERR "%s: Failed to alloc pblk_alloc\n", __func__);
|
printk(KERN_ERR "%s: Failed to alloc pblk_alloc\n", __func__);
|
||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
}
|
}
|
||||||
dc->lblk_alloc_idx = ZONE_NONE;
|
dc->lblk_alloc_pblk = PBLK_NONE;
|
||||||
dc->lblk_alloc = compress_alloc_pages(PBLK_SIZE * lblk_alloc_len(&dc->params));
|
dc->lblk_alloc_len = 0;
|
||||||
|
dc->lblk_alloc = compress_alloc_pages(PBLK_SIZE * 2);
|
||||||
if (!dc->lblk_alloc) {
|
if (!dc->lblk_alloc) {
|
||||||
printk(KERN_ERR "%s: Failed to alloc lblk_alloc\n", __func__);
|
printk(KERN_ERR "%s: Failed to alloc lblk_alloc\n", __func__);
|
||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
}
|
}
|
||||||
dc->lblk_num = LBLK_NONE;
|
dc->lblk_alloc_elem_lblk = LBLK_NONE;
|
||||||
dc->lblk_dirty = false;
|
|
||||||
dc->lblk_alloc_elem = kmalloc(offsetof(struct lblk_alloc_elem, pblk[lblk_per_pblk(&dc->params)]), GFP_KERNEL);
|
dc->lblk_alloc_elem = kmalloc(offsetof(struct lblk_alloc_elem, pblk[lblk_per_pblk(&dc->params)]), GFP_KERNEL);
|
||||||
if (!dc->lblk_alloc_elem) {
|
if (!dc->lblk_alloc_elem) {
|
||||||
printk(KERN_ERR "%s: Failed to alloc lblk_alloc_elem\n", __func__);
|
printk(KERN_ERR "%s: Failed to alloc lblk_alloc_elem\n", __func__);
|
||||||
goto out_nomem;
|
goto out_nomem;
|
||||||
}
|
}
|
||||||
|
dc->lblk_num = LBLK_NONE;
|
||||||
|
dc->lblk_dirty = false;
|
||||||
dc->lblk = compress_alloc_pages(PBLK_SIZE * lblk_per_pblk(&dc->params));
|
dc->lblk = compress_alloc_pages(PBLK_SIZE * lblk_per_pblk(&dc->params));
|
||||||
if (!dc->lblk) {
|
if (!dc->lblk) {
|
||||||
printk(KERN_ERR "%s: Failed to alloc lblk\n", __func__);
|
printk(KERN_ERR "%s: Failed to alloc lblk\n", __func__);
|
||||||
|
|
Loading…
Reference in New Issue