Start implementing stats

Just pblks allocated for now.

Also update device layout info in README.
This commit is contained in:
Tom Marshall 2019-11-04 12:25:54 -08:00
parent 94551dffdd
commit d7fb50911b
8 changed files with 68 additions and 39 deletions

41
README
View File

@ -8,23 +8,28 @@ Note:
Block device layout:
- byte[4096] header
/* Offset 0 */
- byte[4] magic
- u16 version_major
- u16 version_minor
- u64 nr_physical_sectors
- u64 nr_logical_sectors [3 * physical_sectors]
- u16 physical_blocks_per_logical_block_shift (0 .. 18) [4 = 64kb]
(logical blocks may not exceed 1gb due to LZ4)
- u16 flags
- u8 algorithm (1=lz4, 2=zlib, ...) [1]
- u8 compression (1..9) [1]
- u16 pbat_len [1]
- u16 lblk_shift (1..18) [4 = 64kb]
- u64 nr_pblk
- u32 nr_zones
- u32 lblk_per_zone
- byte[32] reserved
/* Offset 64 */
- u64 pblk_alloc
- byte[] reserved
- byte[] zone ... vector of zone
Number of logical blocks per zone:
nr_lblk = 1 << header.logical_blocks_per_group_shift
Device size limits:
- Min: header plus one zone (header, phys_alloc, log_alloc, data)
- Min: header plus one zone (header, pbat, lbat, data)
Arbitrarily limit to 1mb (?)
- 2^48 = 256t physical blocks = 1eb
- Max: 2^48 pblk = 1eb
There are six different lblk_alloc sizes:
Struct name Size lblk_size device_pblk_size
@ -38,16 +43,8 @@ There are six different lblk_alloc sizes:
Zone layout:
- byte[4k] Physical block alloc bitmap
- lblk_alloc_x_y[] Logical block allocation
- data[4k*4k*8] Data
Data size (physical): 4kb*(4k*8) = 128mb
Data size (logical) : 128mb*3 = 384mb
Assume <=4g physical blocks, 64kb logical blocks, 3x compression:
- Zone holds 3*128mb = 384mb logical data
- 384mb/64kb = 6k logical blocks
- 6k * (34b) = 204kb logical block alloc data
- 204kb / 4kb = 51 physical blocks for logical block alloc data
- Overhead: (1+51)/32k = 0.016%
- byte[4k*pbat_len] Physical block allocation table (pbat)
- lblk_alloc_x_y[] Logical block allocation table (lbat)
Note: padded to pblk size
- data[4k*pbat_len*4k*8] Data
One pblk per bit in pbat

View File

@ -249,13 +249,16 @@ static int
do_stats(int argc, char** argv)
{
const char* name;
struct cbd_stats stats;
if (argc != 2) {
usage();
}
name = argv[1];
cbd_stats(name);
cbd_stats(name, &stats);
printf("Stats:\n");
printf("pblk alloc: %lu\n", (unsigned long)stats.pblk_alloc);
return 0;
}

View File

@ -53,6 +53,7 @@ struct compress
struct dm_dev* dev;
struct cbd_params params;
struct cbd_stats stats;
struct lbdcache* lc;
struct workqueue_struct* io_workq;
@ -156,6 +157,7 @@ compress_read_header(struct compress* c)
printk(KERN_INFO " lblk_per_zone=%u\n", (unsigned int)header.params.lblk_per_zone);
memcpy(&c->params, &header.params, sizeof(header.params));
memcpy(&c->stats, &header.stats, sizeof(header.stats));
out:
cbd_free_page(pblkpage);
@ -181,6 +183,7 @@ compress_write_header(struct compress* c)
header.version_major = CBD_VERSION_MAJOR;
header.version_minor = CBD_VERSION_MINOR;
memcpy(&header.params, &c->params, sizeof(header.params));
memcpy(&header.stats, &c->stats, sizeof(header.stats));
cbd_header_put(pblkbuf, &header);
iopagev[0] = pblkpage;
ret = pblk_write_wait(c->params.priv, 0, 1, iopagev);
@ -201,12 +204,12 @@ compress_lbdcache_swap(struct compress* c, u64 lblk, struct lbd* oldlbd)
lbd = lbdcache_get(c->lc, lblk);
if (!lbd) {
printk(KERN_ERR "%s: lbdcache_get failed\n", __func__);
lbdcache_put(c->lc, oldlbd);
lbdcache_put(c->lc, oldlbd, &c->stats);
return NULL;
}
if (lbdcache_put(c->lc, oldlbd) != 0) {
if (lbdcache_put(c->lc, oldlbd, &c->stats) != 0) {
printk(KERN_ERR "%s: failed to put oldlbd\n", __func__);
lbdcache_put(c->lc, lbd);
lbdcache_put(c->lc, lbd, &c->stats);
return NULL;
}
@ -241,7 +244,7 @@ compress_read(struct compress *c, struct bio *bio)
lbd_data_read(lbd, lblk_off, bv.bv_len, data);
bvec_kunmap_irq(data, &flags);
}
ret = lbdcache_put(c->lc, lbd);
ret = lbdcache_put(c->lc, lbd, &c->stats);
return ret;
}
@ -274,7 +277,7 @@ compress_write(struct compress *c, struct bio *bio)
lbd_data_write(lbd, lblk_off, bv.bv_len, data);
bvec_kunmap_irq(data, &flags);
}
ret = lbdcache_put(c->lc, lbd);
ret = lbdcache_put(c->lc, lbd, &c->stats);
return ret;
}

View File

@ -312,7 +312,7 @@ lbatview_wmem(struct lbatview* lv, u32 off, u32 len, void* buf)
}
int
lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len)
lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len, struct cbd_stats* stats)
{
int ret = 0;
int err;
@ -371,6 +371,7 @@ do_free:
if (!ret) {
elem_lelen = __cpu_to_le32(len);
lbatview_wmem(lv, elem_off, lba_elem_len_bytes(lv->params), &elem_lelen);
stats->pblk_alloc += req_nalloc - old_nalloc;
}
mutex_unlock(&lv->lock);

View File

@ -304,7 +304,7 @@ lbd_error(struct lbd* lbd)
}
static int
lbd_flush(struct lbd* lbd)
lbd_flush(struct lbd* lbd, struct cbd_stats* stats)
{
int ret = 0;
int err;
@ -325,7 +325,7 @@ lbd_flush(struct lbd* lbd)
if (lblk_is_zeros(lbd->params, lbd)) {
lbd->c_len = CBD_UNCOMPRESSED;
ret = lbatview_elem_realloc(lbd->lv, lbd->lblk, 0);
ret = lbatview_elem_realloc(lbd->lv, lbd->lblk, 0, stats);
goto unlock;
}
lbd->c_len = lblk_compress(lbd);
@ -340,7 +340,7 @@ lbd_flush(struct lbd* lbd)
lbd->c_len = CBD_UNCOMPRESSED;
count = lblk_per_pblk(lbd->params);
}
ret = lbatview_elem_realloc(lbd->lv, lbd->lblk, lbd->c_len);
ret = lbatview_elem_realloc(lbd->lv, lbd->lblk, lbd->c_len, stats);
if (ret) {
goto unlock;
}
@ -733,7 +733,7 @@ found:
}
int
lbdcache_put(struct lbdcache* lc, struct lbd* lbd)
lbdcache_put(struct lbdcache* lc, struct lbd* lbd, struct cbd_stats* stats)
{
int ret = 0;
@ -742,7 +742,7 @@ lbdcache_put(struct lbdcache* lc, struct lbd* lbd)
}
mutex_lock(&lbd->reflock);
if (--lbd->ref == 0) {
ret = lbd_flush(lbd);
ret = lbd_flush(lbd, stats);
if (ret) {
printk(KERN_ERR "%s: lbd_flush failed\n", __func__);
}

View File

@ -58,7 +58,7 @@ int cbd_open(const char* dev,
const char* name);
int cbd_close(const char* name);
int cbd_stats(const char* name);
int cbd_stats(const char* dev, struct cbd_stats* stats);
int cbd_check(const char* dev,
bool force,

View File

@ -50,11 +50,16 @@ struct cbd_params {
void* priv;
};
struct cbd_stats {
u64 pblk_alloc;
};
struct cbd_header {
u8 magic[4];
u16 version_major;
u16 version_minor;
struct cbd_params params;
struct cbd_stats stats;
};
struct lba
@ -306,6 +311,8 @@ cbd_header_get(const u8* buf, struct cbd_header* header)
header->params.nr_pblk = get64_le(&buf);
header->params.nr_zones = get32_le(&buf);
header->params.lblk_per_zone = get32_le(&buf);
buf += 32; /* Reserved */
header->stats.pblk_alloc = get64_le(&buf);
}
static inline void
@ -322,6 +329,8 @@ cbd_header_put(u8* buf, const struct cbd_header* header)
put64_le(&buf, header->params.nr_pblk);
put32_le(&buf, header->params.nr_zones);
put32_le(&buf, header->params.lblk_per_zone);
buf += 32; /* Reserved */
put64_le(&buf, header->stats.pblk_alloc);
}
static inline u32
@ -510,7 +519,7 @@ struct lbatpage*
int lbatpagecache_put(struct lbatpagecache* lpc, struct lbatpage* lpi);
struct lbatview;
int lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len);
int lbatview_elem_realloc(struct lbatview* lv, u64 lblk, u32 len, struct cbd_stats* stats);
u32 lbatview_elem_len(struct lbatview* lv, u64 lblk);
u64 lbatview_elem_pblk(struct lbatview* lv, u64 lblk, u32 idx);
@ -534,7 +543,7 @@ bool lbdcache_ctr(struct lbdcache* lc,
void lbdcache_dtr(struct lbdcache* lc);
struct lbd*
lbdcache_get(struct lbdcache* lc, u64 lblk);
int lbdcache_put(struct lbdcache* lc, struct lbd* lbd);
int lbdcache_put(struct lbdcache* lc, struct lbd* lbd, struct cbd_stats* stats);
#endif

View File

@ -3,9 +3,25 @@
#include <cbdutil.h>
int
cbd_stats(const char* name)
cbd_stats(const char* dev, struct cbd_stats* stats)
{
error("Not implemented\n");
int fd;
uint8_t pblkbuf[PBLK_SIZE];
struct cbd_header header;
fd = open(dev, O_RDONLY);
if (fd < 0) {
error("Cannot open device\n");
}
if (read(fd, pblkbuf, sizeof(pblkbuf)) != sizeof(pblkbuf)) {
error("Cannot read device\n");
}
close(fd);
cbd_header_get(pblkbuf, &header);
if (memcmp(header.magic, CBD_MAGIC, sizeof(header.magic)) != 0) {
error("Bad magic\n");
}
memcpy(stats, &header.stats, sizeof(struct cbd_stats));
return 0;
}