diff --git a/dm-compress/compress.c b/dm-compress/compress.c index d30a178..35f8ad9 100644 --- a/dm-compress/compress.c +++ b/dm-compress/compress.c @@ -149,6 +149,7 @@ compress_read_header(struct compress* c) printk(KERN_INFO "%s: parameters...\n", __func__); printk(KERN_INFO " algorithm=%hu\n", (unsigned short)header.params.algorithm); printk(KERN_INFO " compression=%hu\n", (unsigned short)header.params.compression); + printk(KERN_INFO " pbat_len=%hu\n", (unsigned short)header.params.pbat_len); printk(KERN_INFO " lblk_shift=%hu\n", (unsigned short)header.params.lblk_shift); 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); diff --git a/dm-compress/lbd.c b/dm-compress/lbd.c index 8f47fdf..ba723b7 100644 --- a/dm-compress/lbd.c +++ b/dm-compress/lbd.c @@ -319,8 +319,9 @@ lbd_flush(struct lbd* lbd) int err; u32 n; u64 pblk; - u32 count = lblk_per_pblk(lbd->params); - struct page* iopagev[count]; + u32 nr_pages = lblk_per_pblk(lbd->params); + u32 count; + struct page* iopagev[1]; mutex_lock(&lbd->lock); if (!PageDirty(lbd->pagev[0])) { @@ -365,8 +366,7 @@ lbd_flush(struct lbd* lbd) goto out; unlock: - count = lblk_per_pblk(lbd->params); - for (n = 0; n < count; ++n) { + for (n = 0; n < nr_pages; ++n) { unlock_page(lbd->pagev[n]); } @@ -433,12 +433,12 @@ static int lbd_reset(struct lbd* lbd, u64 lblk) { int ret = 0; - u32 count = lblk_per_pblk(lbd->params); + u32 nr_pages = lblk_per_pblk(lbd->params); u32 n; if (lbd->lv) { printk(KERN_ERR "%s: lbatview leak\n", __func__); } - for (n = 0; n < count; ++n) { + for (n = 0; n < nr_pages; ++n) { lock_page(lbd->pagev[n]); } lbd->lv = lbatviewcache_get(lbd->lvc, lblk); @@ -468,7 +468,7 @@ out: if (ret) { lbatviewcache_put(lbd->lvc, lbd->lv); lbd->lv = NULL; - for (n = 0; n < count; ++n) { + for (n = 0; n < nr_pages; ++n) { unlock_page(lbd->pagev[n]); } lbd->lblk = LBLK_NONE; diff --git a/dm-compress/pbat.c b/dm-compress/pbat.c index 9b4ac5f..1a47ad8 100644 --- a/dm-compress/pbat.c +++ b/dm-compress/pbat.c @@ -36,7 +36,7 @@ struct pbat { struct mutex lock; struct cbd_params* params; - struct page* pages; + struct page** pagev; u8* buf; }; @@ -44,18 +44,25 @@ static bool pbat_ctr(struct pbat* pbat, struct cbd_params* params) { + u32 nr_pages = pbat_len(params); + memset(pbat, 0, sizeof(struct pbat)); pbat->zone = ZONE_NONE; mutex_init(&pbat->reflock); pbat->ref = 0; mutex_init(&pbat->lock); pbat->params = params; - pbat->pages = cbd_alloc_pages(pbat_len(params)); - if (!pbat->pages) { - printk(KERN_ERR "%s: Failed to alloc pbat_buf\n", __func__); + pbat->pagev = kzalloc(nr_pages * sizeof(struct page*), GFP_KERNEL); + if (!pbat->pagev) { + return false; + } + if (!cbd_alloc_pagev(pbat->pagev, nr_pages)) { + return false; + } + pbat->buf = vmap(pbat->pagev, nr_pages, VM_MAP, PAGE_KERNEL); + if (!pbat->buf) { return false; } - pbat->buf = page_address(pbat->pages); return true; } @@ -63,30 +70,44 @@ pbat_ctr(struct pbat* pbat, static void pbat_dtr(struct pbat* pbat) { - lock_page(pbat->pages); + u32 nr_pages = pbat_len(pbat->params); + u32 n; + + for (n = 0; n < nr_pages; ++n) { + lock_page(pbat->pagev[n]); + } + vunmap(pbat->buf); pbat->buf = NULL; - cbd_free_pages(pbat->pages, pbat_len(pbat->params)); - pbat->pages = NULL; + cbd_free_pagev(pbat->pagev, nr_pages); + kfree(pbat->pagev); + pbat->pagev = NULL; } static bool pbat_error(struct pbat* pbat) { - return PageError(pbat->pages); + u32 nr_pages = pbat_len(pbat->params); + u32 n; + + for (n = 0; n < nr_pages; ++n) { + if (PageError(pbat->pagev[n])) { + return true; + } + } + + return false; } static int pbat_flush(struct pbat* pbat) { int ret = 0; - u32 count = pbat_len(pbat->params); - struct page* iopagev[count]; - u64 pblk; + u32 nr_pages = pbat_len(pbat->params); u32 n; - u8* p; + u64 pblk; mutex_lock(&pbat->lock); - if (!PageDirty(pbat->pages)) { + if (!PageDirty(pbat->pagev[0])) { goto unlock; } if (pbat_error(pbat)) { @@ -94,17 +115,15 @@ pbat_flush(struct pbat* pbat) goto unlock; } pblk = pbat_off(pbat->params, pbat->zone); - p = pbat->buf; - for (n = 0; n < count; ++n, p += PBLK_SIZE) { - iopagev[n] = virt_to_page(p); - } - pblk_write(pbat->params->priv, pblk, count, iopagev); + pblk_write(pbat->params->priv, pblk, nr_pages, pbat->pagev); mutex_unlock(&pbat->lock); return ret; unlock: - unlock_page(pbat->pages); + for (n = 0; n < nr_pages; ++n) { + unlock_page(pbat->pagev[n]); + } mutex_unlock(&pbat->lock); return ret; @@ -114,21 +133,15 @@ static int pbat_read(struct pbat* pbat) { int ret = 0; - u32 count = pbat_len(pbat->params); - struct page* iopagev[count]; + u32 nr_pages = pbat_len(pbat->params); u64 pblk; - u32 n; - u8* p; /* XXX: can't happen because pbatcache will not use a page with an error */ - if (PageError(pbat->pages)) { + if (PageError(pbat->pagev[0])) { return -EIO; } pblk = pbat_off(pbat->params, pbat->zone); - for (n = 0, p = pbat->buf; n < count; ++n, p += PBLK_SIZE) { - iopagev[n] = virt_to_page(p); - } - ret = pblk_read_wait(pbat->params->priv, pblk, count, iopagev); + ret = pblk_read_wait(pbat->params->priv, pblk, nr_pages, pbat->pagev); return ret; } @@ -137,15 +150,21 @@ static int pbat_reset(struct pbat* pbat, u32 zone) { int ret = 0; + u32 nr_pages = pbat_len(pbat->params); + u32 n; - lock_page(pbat->pages); + for (n = 0; n < nr_pages; ++n) { + lock_page(pbat->pagev[n]); + } if (pbat->zone != zone) { pbat->zone = zone; ret = pbat_read(pbat); } if (ret) { - unlock_page(pbat->pages); + for (n = 0; n < nr_pages; ++n) { + unlock_page(pbat->pagev[n]); + } pbat->zone = ZONE_NONE; } @@ -172,7 +191,7 @@ pbat_alloc(struct pbat* pbat) goto out; } pblk = idx + zone_data_off(pbat->params, pbat->zone); - SetPageDirty(pbat->pages); + SetPageDirty(pbat->pagev[0]); out: mutex_unlock(&pbat->lock); @@ -182,7 +201,7 @@ out: int pbat_free(struct pbat* pbat, u64 pblk) { - u32 zone_pblk_count = pbat_len(pbat->params) * PBLK_SIZE_BITS; + u32 pblk_count = pbat_len(pbat->params) * PBLK_SIZE_BITS; u32 zone; u32 idx; @@ -193,10 +212,10 @@ pbat_free(struct pbat* pbat, u64 pblk) return -EINVAL; } idx = pblk - zone_data_off(pbat->params, zone); - BUG_ON(idx >= zone_pblk_count); + BUG_ON(idx >= pblk_count); mutex_lock(&pbat->lock); cbd_bitmap_free(pbat->buf, idx); - SetPageDirty(pbat->pages); + SetPageDirty(pbat->pagev[0]); mutex_unlock(&pbat->lock); return 0; diff --git a/include/libcbd.h b/include/libcbd.h index 33477c5..10291aa 100644 --- a/include/libcbd.h +++ b/include/libcbd.h @@ -50,7 +50,8 @@ typedef enum { } tristate_t; int cbd_format(const char* dev, - uint64_t psize, uint16_t lshift, uint64_t lsize, + uint64_t psize, uint16_t pbatlen, + uint16_t lshift, uint64_t lsize, enum cbd_alg alg, uint level); int cbd_open(const char* dev, const char* name); diff --git a/include/linux/dm-compress.h b/include/linux/dm-compress.h index f653d65..bdcde2f 100644 --- a/include/linux/dm-compress.h +++ b/include/linux/dm-compress.h @@ -39,6 +39,7 @@ enum cbd_alg { struct cbd_params { u8 algorithm; /* enum cbd_alg */ u8 compression; /* 0..9 */ + u16 pbat_len; u16 lblk_shift; u64 nr_pblk; u32 nr_zones; @@ -197,7 +198,7 @@ lblk_per_pblk(const struct cbd_params* params) static inline u32 pbat_len(const struct cbd_params* params) { - return 1; + return params->pbat_len; } static inline u32 @@ -296,6 +297,7 @@ cbd_header_get(const u8* buf, struct cbd_header* header) header->version_minor = get16_le(&buf); header->params.algorithm = get_byte(&buf); header->params.compression = get_byte(&buf); + header->params.pbat_len = get16_le(&buf); header->params.lblk_shift = get16_le(&buf); header->params.nr_pblk = get64_le(&buf); header->params.nr_zones = get32_le(&buf); @@ -310,6 +312,7 @@ cbd_header_put(u8* buf, const struct cbd_header* header) put16_le(&buf, header->version_minor); put_byte(&buf, header->params.algorithm); put_byte(&buf, header->params.compression); + put16_le(&buf, header->params.pbat_len); put16_le(&buf, header->params.lblk_shift); put64_le(&buf, header->params.nr_pblk); put32_le(&buf, header->params.nr_zones); diff --git a/libcbd/format.c b/libcbd/format.c index 1c9855d..8c4224b 100644 --- a/libcbd/format.c +++ b/libcbd/format.c @@ -27,7 +27,8 @@ pblk_write(int fd, u64 pblk, u32 count, const u8* data) int cbd_format(const char* dev, - uint64_t psize, uint16_t lshift, uint64_t lsize, + uint64_t psize, uint16_t pbatlen, + uint16_t lshift, uint64_t lsize, enum cbd_alg alg, uint level) { int devfd; @@ -50,6 +51,9 @@ cbd_format(const char* dev, } psize = pos / PBLK_SIZE * PBLK_SIZE; } + if (!pbatlen) { + pbatlen = 1; + } if (!lshift) { lshift = CBD_DEFAULT_LOGICAL_BLOCK_SHIFT; } @@ -77,6 +81,7 @@ cbd_format(const char* dev, printf("%s: paramaters...\n", __func__); printf(" psize=%lu\n", (unsigned long)psize); + printf(" pbatlen=%hu\n", (unsigned short)pbatlen); printf(" lshift=%hu\n", (unsigned short)lshift); printf(" lsize=%lu\n", (unsigned long)lsize); memset(&header, 0, sizeof(header)); @@ -85,6 +90,7 @@ cbd_format(const char* dev, header.version_minor = CBD_VERSION_MINOR; header.params.algorithm = alg; header.params.compression = level; + header.params.pbat_len = pbatlen; header.params.lblk_shift = lshift; header.params.nr_pblk = psize / PBLK_SIZE; /* XXX: Initial estimate */