First fully working version

This commit is contained in:
Tom Marshall 2019-10-25 10:03:00 -07:00
parent 1b5b24a179
commit f8361d1e2e
6 changed files with 104 additions and 133 deletions

View File

@ -42,7 +42,7 @@ struct lbatpage {
bool dirty;
};
bool
static bool
lbatpage_ctr(struct lbatpage* lp, struct cbd_params* params)
{
lp->pblk = PBLK_NONE;
@ -61,7 +61,7 @@ lbatpage_ctr(struct lbatpage* lp, struct cbd_params* params)
return true;
}
void
static void
lbatpage_dtr(struct lbatpage* lp)
{
lp->buf = NULL;
@ -83,7 +83,7 @@ lbatpage_flush_endio(struct bio* bio)
}
}
int
static int
lbatpage_flush(struct lbatpage* lp)
{
int ret = 0;
@ -111,6 +111,15 @@ out:
return ret;
}
void
lbatpage_reset(struct lbatpage* lp, u64 pblk)
{
if (lp->pblk != pblk) {
lp->pblk = pblk;
lp->state = CACHE_STATE_UNCACHED;
}
}
int
lbatpage_read(struct lbatpage* lp)
{
@ -134,15 +143,6 @@ out:
return ret;
}
void
lbatpage_reset(struct lbatpage* lp, u64 pblk)
{
if (lp->pblk != pblk) {
lp->pblk = pblk;
lp->state = CACHE_STATE_UNCACHED;
}
}
u8*
lbatpage_get_buf(struct lbatpage* lp, bool rw)
{
@ -277,14 +277,12 @@ lbatpagecache_get(struct lbatpagecache* lpc, u64 pblk)
}
mutex_unlock(&lp->reflock);
}
printk(KERN_INFO "%s: all pages in use, realloc...\n", __func__);
n = lpc->len;
if (!lbatpagecache_realloc(lpc, lpc->len * 2)) {
printk(KERN_ERR "%s: realloc failed\n", __func__);
lp = NULL;
goto out;
}
printk(KERN_INFO "%s: realloc done, using n=%u\n", __func__, n);
lp = lpc->cache[n];
mutex_lock(&lp->reflock);

View File

@ -43,7 +43,7 @@ struct lbatview {
struct lbatpage* pages[2];
};
bool
static bool
lbatview_ctr(struct lbatview* lv,
struct cbd_params* params,
struct pbatcache* pbatcache,
@ -64,7 +64,7 @@ lbatview_ctr(struct lbatview* lv,
return true;
}
void
static void
lbatview_dtr(struct lbatview* lv)
{
if (pbatcache_put(lv->pbatcache, lv->pbat) != 0) {
@ -77,17 +77,15 @@ lbatview_dtr(struct lbatview* lv)
lv->lpc = NULL;
}
int
static int
lbatview_flush(struct lbatview* lv)
{
int ret = 0;
mutex_lock(&lv->lock);
if (lv->state != CACHE_STATE_DIRTY) {
if (lv->state == CACHE_STATE_ERROR) {
ret = -EIO;
goto out;
}
if (lv->state == CACHE_STATE_ERROR) {
ret = -EIO;
goto out;
}
if (lv->pages[0]) {
ret = lbatpagecache_put(lv->lpc, lv->pages[0]);
@ -118,6 +116,38 @@ out:
return ret;
}
static bool
lbatview_reset(struct lbatview* lv, u64 pblk, u32 count)
{
u32 zone;
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 = zone_for_pblk(lv->params, pblk);
lv->pbat = pbatcache_get(lv->pbatcache, zone);
if (!lv->pbat) {
return false;
}
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 true;
}
int
lbatview_read(struct lbatview* lv)
{
@ -146,43 +176,11 @@ out:
return ret;
}
bool
lbatview_reset(struct lbatview* lv, u64 pblk, u32 count)
{
u32 zone;
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) {
return false;
}
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 true;
}
static u64
lbatview_alloc_pblk(struct lbatview* lv)
{
int ret = 0;
u32 zone = (lv->pblk - CBD_HEADER_BLOCKS) / zone_len(lv->params);
u32 zone = zone_for_pblk(lv->params, lv->pblk);
u64 pblk;
u32 zone_off;
struct pbat* pbat;
@ -262,7 +260,7 @@ static int
lbatview_free_pblk(struct lbatview* lv, u64 pblk)
{
int ret = 0;
u32 zone = (lv->pblk - CBD_HEADER_BLOCKS) / zone_len(lv->params);
u32 zone = zone_for_pblk(lv->params, lv->pblk);
u32 pblk_zone;
struct pbat* pbat;
@ -274,12 +272,8 @@ lbatview_free_pblk(struct lbatview* lv, u64 pblk)
if (ret) {
return ret;
}
if (pblk < CBD_HEADER_BLOCKS) {
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) {
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: zone out of bounds\n", __func__, (unsigned long)pblk);
return -EINVAL;
}
@ -315,7 +309,7 @@ lbatview_free_pblk(struct lbatview* lv, u64 pblk)
static u32
lbatview_elem_off(struct lbatview* lv, u64 lblk)
{
u32 lv_zone = (lv->pblk - CBD_HEADER_BLOCKS) / zone_len(lv->params);
u32 lv_zone = zone_for_pblk(lv->params, lv->pblk);
/* The relative lblk in the zone. */
u32 zone_rel_lblk = lblk - (lv_zone * lv->params->lblk_per_zone);
/* The offset of the element in the (full) lbat. */
@ -664,14 +658,12 @@ lbatviewcache_get(struct lbatviewcache* lvc, u64 lblk)
}
mutex_unlock(&lv->reflock);
}
printk(KERN_INFO "%s: all objects in use, realloc...\n", __func__);
n = lvc->len;
if (!lbatviewcache_realloc(lvc, lvc->len * 2)) {
printk(KERN_ERR "%s: realloc failed\n", __func__);
lv = NULL;
goto out;
}
printk(KERN_INFO "%s: realloc done, using n=%u\n", __func__, n);
lv = lvc->cache[n];
mutex_lock(&lv->reflock);

View File

@ -105,7 +105,7 @@ lblk_compress(struct lbd* lbd)
void *dbuf = lbd->buf;
u32 dlen = PBLK_SIZE * lblk_per_pblk(lbd->params);
void *cbuf = lbd->lz4_cbuf;
u32 clen = PBLK_SIZE * lblk_per_pblk(lbd->params);
u32 clen = PBLK_SIZE * lblk_per_pblk(lbd->params) - 1;
ret = LZ4_compress_default(dbuf, cbuf, dlen, clen, lbd->lz4_wrkmem);
if (ret <= 0) {
@ -137,7 +137,7 @@ lblk_decompress(struct lbd* lbd, u32 clen)
return 0;
}
bool
static bool
lbd_ctr(struct lbd* lbd,
struct cbd_params* params,
struct lbatviewcache* lvc)
@ -169,7 +169,7 @@ lbd_ctr(struct lbd* lbd,
return true;
}
void
static void
lbd_dtr(struct lbd* lbd)
{
if (lbatviewcache_put(lbd->lvc, lbd->lv) != 0) {
@ -200,7 +200,7 @@ lbd_flush_endio(struct bio* bio)
}
}
int
static int
lbd_flush(struct lbd* lbd)
{
int ret = 0;
@ -276,6 +276,22 @@ out:
return ret;
}
static bool
lbd_reset(struct lbd* lbd, u64 lblk)
{
if (lbd->lv) { printk(KERN_ERR "%s: lbatview leak\n", __func__); }
lbd->lv = lbatviewcache_get(lbd->lvc, lblk);
if (!lbd->lv) {
printk(KERN_ERR "%s: lbatviewcache_get failed\n", __func__);
return false;
}
lbd->lblk = lblk;
lbd->state = CACHE_STATE_UNCACHED;
return true;
}
int
lbd_read(struct lbd* lbd)
{
@ -338,22 +354,6 @@ out:
return ret;
}
bool
lbd_reset(struct lbd* lbd, u64 lblk)
{
if (lbd->lv) { printk(KERN_ERR "%s: lbatview leak\n", __func__); }
lbd->lv = lbatviewcache_get(lbd->lvc, lblk);
if (!lbd->lv) {
printk(KERN_ERR "%s: lbatviewcache_get failed\n", __func__);
return false;
}
lbd->lblk = lblk;
lbd->state = CACHE_STATE_UNCACHED;
return true;
}
void
lbd_data_read(struct lbd* lbd, u32 off, u32 len, u8* buf)
{

View File

@ -41,7 +41,7 @@ struct pbat {
u8* buf;
};
bool
static bool
pbat_ctr(struct pbat* pbat,
struct cbd_params* params)
{
@ -62,7 +62,7 @@ pbat_ctr(struct pbat* pbat,
return true;
}
void
static void
pbat_dtr(struct pbat* pbat)
{
pbat->buf = NULL;
@ -87,7 +87,7 @@ pbat_flush_endio(struct bio* bio)
}
}
int
static int
pbat_flush(struct pbat* pbat)
{
int ret = 0;
@ -122,6 +122,15 @@ out:
return ret;
}
static void
pbat_reset(struct pbat* pbat, u32 zone)
{
if (pbat->zone != zone) {
pbat->zone = zone;
pbat->state = CACHE_STATE_UNCACHED;
}
}
int
pbat_read(struct pbat* pbat)
{
@ -150,15 +159,6 @@ out:
return ret;
}
void
pbat_reset(struct pbat* pbat, u32 zone)
{
if (pbat->zone != zone) {
pbat->zone = zone;
pbat->state = CACHE_STATE_UNCACHED;
}
}
u32
pbat_zone(struct pbat* pbat)
{
@ -194,8 +194,7 @@ pbat_free(struct pbat* pbat, u64 pblk)
u32 zone;
u32 idx;
BUG_ON(pblk < CBD_HEADER_BLOCKS);
zone = (pblk - CBD_HEADER_BLOCKS) / zone_len(pbat->params);
zone = zone_for_pblk(pbat->params, pblk);
BUG_ON(zone != pbat->zone);
if (pblk < zone_data_off(pbat->params, zone)) {
printk(KERN_ERR "%s: pblk in metadata\n", __func__);
@ -329,14 +328,12 @@ pbatcache_get(struct pbatcache* pc, u32 zone)
}
mutex_unlock(&pbat->reflock);
}
printk(KERN_INFO "%s: all objects in use, realloc...\n", __func__);
n = pc->len;
if (!pbatcache_realloc(pc, pc->len * 2)) {
printk(KERN_ERR "%s: realloc failed\n", __func__);
pbat = NULL;
goto out;
}
printk(KERN_INFO "%s: realloc done, using n=%u\n", __func__, n);
pbat = pc->cache[n];
mutex_lock(&pbat->reflock);

View File

@ -466,6 +466,17 @@ void cbd_free_pages(struct page* pages, size_t len);
bool cbd_alloc_pagev(struct page** pagev, size_t len);
void cbd_free_pagev(struct page** pagev, size_t len);
/* Core low-level I/O */
int pblk_read_wait(struct cbd_params* params,
u64 pblk, u32 count, struct page** pagev);
int pblk_read(struct cbd_params* params,
u64 pblk, u32 count, struct page** pagev,
pblk_endio_t endio, void* endio_priv);
void pblk_write(struct cbd_params* params,
u64 pblk, u32 count, struct page** pagev,
pblk_endio_t endio, void* endio_priv);
int pblk_endio(struct bio* bio);
/* Debug stuff */
typedef unsigned char byte;
#define MD5_DIGEST_SIZE 16
@ -478,23 +489,10 @@ void md5_init(struct md5* ctx);
void md5_update(struct md5* ctx, const void* data, size_t len);
void md5_final(struct md5* ctx, byte* buf);
int pblk_read_wait(struct cbd_params* params,
u64 pblk, u32 count, struct page** pagev);
int pblk_read(struct cbd_params* params,
u64 pblk, u32 count, struct page** pagev,
pblk_endio_t endio, void* endio_priv);
void pblk_write(struct cbd_params* params,
u64 pblk, u32 count, struct page** pagev,
pblk_endio_t endio, void* endio_priv);
int pblk_endio(struct bio* bio);
struct pbat;
bool pbat_ctr(struct pbat* pbat,
struct cbd_params* params);
void pbat_dtr(struct pbat* pbat);
int pbat_flush(struct pbat* pbat);
int pbat_read(struct pbat* pbat);
void pbat_reset(struct pbat* pbat, u32 zone);
u32 pbat_zone(struct pbat* pbat);
u64 pbat_alloc(struct pbat* pbat);
int pbat_free(struct pbat* pbat, u64 pblk);
@ -510,11 +508,7 @@ int pbatcache_put(struct pbatcache* pbatcache, struct pbat* pbat);
struct lbatpage;
bool lbatpage_ctr(struct lbatpage* lp, struct cbd_params* params);
void lbatpage_dtr(struct lbatpage* lp);
int lbatpage_flush(struct lbatpage* lp);
int lbatpage_read(struct lbatpage* lp);
void lbatpage_reset(struct lbatpage* lp, u64 pblk);
u8* lbatpage_get_buf(struct lbatpage* lp, bool rw);
void lbatpage_put_buf(struct lbatpage* lp);
@ -528,14 +522,7 @@ struct lbatpage*
int lbatpagecache_put(struct lbatpagecache* lpc, struct lbatpage* lpi);
struct lbatview;
bool lbatview_ctr(struct lbatview* lv,
struct cbd_params* params,
struct pbatcache* pbatcache,
struct lbatpagecache* lpc);
void lbatview_dtr(struct lbatview* lv);
int lbatview_flush(struct lbatview* lv);
int lbatview_read(struct lbatview* lv);
bool lbatview_reset(struct lbatview* lv, u64 pblk, u32 count);
int lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len);
u32 lbatview_elem_len(struct lbatview* lv, u64 lblk);
u64 lbatview_elem_pblk(struct lbatview* lv, u64 lblk, u32 idx);
@ -550,13 +537,7 @@ struct lbatview*
int lbatviewcache_put(struct lbatviewcache* lvc, struct lbatview* lbv);
struct lbd;
bool lbd_ctr(struct lbd* lbd,
struct cbd_params* params,
struct lbatviewcache* lvc);
void lbd_dtr(struct lbd* lbd);
int lbd_flush(struct lbd* lbd);
int lbd_read(struct lbd* lbd);
bool lbd_reset(struct lbd* lbd, u64 lblk);
void lbd_data_read(struct lbd* lbd, u32 off, u32 len, u8* buf);
void lbd_data_write(struct lbd* lbd, u32 off, u32 len, const u8* buf);

View File

@ -80,8 +80,11 @@ check_one_lblk(const struct cbd_params* params,
printf(" lblk[%u]: len=%u\n", lblk, lba->len);
}
}
else {
printf(" lblk[%u]: EMPTY\n", lblk);
}
if (lba->len > PBLK_SIZE * lblk_per_pblk(params)) {
printf(" Length out of bounds\n");
printf(" :E: Length out of bounds\n");
return;
}
c_len = (lba->len == CBD_UNCOMPRESSED) ? PBLK_SIZE * lblk_per_pblk(params) : lba->len;