Use page vector and vmap for lbd
This commit is contained in:
parent
8e1630b08c
commit
11cc8a229e
|
@ -40,7 +40,7 @@ struct lbd {
|
||||||
struct lbatviewcache* lvc;
|
struct lbatviewcache* lvc;
|
||||||
struct lbatview* lv;
|
struct lbatview* lv;
|
||||||
void* percpu;
|
void* percpu;
|
||||||
struct page* pages;
|
struct page** pagev;
|
||||||
u8* buf;
|
u8* buf;
|
||||||
u32 c_len;
|
u32 c_len;
|
||||||
};
|
};
|
||||||
|
@ -292,6 +292,8 @@ lbd_ctr(struct lbd* lbd,
|
||||||
struct lbatviewcache* lvc,
|
struct lbatviewcache* lvc,
|
||||||
void* percpu)
|
void* percpu)
|
||||||
{
|
{
|
||||||
|
u32 nr_pages = lblk_per_pblk(params);
|
||||||
|
|
||||||
memset(lbd, 0, sizeof(struct lbd));
|
memset(lbd, 0, sizeof(struct lbd));
|
||||||
lbd->lblk = LBLK_NONE;
|
lbd->lblk = LBLK_NONE;
|
||||||
mutex_init(&lbd->reflock);
|
mutex_init(&lbd->reflock);
|
||||||
|
@ -301,11 +303,17 @@ lbd_ctr(struct lbd* lbd,
|
||||||
lbd->lvc = lvc;
|
lbd->lvc = lvc;
|
||||||
lbd->lv = NULL;
|
lbd->lv = NULL;
|
||||||
lbd->percpu = percpu;
|
lbd->percpu = percpu;
|
||||||
lbd->pages = cbd_alloc_pages(lblk_per_pblk(lbd->params));
|
lbd->pagev = kzalloc(nr_pages * sizeof(struct page*), GFP_KERNEL);
|
||||||
if (!lbd->pages) {
|
if (!lbd->pagev) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!cbd_alloc_pagev(lbd->pagev, nr_pages)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lbd->buf = vmap(lbd->pagev, nr_pages, VM_MAP, PAGE_KERNEL);
|
||||||
|
if (!lbd->buf) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
lbd->buf = page_address(lbd->pages);
|
|
||||||
lbd->c_len = 0;
|
lbd->c_len = 0;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -314,13 +322,17 @@ lbd_ctr(struct lbd* lbd,
|
||||||
static void
|
static void
|
||||||
lbd_dtr(struct lbd* lbd)
|
lbd_dtr(struct lbd* lbd)
|
||||||
{
|
{
|
||||||
|
u32 nr_pages = lblk_per_pblk(lbd->params);
|
||||||
|
|
||||||
if (lbatviewcache_put(lbd->lvc, lbd->lv) != 0) {
|
if (lbatviewcache_put(lbd->lvc, lbd->lv) != 0) {
|
||||||
printk(KERN_ERR "%s: lbatviewcache_put failed\n", __func__);
|
printk(KERN_ERR "%s: lbatviewcache_put failed\n", __func__);
|
||||||
}
|
}
|
||||||
lbd->c_len = 0;
|
lbd->c_len = 0;
|
||||||
|
vunmap(lbd->buf);
|
||||||
lbd->buf = NULL;
|
lbd->buf = NULL;
|
||||||
cbd_free_pages(lbd->pages, lblk_per_pblk(lbd->params));
|
cbd_free_pagev(lbd->pagev, nr_pages);
|
||||||
lbd->pages = NULL;
|
kfree(lbd->pagev);
|
||||||
|
lbd->pagev = NULL;
|
||||||
lbd->percpu = NULL;
|
lbd->percpu = NULL;
|
||||||
lbd->lv = NULL;
|
lbd->lv = NULL;
|
||||||
lbd->lvc = NULL;
|
lbd->lvc = NULL;
|
||||||
|
@ -331,10 +343,9 @@ lbd_error(struct lbd* lbd)
|
||||||
{
|
{
|
||||||
u32 count = lblk_per_pblk(lbd->params);
|
u32 count = lblk_per_pblk(lbd->params);
|
||||||
u32 n;
|
u32 n;
|
||||||
u8* p;
|
|
||||||
|
|
||||||
for (n = 0, p = lbd->buf; n < count; ++n, p += PBLK_SIZE) {
|
for (n = 0; n < count; ++n) {
|
||||||
if (PageError(virt_to_page(p))) {
|
if (PageError(lbd->pagev[n])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,14 +358,13 @@ lbd_flush(struct lbd* lbd)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int err;
|
int err;
|
||||||
u8* p;
|
|
||||||
u32 n;
|
u32 n;
|
||||||
u64 pblk;
|
u64 pblk;
|
||||||
u32 count = lblk_per_pblk(lbd->params);
|
u32 count = lblk_per_pblk(lbd->params);
|
||||||
struct page* iopagev[count];
|
struct page* iopagev[count];
|
||||||
|
|
||||||
mutex_lock(&lbd->lock);
|
mutex_lock(&lbd->lock);
|
||||||
if (!PageDirty(lbd->pages)) {
|
if (!PageDirty(lbd->pagev[0])) {
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
if (lbd_error(lbd)) {
|
if (lbd_error(lbd)) {
|
||||||
|
@ -383,23 +393,22 @@ lbd_flush(struct lbd* lbd)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto unlock;
|
goto unlock;
|
||||||
}
|
}
|
||||||
for (n = 0, p = lbd->buf; n < count; ++n, p += PBLK_SIZE) {
|
for (n = 0; n < count; ++n) {
|
||||||
pblk = lbatview_elem_pblk(lbd->lv, lbd->lblk, n);
|
pblk = lbatview_elem_pblk(lbd->lv, lbd->lblk, n);
|
||||||
BUG_ON(pblk == PBLK_NONE);
|
BUG_ON(pblk == PBLK_NONE);
|
||||||
iopagev[0] = virt_to_page(p);
|
iopagev[0] = lbd->pagev[n];
|
||||||
pblk_write(lbd->params, pblk, 1, iopagev);
|
pblk_write(lbd->params, pblk, 1, iopagev);
|
||||||
}
|
}
|
||||||
while (n < lblk_per_pblk(lbd->params)) {
|
while (n < lblk_per_pblk(lbd->params)) {
|
||||||
unlock_page(virt_to_page(p));
|
unlock_page(lbd->pagev[n]);
|
||||||
++n;
|
++n;
|
||||||
p += PBLK_SIZE;
|
|
||||||
}
|
}
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
count = lblk_per_pblk(lbd->params);
|
count = lblk_per_pblk(lbd->params);
|
||||||
for (n = 0, p = lbd->buf; n < count; ++n, p += PBLK_SIZE) {
|
for (n = 0; n < count; ++n) {
|
||||||
unlock_page(virt_to_page(p));
|
unlock_page(lbd->pagev[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -419,12 +428,11 @@ lbd_read(struct lbd* lbd)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 count;
|
u32 count;
|
||||||
u32 n;
|
u32 n;
|
||||||
u8* p;
|
|
||||||
u64 pblk;
|
u64 pblk;
|
||||||
struct page* iopagev[1];
|
struct page* iopagev[1];
|
||||||
|
|
||||||
/* XXX: can't happen because lbdcache will not use a page with an error */
|
/* XXX: can't happen because lbdcache will not use a page with an error */
|
||||||
if (PageError(lbd->pages)) {
|
if (PageError(lbd->pagev[0])) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
lbd->c_len = lbatview_elem_len(lbd->lv, lbd->lblk);
|
lbd->c_len = lbatview_elem_len(lbd->lv, lbd->lblk);
|
||||||
|
@ -435,13 +443,13 @@ lbd_read(struct lbd* lbd)
|
||||||
count = (lbd->c_len == CBD_UNCOMPRESSED) ?
|
count = (lbd->c_len == CBD_UNCOMPRESSED) ?
|
||||||
lblk_per_pblk(lbd->params) :
|
lblk_per_pblk(lbd->params) :
|
||||||
DIV_ROUND_UP(lbd->c_len, PBLK_SIZE);
|
DIV_ROUND_UP(lbd->c_len, PBLK_SIZE);
|
||||||
for (n = 0, p = lbd->buf; n < count; ++n, p += PBLK_SIZE) {
|
for (n = 0; n < count; ++n) {
|
||||||
pblk = lbatview_elem_pblk(lbd->lv, lbd->lblk, n);
|
pblk = lbatview_elem_pblk(lbd->lv, lbd->lblk, n);
|
||||||
if (pblk == PBLK_NONE) {
|
if (pblk == PBLK_NONE) {
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
iopagev[0] = virt_to_page(p);
|
iopagev[0] = lbd->pagev[n];
|
||||||
/* XXX: Issue non-blocking reads? */
|
/* XXX: Issue non-blocking reads? */
|
||||||
ret = pblk_read_wait(lbd->params, pblk, 1, iopagev);
|
ret = pblk_read_wait(lbd->params, pblk, 1, iopagev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -468,12 +476,11 @@ lbd_reset(struct lbd* lbd, u64 lblk)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 count = lblk_per_pblk(lbd->params);
|
u32 count = lblk_per_pblk(lbd->params);
|
||||||
u32 n;
|
u32 n;
|
||||||
u8* p;
|
|
||||||
|
|
||||||
if (lbd->lv) { printk(KERN_ERR "%s: lbatview leak\n", __func__); }
|
if (lbd->lv) { printk(KERN_ERR "%s: lbatview leak\n", __func__); }
|
||||||
|
|
||||||
for (n = 0, p = lbd->buf; n < count; ++n, p += PBLK_SIZE) {
|
for (n = 0; n < count; ++n) {
|
||||||
lock_page(virt_to_page(p));
|
lock_page(lbd->pagev[n]);
|
||||||
}
|
}
|
||||||
lbd->lv = lbatviewcache_get(lbd->lvc, lblk);
|
lbd->lv = lbatviewcache_get(lbd->lvc, lblk);
|
||||||
if (!lbd->lv) {
|
if (!lbd->lv) {
|
||||||
|
@ -502,8 +509,8 @@ out:
|
||||||
if (ret) {
|
if (ret) {
|
||||||
lbatviewcache_put(lbd->lvc, lbd->lv);
|
lbatviewcache_put(lbd->lvc, lbd->lv);
|
||||||
lbd->lv = NULL;
|
lbd->lv = NULL;
|
||||||
for (n = 0, p = lbd->buf; n < count; ++n, p += PBLK_SIZE) {
|
for (n = 0; n < count; ++n) {
|
||||||
unlock_page(virt_to_page(p));
|
unlock_page(lbd->pagev[n]);
|
||||||
}
|
}
|
||||||
lbd->lblk = LBLK_NONE;
|
lbd->lblk = LBLK_NONE;
|
||||||
}
|
}
|
||||||
|
@ -534,7 +541,7 @@ lbd_data_write(struct lbd* lbd, u32 off, u32 len, const u8* buf)
|
||||||
}
|
}
|
||||||
mutex_lock(&lbd->lock);
|
mutex_lock(&lbd->lock);
|
||||||
memcpy(lbd->buf + off, buf, len);
|
memcpy(lbd->buf + off, buf, len);
|
||||||
SetPageDirty(lbd->pages);
|
SetPageDirty(lbd->pagev[0]);
|
||||||
mutex_unlock(&lbd->lock);
|
mutex_unlock(&lbd->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,7 +581,7 @@ lbdcache_realloc(struct lbdcache* lc, unsigned int len)
|
||||||
lc->len = len;
|
lc->len = len;
|
||||||
lc->cache = cache;
|
lc->cache = cache;
|
||||||
while (n < len) {
|
while (n < len) {
|
||||||
lbd = kmalloc(sizeof(struct lbd), GFP_KERNEL);
|
lbd = kzalloc(sizeof(struct lbd), GFP_KERNEL);
|
||||||
if (!lbd) {
|
if (!lbd) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue