Add stats
In /sys/fs/compress/device-name: lblk_size, pblk_used/total, lblk_used/total, pbat_r/w, lbatpblk_r/w, lbd_r/w
This commit is contained in:
parent
c4aabad212
commit
e70d283921
|
@ -52,6 +52,9 @@ struct compress
|
|||
{
|
||||
struct dm_dev* dev;
|
||||
|
||||
struct kobject kobj;
|
||||
struct completion kobj_unregister;
|
||||
|
||||
struct compress_params kparams;
|
||||
struct compress_stats kstats;
|
||||
struct lbdcache* lc;
|
||||
|
@ -59,6 +62,8 @@ struct compress
|
|||
struct workqueue_struct* io_workq;
|
||||
};
|
||||
|
||||
static struct kobject* compress_kobj;
|
||||
|
||||
static inline u64
|
||||
blkdev_pblk_size(struct block_device *bdev)
|
||||
{
|
||||
|
@ -91,7 +96,6 @@ compress_read_header(struct compress* c)
|
|||
pblkbuf = page_address(pblkpage);
|
||||
iopagev[0] = pblkpage;
|
||||
|
||||
c->kparams.dev = c->dev->bdev;
|
||||
ret = pblk_read_wait(&c->kparams, 0, 1, iopagev);
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s: failed to read header\n", __func__);
|
||||
|
@ -155,6 +159,9 @@ compress_read_header(struct compress* c)
|
|||
printk(KERN_INFO " nr_pblk=%lu\n", (unsigned long)header.params.nr_pblk);
|
||||
printk(KERN_INFO " nr_zones=%u\n", (unsigned int)header.params.nr_zones);
|
||||
printk(KERN_INFO " lblk_per_zone=%u\n", (unsigned int)header.params.lblk_per_zone);
|
||||
printk(KERN_INFO "%s: stats...\n", __func__);
|
||||
printk(KERN_INFO " pblk_used=%lu\n", (unsigned long)header.stats.pblk_alloc);
|
||||
printk(KERN_INFO " lblk_used=%lu\n", (unsigned long)header.stats.lblk_alloc);
|
||||
|
||||
memcpy(&c->kparams.params, &header.params, sizeof(header.params));
|
||||
memcpy(&c->kstats.stats, &header.stats, sizeof(header.stats));
|
||||
|
@ -285,6 +292,158 @@ compress_io_work(struct work_struct* work)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*** sysfs stuff ***/
|
||||
|
||||
typedef enum {
|
||||
attr_lblk_size,
|
||||
attr_pblk_used,
|
||||
attr_pblk_total,
|
||||
attr_lblk_used,
|
||||
attr_lblk_total,
|
||||
attr_pbat_r,
|
||||
attr_pbat_w,
|
||||
attr_lbatpblk_r,
|
||||
attr_lbatpblk_w,
|
||||
attr_lbd_r,
|
||||
attr_lbd_w,
|
||||
} attr_id_t;
|
||||
|
||||
struct compress_attr {
|
||||
struct attribute attr;
|
||||
short attr_id;
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
compress_attr_show(struct kobject* kobj, struct attribute* attr,
|
||||
char* buf)
|
||||
{
|
||||
struct compress* c = container_of(kobj, struct compress, kobj);
|
||||
struct compress_attr* a = container_of(attr, struct compress_attr, attr);
|
||||
u64 val = 0;
|
||||
|
||||
mutex_lock(&c->kstats.lock);
|
||||
switch (a->attr_id) {
|
||||
case attr_lblk_size:
|
||||
val = PBLK_SIZE * lblk_per_pblk(&c->kparams.params);
|
||||
break;
|
||||
case attr_pblk_used:
|
||||
val = c->kstats.stats.pblk_alloc;
|
||||
break;
|
||||
case attr_pblk_total:
|
||||
val = pbat_len(&c->kparams.params) * PBLK_SIZE_BITS *
|
||||
c->kparams.params.nr_zones;
|
||||
break;
|
||||
case attr_lblk_used:
|
||||
val = c->kstats.stats.lblk_alloc;
|
||||
break;
|
||||
case attr_lblk_total:
|
||||
val = c->kparams.params.lblk_per_zone *
|
||||
c->kparams.params.nr_zones;
|
||||
break;
|
||||
case attr_pbat_r:
|
||||
val = c->kstats.pbat_r;
|
||||
break;
|
||||
case attr_pbat_w:
|
||||
val = c->kstats.pbat_w;
|
||||
break;
|
||||
case attr_lbatpblk_r:
|
||||
val = c->kstats.lbatpblk_r;
|
||||
break;
|
||||
case attr_lbatpblk_w:
|
||||
val = c->kstats.lbatpblk_w;
|
||||
break;
|
||||
case attr_lbd_r:
|
||||
val = c->kstats.lbd_r;
|
||||
break;
|
||||
case attr_lbd_w:
|
||||
val = c->kstats.lbd_w;
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&c->kstats.lock);
|
||||
return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)val);
|
||||
}
|
||||
|
||||
#define COMPRESS_ATTR(_name,_mode,_id) \
|
||||
static struct compress_attr compress_attr_##_name = { \
|
||||
.attr = { .name = __stringify(_name), .mode = _mode }, \
|
||||
.attr_id = attr_##_id, \
|
||||
}
|
||||
|
||||
#define COMPRESS_ATTR_FUNC(_name,_mode) COMPRESS_ATTR(_name, _mode, _name)
|
||||
|
||||
COMPRESS_ATTR_FUNC(lblk_size, 0444);
|
||||
COMPRESS_ATTR_FUNC(pblk_used, 0444);
|
||||
COMPRESS_ATTR_FUNC(pblk_total, 0444);
|
||||
COMPRESS_ATTR_FUNC(lblk_used, 0444);
|
||||
COMPRESS_ATTR_FUNC(lblk_total, 0444);
|
||||
COMPRESS_ATTR_FUNC(pbat_r, 0444);
|
||||
COMPRESS_ATTR_FUNC(pbat_w, 0444);
|
||||
COMPRESS_ATTR_FUNC(lbatpblk_r, 0444);
|
||||
COMPRESS_ATTR_FUNC(lbatpblk_w, 0444);
|
||||
COMPRESS_ATTR_FUNC(lbd_r, 0444);
|
||||
COMPRESS_ATTR_FUNC(lbd_w, 0444);
|
||||
|
||||
#define ATTR_LIST(name) &compress_attr_##name.attr
|
||||
|
||||
static struct attribute* compress_attrs[] = {
|
||||
ATTR_LIST(lblk_size),
|
||||
ATTR_LIST(pblk_used),
|
||||
ATTR_LIST(pblk_total),
|
||||
ATTR_LIST(lblk_used),
|
||||
ATTR_LIST(lblk_total),
|
||||
ATTR_LIST(pbat_r),
|
||||
ATTR_LIST(pbat_w),
|
||||
ATTR_LIST(lbatpblk_r),
|
||||
ATTR_LIST(lbatpblk_w),
|
||||
ATTR_LIST(lbd_r),
|
||||
ATTR_LIST(lbd_w),
|
||||
NULL
|
||||
};
|
||||
|
||||
#undef ATTR_LIST
|
||||
|
||||
static void
|
||||
compress_sysfs_release(struct kobject* kobj)
|
||||
{
|
||||
struct compress* c = container_of(kobj, struct compress, kobj);
|
||||
|
||||
complete(&c->kobj_unregister);
|
||||
}
|
||||
|
||||
static const struct sysfs_ops compress_attr_ops = {
|
||||
.show = compress_attr_show,
|
||||
};
|
||||
|
||||
static struct kobj_type compress_ktype = {
|
||||
.default_attrs = compress_attrs,
|
||||
.sysfs_ops = &compress_attr_ops,
|
||||
.release = compress_sysfs_release,
|
||||
};
|
||||
|
||||
static int
|
||||
compress_register_sysfs(struct compress* c)
|
||||
{
|
||||
int err;
|
||||
char name[32];
|
||||
|
||||
snprintf(name, sizeof(name), "%pg", c->dev->bdev);
|
||||
|
||||
init_completion(&c->kobj_unregister);
|
||||
err = kobject_init_and_add(&c->kobj, &compress_ktype, compress_kobj, "%s", name);
|
||||
if (err) {
|
||||
kobject_put(&c->kobj);
|
||||
wait_for_completion(&c->kobj_unregister);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static void
|
||||
compress_unregister_sysfs(struct compress* c)
|
||||
{
|
||||
kobject_del(&c->kobj);
|
||||
}
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
* echo "<start_sector> <end_sector> compress <backing_device> <args...>" | dmsetup create <compress_name>
|
||||
|
@ -363,13 +522,20 @@ compress_ctr(struct dm_target *ti, unsigned int argc, char **argv)
|
|||
ti->private = c;
|
||||
|
||||
backing_nr_pblks = blkdev_pblk_size(c->dev->bdev);
|
||||
|
||||
if ((backing_nr_pblks >> 48) != 0) {
|
||||
ti->error = "Device too large";
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = compress_register_sysfs(c);
|
||||
if (ret) {
|
||||
ti->error = "Failed to register sysfs";
|
||||
goto err;
|
||||
}
|
||||
c->kparams.dev = c->dev->bdev;
|
||||
mutex_init(&c->kstats.lock);
|
||||
|
||||
if (!cache_pages) {
|
||||
/* Minimum of 1/1k RAM and 1/64k device size */
|
||||
cache_pages = min((unsigned int)(totalram_pages >> 10),
|
||||
|
@ -465,6 +631,7 @@ compress_dtr(struct dm_target *ti)
|
|||
if (c->io_workq) {
|
||||
destroy_workqueue(c->io_workq);
|
||||
}
|
||||
compress_unregister_sysfs(c);
|
||||
dm_put_device(ti, c->dev);
|
||||
kfree(c);
|
||||
}
|
||||
|
@ -518,6 +685,13 @@ static int __init
|
|||
dm_compress_init(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
compress_kobj = kobject_create_and_add("compress", fs_kobj);
|
||||
if (!compress_kobj) {
|
||||
printk(KERN_ERR "Failed to add sysfs kobj\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = dm_register_target(&compress_target);
|
||||
if (res < 0) {
|
||||
printk(KERN_ERR "Failed to register dm-compress: %d\n", res);
|
||||
|
@ -530,6 +704,11 @@ static void __exit
|
|||
dm_compress_exit(void)
|
||||
{
|
||||
dm_unregister_target(&compress_target);
|
||||
|
||||
if (compress_kobj) {
|
||||
kobject_put(compress_kobj);
|
||||
compress_kobj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
module_init(dm_compress_init);
|
||||
|
|
|
@ -37,13 +37,16 @@ struct lbatpblk {
|
|||
|
||||
struct mutex lock;
|
||||
struct compress_params* kparams;
|
||||
struct compress_stats* kstats;
|
||||
struct page* page;
|
||||
u8* buf;
|
||||
bool dirty;
|
||||
};
|
||||
|
||||
static bool
|
||||
lbatpblk_ctr(struct lbatpblk* lp, struct compress_params* kparams)
|
||||
lbatpblk_ctr(struct lbatpblk* lp,
|
||||
struct compress_params* kparams,
|
||||
struct compress_stats* kstats)
|
||||
{
|
||||
memset(lp, 0, sizeof(struct lbatpblk));
|
||||
INIT_LIST_HEAD(&lp->list);
|
||||
|
@ -52,6 +55,7 @@ lbatpblk_ctr(struct lbatpblk* lp, struct compress_params* kparams)
|
|||
lp->ref = 0;
|
||||
mutex_init(&lp->lock);
|
||||
lp->kparams = kparams;
|
||||
lp->kstats = kstats;
|
||||
lp->page = cbd_alloc_page();
|
||||
if (!lp->page) {
|
||||
return false;
|
||||
|
@ -93,6 +97,9 @@ lbatpblk_flush(struct lbatpblk* lp)
|
|||
iopagev[0] = lp->page;
|
||||
pblk_write(lp->kparams, lp->pblk, 1, iopagev);
|
||||
mutex_unlock(&lp->lock);
|
||||
mutex_lock(&lp->kstats->lock);
|
||||
++lp->kstats->lbatpblk_w;
|
||||
mutex_unlock(&lp->kstats->lock);
|
||||
|
||||
return ret;
|
||||
|
||||
|
@ -111,6 +118,9 @@ lbatpblk_read(struct lbatpblk* lp)
|
|||
|
||||
pagev[0] = lp->page;
|
||||
ret = pblk_read_wait(lp->kparams, lp->pblk, 1, pagev);
|
||||
mutex_lock(&lp->kstats->lock);
|
||||
++lp->kstats->lbatpblk_r;
|
||||
mutex_unlock(&lp->kstats->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -166,7 +176,8 @@ lbatpblkcache_size(void)
|
|||
|
||||
bool
|
||||
lbatpblkcache_ctr(struct lbatpblkcache* lpc,
|
||||
struct compress_params* kparams, u32 cache_pages)
|
||||
struct compress_params* kparams, struct compress_stats* kstats,
|
||||
u32 cache_pages)
|
||||
{
|
||||
struct lbatpblk* cache;
|
||||
u32 cache_len;
|
||||
|
@ -190,7 +201,7 @@ lbatpblkcache_ctr(struct lbatpblkcache* lpc,
|
|||
lpc->cache_len = cache_len;
|
||||
lpc->cache = cache;
|
||||
for (n = 0; n < cache_len; ++n) {
|
||||
if (!lbatpblk_ctr(&cache[n], kparams)) {
|
||||
if (!lbatpblk_ctr(&cache[n], kparams, kstats)) {
|
||||
return false;
|
||||
}
|
||||
list_add_tail(&cache[n].list, &lpc->cache_head);
|
||||
|
|
|
@ -464,7 +464,7 @@ lbatviewcache_size(void)
|
|||
|
||||
bool
|
||||
lbatviewcache_ctr(struct lbatviewcache* lvc,
|
||||
struct compress_params* kparams, struct compress_stats* stats,
|
||||
struct compress_params* kparams, struct compress_stats* kstats,
|
||||
u32 cache_pages)
|
||||
{
|
||||
struct lbatview* cache;
|
||||
|
@ -477,14 +477,14 @@ lbatviewcache_ctr(struct lbatviewcache* lvc,
|
|||
if (!lvc->pc) {
|
||||
return false;
|
||||
}
|
||||
if (!pbatcache_ctr(lvc->pc, kparams, cache_pages)) {
|
||||
if (!pbatcache_ctr(lvc->pc, kparams, kstats, cache_pages)) {
|
||||
return false;
|
||||
}
|
||||
lvc->lpc = kmalloc(lbatpblkcache_size(), GFP_KERNEL);
|
||||
if (!lvc->lpc) {
|
||||
return false;
|
||||
}
|
||||
if (!lbatpblkcache_ctr(lvc->lpc, kparams, cache_pages)) {
|
||||
if (!lbatpblkcache_ctr(lvc->lpc, kparams, kstats, cache_pages)) {
|
||||
return false;
|
||||
}
|
||||
/* lbatviewcache gets one entry per lbatpblk (XXX: 5/6?) */
|
||||
|
@ -503,7 +503,7 @@ lbatviewcache_ctr(struct lbatviewcache* lvc,
|
|||
lvc->cache_len = cache_len;
|
||||
lvc->cache = cache;
|
||||
for (n = 0; n < cache_len; ++n) {
|
||||
if (!lbatview_ctr(&cache[n], kparams, stats, lvc->pc, lvc->lpc)) {
|
||||
if (!lbatview_ctr(&cache[n], kparams, kstats, lvc->pc, lvc->lpc)) {
|
||||
return false;
|
||||
}
|
||||
list_add_tail(&cache[n].list, &lvc->cache_head);
|
||||
|
|
|
@ -40,6 +40,7 @@ struct lbd {
|
|||
|
||||
struct mutex lock;
|
||||
struct compress_params* kparams;
|
||||
struct compress_stats* kstats;
|
||||
struct lbatviewcache* lvc;
|
||||
struct lbatview* lv;
|
||||
void* percpu;
|
||||
|
@ -251,6 +252,7 @@ lblk_decompress(struct lbd* lbd)
|
|||
static bool
|
||||
lbd_ctr(struct lbd* lbd,
|
||||
struct compress_params* kparams,
|
||||
struct compress_stats* kstats,
|
||||
struct lbatviewcache* lvc,
|
||||
void* percpu)
|
||||
{
|
||||
|
@ -265,6 +267,7 @@ lbd_ctr(struct lbd* lbd,
|
|||
lbd->ref = 0;
|
||||
mutex_init(&lbd->lock);
|
||||
lbd->kparams = kparams;
|
||||
lbd->kstats = kstats;
|
||||
lbd->lvc = lvc;
|
||||
lbd->lv = NULL;
|
||||
lbd->percpu = percpu;
|
||||
|
@ -357,6 +360,9 @@ lbd_flush(struct lbd* lbd)
|
|||
iopagev[0] = lbd->pagev[n];
|
||||
pblk_write(lbd->kparams, pblk, 1, iopagev);
|
||||
}
|
||||
mutex_lock(&lbd->kstats->lock);
|
||||
++lbd->kstats->lbd_w;
|
||||
mutex_unlock(&lbd->kstats->lock);
|
||||
while (n < lblk_per_pblk(&lbd->kparams->params)) {
|
||||
unlock_page(lbd->pagev[n]);
|
||||
++n;
|
||||
|
@ -422,6 +428,9 @@ lbd_read(struct lbd* lbd)
|
|||
}
|
||||
}
|
||||
lbd->c_len = CBD_UNCOMPRESSED;
|
||||
mutex_lock(&lbd->kstats->lock);
|
||||
++lbd->kstats->lbd_r;
|
||||
mutex_unlock(&lbd->kstats->lock);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
@ -644,7 +653,7 @@ lbdcache_ctr(struct lbdcache* lc,
|
|||
lc->cache_len = cache_len;
|
||||
lc->cache = cache;
|
||||
for (n = 0; n < cache_len; ++n) {
|
||||
if (!lbd_ctr(&cache[n], kparams, lc->lvc, lc->percpu)) {
|
||||
if (!lbd_ctr(&cache[n], kparams, kstats, lc->lvc, lc->percpu)) {
|
||||
return false;
|
||||
}
|
||||
list_add_tail(&cache[n].lru_list, &lc->cache_head);
|
||||
|
|
|
@ -37,6 +37,7 @@ struct pbat {
|
|||
|
||||
struct mutex lock;
|
||||
struct compress_params* kparams;
|
||||
struct compress_stats* kstats;
|
||||
bool full;
|
||||
u32 last_alloc;
|
||||
struct page** pagev;
|
||||
|
@ -45,7 +46,8 @@ struct pbat {
|
|||
|
||||
static bool
|
||||
pbat_ctr(struct pbat* pbat,
|
||||
struct compress_params* kparams)
|
||||
struct compress_params* kparams,
|
||||
struct compress_stats* kstats)
|
||||
{
|
||||
u32 nr_pages = pbat_len(&kparams->params);
|
||||
|
||||
|
@ -56,6 +58,7 @@ pbat_ctr(struct pbat* pbat,
|
|||
pbat->ref = 0;
|
||||
mutex_init(&pbat->lock);
|
||||
pbat->kparams = kparams;
|
||||
pbat->kstats = kstats;
|
||||
pbat->full = false;
|
||||
pbat->last_alloc = 0;
|
||||
pbat->pagev = kzalloc(nr_pages * sizeof(struct page*), GFP_KERNEL);
|
||||
|
@ -121,6 +124,9 @@ pbat_flush(struct pbat* pbat)
|
|||
pblk = pbat_off(&pbat->kparams->params, pbat->zone);
|
||||
pblk_write(pbat->kparams, pblk, nr_pages, pbat->pagev);
|
||||
mutex_unlock(&pbat->lock);
|
||||
mutex_lock(&pbat->kstats->lock);
|
||||
++pbat->kstats->pbat_w;
|
||||
mutex_unlock(&pbat->kstats->lock);
|
||||
|
||||
return ret;
|
||||
|
||||
|
@ -146,6 +152,9 @@ pbat_read(struct pbat* pbat)
|
|||
}
|
||||
pblk = pbat_off(&pbat->kparams->params, pbat->zone);
|
||||
ret = pblk_read_wait(pbat->kparams, pblk, nr_pages, pbat->pagev);
|
||||
mutex_lock(&pbat->kstats->lock);
|
||||
++pbat->kstats->pbat_r;
|
||||
mutex_unlock(&pbat->kstats->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -250,7 +259,8 @@ pbatcache_size(void)
|
|||
|
||||
bool
|
||||
pbatcache_ctr(struct pbatcache* pc,
|
||||
struct compress_params* kparams, u32 cache_pages)
|
||||
struct compress_params* kparams, struct compress_stats* kstats,
|
||||
u32 cache_pages)
|
||||
{
|
||||
struct pbat* cache;
|
||||
u32 cache_len;
|
||||
|
@ -274,7 +284,7 @@ pbatcache_ctr(struct pbatcache* pc,
|
|||
pc->cache_len = cache_len;
|
||||
pc->cache = cache;
|
||||
for (n = 0; n < cache_len; ++n) {
|
||||
if (!pbat_ctr(&cache[n], kparams)) {
|
||||
if (!pbat_ctr(&cache[n], kparams, kstats)) {
|
||||
return false;
|
||||
}
|
||||
list_add_tail(&cache[n].list, &pc->cache_head);
|
||||
|
|
|
@ -519,6 +519,12 @@ struct compress_params {
|
|||
struct compress_stats {
|
||||
struct mutex lock;
|
||||
struct cbd_stats stats;
|
||||
u64 pbat_r;
|
||||
u64 pbat_w;
|
||||
u64 lbatpblk_r;
|
||||
u64 lbatpblk_w;
|
||||
u64 lbd_r;
|
||||
u64 lbd_w;
|
||||
};
|
||||
|
||||
typedef void (*pblk_endio_t)(struct bio*);
|
||||
|
@ -551,7 +557,8 @@ int pbat_free(struct pbat* pbat, u64 pblk);
|
|||
struct pbatcache;
|
||||
size_t pbatcache_size(void);
|
||||
bool pbatcache_ctr(struct pbatcache* pbatcache,
|
||||
struct compress_params* kparams, u32 cache_pages);
|
||||
struct compress_params* kparams, struct compress_stats* kstats,
|
||||
u32 cache_pages);
|
||||
void pbatcache_dtr(struct pbatcache* pbatcache);
|
||||
struct pbat*
|
||||
pbatcache_get(struct pbatcache* pbatcache, u32 zone, bool avail);
|
||||
|
@ -565,7 +572,8 @@ void lbatpblk_put_buf(struct lbatpblk* lp);
|
|||
struct lbatpblkcache;
|
||||
size_t lbatpblkcache_size(void);
|
||||
bool lbatpblkcache_ctr(struct lbatpblkcache* lpc,
|
||||
struct compress_params* kparams, u32 cache_pages);
|
||||
struct compress_params* kparams, struct compress_stats* kstats,
|
||||
u32 cache_pages);
|
||||
void lbatpblkcache_dtr(struct lbatpblkcache* lpc);
|
||||
struct lbatpblk*
|
||||
lbatpblkcache_get(struct lbatpblkcache* lpc, u64 pblk);
|
||||
|
|
Loading…
Reference in New Issue