DEBUG: pbat read verification
This commit is contained in:
parent
e1ec3567df
commit
290b1873a0
|
@ -29,6 +29,13 @@
|
|||
|
||||
#include <linux/dm-compress.h>
|
||||
|
||||
#define CPU_NONE (~0)
|
||||
|
||||
struct iostate {
|
||||
int cpu;
|
||||
byte hash[MD5_DIGEST_SIZE];
|
||||
};
|
||||
|
||||
struct pbat {
|
||||
u32 zone;
|
||||
struct mutex reflock;
|
||||
|
@ -39,8 +46,50 @@ struct pbat {
|
|||
struct cbd_params* params;
|
||||
struct page* pages;
|
||||
u8* buf;
|
||||
|
||||
struct iostate lrs; /* last read state */
|
||||
struct iostate lws; /* last written state */
|
||||
};
|
||||
|
||||
static void
|
||||
pbat_save_state(struct pbat* pbat)
|
||||
{
|
||||
struct md5 ctx;
|
||||
|
||||
md5_init(&ctx);
|
||||
md5_update(&ctx, pbat->buf, PBLK_SIZE);
|
||||
md5_final(&ctx, pbat->lws.hash);
|
||||
pbat->lws.cpu = smp_processor_id();
|
||||
}
|
||||
|
||||
static bool
|
||||
pbat_check_state(struct pbat* pbat)
|
||||
{
|
||||
struct md5 ctx;
|
||||
byte hash[MD5_DIGEST_SIZE];
|
||||
|
||||
if (pbat->lws.cpu == CPU_NONE) {
|
||||
pbat_save_state(pbat);
|
||||
memcpy(&pbat->lrs, &pbat->lws, sizeof(struct iostate));
|
||||
return true;
|
||||
}
|
||||
|
||||
md5_init(&ctx);
|
||||
md5_update(&ctx, pbat->buf, PBLK_SIZE);
|
||||
md5_final(&ctx, hash);
|
||||
if (!memcmp(hash, pbat->lws.hash, MD5_DIGEST_SIZE)) {
|
||||
return true;
|
||||
}
|
||||
if (!memcmp(hash, pbat->lrs.hash, MD5_DIGEST_SIZE)) {
|
||||
printk(KERN_ERR "%s: read stale data: wcpu=%d curcpu=%d\n", __func__,
|
||||
pbat->lws.cpu, smp_processor_id());
|
||||
return false;
|
||||
}
|
||||
printk(KERN_ERR "%s: read bogus data: wcpu=%d curcpu=%d\n", __func__,
|
||||
pbat->lws.cpu, smp_processor_id());
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
pbat_ctr(struct pbat* pbat,
|
||||
struct cbd_params* params)
|
||||
|
@ -58,6 +107,8 @@ pbat_ctr(struct pbat* pbat,
|
|||
return false;
|
||||
}
|
||||
pbat->buf = page_address(pbat->pages);
|
||||
pbat->lrs.cpu = CPU_NONE;
|
||||
pbat->lws.cpu = CPU_NONE;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -114,6 +165,7 @@ pbat_flush(struct pbat* pbat)
|
|||
iobuf = page_address(iopagev[n]);
|
||||
memcpy(iobuf, pbat->buf + n * PBLK_SIZE, PBLK_SIZE);
|
||||
}
|
||||
pbat_save_state(pbat);
|
||||
pblk_write(pbat->params, pblk, count, iopagev, pbat_flush_endio, pbat);
|
||||
pbat->state = CACHE_STATE_CLEAN;
|
||||
|
||||
|
@ -139,6 +191,7 @@ pbat_read(struct pbat* pbat)
|
|||
struct page* pagev[count];
|
||||
u64 pblk;
|
||||
u32 n;
|
||||
bool retried = false;
|
||||
|
||||
mutex_lock(&pbat->lock);
|
||||
if (pbat->state != CACHE_STATE_UNCACHED) {
|
||||
|
@ -148,10 +201,20 @@ pbat_read(struct pbat* pbat)
|
|||
for (n = 0; n < count; ++n) {
|
||||
pagev[n] = virt_to_page(pbat->buf + n * PBLK_SIZE);
|
||||
}
|
||||
again:
|
||||
ret = pblk_read_wait(pbat->params, pblk, count, pagev);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
if (!pbat_check_state(pbat)) {
|
||||
printk(KERN_ERR "%s: check state failed, retrying\n", __func__);
|
||||
yield();
|
||||
retried = true;
|
||||
goto again;
|
||||
}
|
||||
if (retried) {
|
||||
printk(KERN_ERR "%s: read good data after retry\n", __func__);
|
||||
}
|
||||
pbat->state = CACHE_STATE_CLEAN;
|
||||
|
||||
out:
|
||||
|
@ -216,6 +279,8 @@ struct pbatcache {
|
|||
struct cbd_params* params;
|
||||
unsigned int len;
|
||||
struct pbat** cache;
|
||||
struct iostate* lrsv;
|
||||
struct iostate* lwsv;
|
||||
};
|
||||
|
||||
size_t
|
||||
|
@ -261,9 +326,17 @@ bool
|
|||
pbatcache_ctr(struct pbatcache* pc,
|
||||
struct cbd_params* params)
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
memset(pc, 0, sizeof(struct pbatcache));
|
||||
mutex_init(&pc->lock);
|
||||
pc->params = params;
|
||||
pc->lrsv = kzalloc(params->nr_zones * sizeof(struct iostate), GFP_KERNEL);
|
||||
pc->lwsv = kzalloc(params->nr_zones * sizeof(struct iostate), GFP_KERNEL);
|
||||
for (idx = 0; idx < params->nr_zones; ++idx) {
|
||||
pc->lrsv[idx].cpu = CPU_NONE;
|
||||
pc->lwsv[idx].cpu = CPU_NONE;
|
||||
}
|
||||
|
||||
return pbatcache_realloc(pc, 1);
|
||||
}
|
||||
|
@ -274,6 +347,8 @@ pbatcache_dtr(struct pbatcache* pc)
|
|||
unsigned int n;
|
||||
struct pbat* pbat;
|
||||
|
||||
kfree(pc->lwsv);
|
||||
kfree(pc->lrsv);
|
||||
for (n = 0; n < pc->len; ++n) {
|
||||
pbat = pc->cache[n];
|
||||
if (!pbat) {
|
||||
|
@ -340,6 +415,8 @@ pbatcache_get(struct pbatcache* pc, u32 zone)
|
|||
found:
|
||||
pbat_reset(pbat, zone);
|
||||
pbat->ref = 1;
|
||||
memcpy(&pbat->lrs, &pc->lrsv[zone], sizeof(struct iostate));
|
||||
memcpy(&pbat->lws, &pc->lwsv[zone], sizeof(struct iostate));
|
||||
mutex_unlock(&pbat->reflock);
|
||||
|
||||
out:
|
||||
|
@ -363,6 +440,8 @@ pbatcache_put(struct pbatcache* pc, struct pbat* pbat)
|
|||
if (ret) {
|
||||
printk(KERN_ERR "%s: pbat_flush failed\n", __func__);
|
||||
}
|
||||
memcpy(&pc->lrsv[pbat->zone], &pbat->lrs, sizeof(struct iostate));
|
||||
memcpy(&pc->lwsv[pbat->zone], &pbat->lws, sizeof(struct iostate));
|
||||
}
|
||||
mutex_unlock(&pbat->reflock);
|
||||
mutex_unlock(&pc->lock);
|
||||
|
|
Loading…
Reference in New Issue