Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751321AbdCPCq5 (ORCPT ); Wed, 15 Mar 2017 22:46:57 -0400 Received: from mail-pg0-f67.google.com ([74.125.83.67]:35101 "EHLO mail-pg0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751143AbdCPCqw (ORCPT ); Wed, 15 Mar 2017 22:46:52 -0400 From: js1304@gmail.com X-Google-Original-From: iamjoonsoo.kim@lge.com To: Andrew Morton Cc: Minchan Kim , Sergey Senozhatsky , linux-kernel@vger.kernel.org, kernel-team@lge.com, Joonsoo Kim Subject: [PATCH 2/4] zram: introduce zram_entry to prepare dedup functionality Date: Thu, 16 Mar 2017 11:46:36 +0900 Message-Id: <1489632398-31501-3-git-send-email-iamjoonsoo.kim@lge.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1489632398-31501-1-git-send-email-iamjoonsoo.kim@lge.com> References: <1489632398-31501-1-git-send-email-iamjoonsoo.kim@lge.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8118 Lines: 247 From: Joonsoo Kim Following patch will implement deduplication functionality in the zram and it requires an indirection layer to manage the life cycle of zsmalloc handle. To prepare that, this patch introduces zram_entry which can be used to manage the life-cycle of zsmalloc handle. Many lines are changed due to rename but core change is just simple introduction about newly data structure. Signed-off-by: Joonsoo Kim --- drivers/block/zram/zram_drv.c | 81 ++++++++++++++++++++++++++++--------------- drivers/block/zram/zram_drv.h | 6 +++- 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index f65dcd1..a3d9cbca 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -419,6 +419,31 @@ static ssize_t debug_stat_show(struct device *dev, static DEVICE_ATTR_RO(mm_stat); static DEVICE_ATTR_RO(debug_stat); +static struct zram_entry *zram_entry_alloc(struct zram_meta *meta, + unsigned int len, gfp_t flags) +{ + struct zram_entry *entry; + + entry = kzalloc(sizeof(*entry), flags); + if (!entry) + return NULL; + + entry->handle = zs_malloc(meta->mem_pool, len, flags); + if (!entry->handle) { + kfree(entry); + return NULL; + } + + return entry; +} + +static inline void zram_entry_free(struct zram_meta *meta, + struct zram_entry *entry) +{ + zs_free(meta->mem_pool, entry->handle); + kfree(entry); +} + static void zram_meta_free(struct zram_meta *meta, u64 disksize) { size_t num_pages = disksize >> PAGE_SHIFT; @@ -426,15 +451,15 @@ static void zram_meta_free(struct zram_meta *meta, u64 disksize) /* Free all pages that are still in this zram device */ for (index = 0; index < num_pages; index++) { - unsigned long handle = meta->table[index].handle; + struct zram_entry *entry = meta->table[index].entry; /* * No memory is allocated for same element filled pages. * Simply clear same page flag. */ - if (!handle || zram_test_flag(meta, index, ZRAM_SAME)) + if (!entry || zram_test_flag(meta, index, ZRAM_SAME)) continue; - zs_free(meta->mem_pool, handle); + zram_entry_free(meta, entry); } zs_destroy_pool(meta->mem_pool); @@ -479,7 +504,7 @@ static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize) static void zram_free_page(struct zram *zram, size_t index) { struct zram_meta *meta = zram->meta; - unsigned long handle = meta->table[index].handle; + struct zram_entry *entry = meta->table[index].entry; /* * No memory is allocated for same element filled pages. @@ -492,16 +517,16 @@ static void zram_free_page(struct zram *zram, size_t index) return; } - if (!handle) + if (!entry) return; - zs_free(meta->mem_pool, handle); + zram_entry_free(meta, entry); atomic64_sub(zram_get_obj_size(meta, index), &zram->stats.compr_data_size); atomic64_dec(&zram->stats.pages_stored); - meta->table[index].handle = 0; + meta->table[index].entry = NULL; zram_set_obj_size(meta, index, 0); } @@ -510,20 +535,20 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) int ret = 0; unsigned char *cmem; struct zram_meta *meta = zram->meta; - unsigned long handle; + struct zram_entry *entry; unsigned int size; bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); - handle = meta->table[index].handle; + entry = meta->table[index].entry; size = zram_get_obj_size(meta, index); - if (!handle || zram_test_flag(meta, index, ZRAM_SAME)) { + if (!entry || zram_test_flag(meta, index, ZRAM_SAME)) { bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); zram_fill_page(mem, PAGE_SIZE, meta->table[index].element); return 0; } - cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_RO); + cmem = zs_map_object(meta->mem_pool, entry->handle, ZS_MM_RO); if (size == PAGE_SIZE) { copy_page(mem, cmem); } else { @@ -532,7 +557,7 @@ static int zram_decompress_page(struct zram *zram, char *mem, u32 index) ret = zcomp_decompress(zstrm, cmem, size, mem); zcomp_stream_put(zram->comp); } - zs_unmap_object(meta->mem_pool, handle); + zs_unmap_object(meta->mem_pool, entry->handle); bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); /* Should NEVER happen. Return bio error if it does. */ @@ -554,7 +579,7 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec, page = bvec->bv_page; bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); - if (unlikely(!meta->table[index].handle) || + if (unlikely(!meta->table[index].entry) || zram_test_flag(meta, index, ZRAM_SAME)) { bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); handle_same_page(bvec, meta->table[index].element); @@ -599,7 +624,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, { int ret = 0; unsigned int clen; - unsigned long handle = 0; + struct zram_entry *entry = NULL; struct page *page; unsigned char *user_mem, *cmem, *src, *uncmem = NULL; struct zram_meta *meta = zram->meta; @@ -670,29 +695,31 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, } /* - * handle allocation has 2 paths: + * entry allocation has 2 paths: * a) fast path is executed with preemption disabled (for * per-cpu streams) and has __GFP_DIRECT_RECLAIM bit clear, * since we can't sleep; * b) slow path enables preemption and attempts to allocate * the page with __GFP_DIRECT_RECLAIM bit set. we have to * put per-cpu compression stream and, thus, to re-do - * the compression once handle is allocated. + * the compression once entry is allocated. * - * if we have a 'non-null' handle here then we are coming - * from the slow path and handle has already been allocated. + * if we have a 'non-null' entry here then we are coming + * from the slow path and entry has already been allocated. */ - if (!handle) - handle = zs_malloc(meta->mem_pool, clen, + if (!entry) { + entry = zram_entry_alloc(meta, clen, __GFP_KSWAPD_RECLAIM | __GFP_NOWARN); - if (!handle) { + } + + if (!entry) { zcomp_stream_put(zram->comp); zstrm = NULL; atomic64_inc(&zram->stats.writestall); - handle = zs_malloc(meta->mem_pool, clen, GFP_NOIO); - if (handle) + entry = zram_entry_alloc(meta, clen, GFP_NOIO); + if (entry) goto compress_again; pr_err("Error allocating memory for compressed page: %u, size=%u\n", @@ -705,12 +732,12 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, update_used_max(zram, alloced_pages); if (zram->limit_pages && alloced_pages > zram->limit_pages) { - zs_free(meta->mem_pool, handle); + zram_entry_free(meta, entry); ret = -ENOMEM; goto out; } - cmem = zs_map_object(meta->mem_pool, handle, ZS_MM_WO); + cmem = zs_map_object(meta->mem_pool, entry->handle, ZS_MM_WO); if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) { src = kmap_atomic(page); @@ -722,7 +749,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, zcomp_stream_put(zram->comp); zstrm = NULL; - zs_unmap_object(meta->mem_pool, handle); + zs_unmap_object(meta->mem_pool, entry->handle); /* * Free memory associated with this sector @@ -731,7 +758,7 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, bit_spin_lock(ZRAM_ACCESS, &meta->table[index].value); zram_free_page(zram, index); - meta->table[index].handle = handle; + meta->table[index].entry = entry; zram_set_obj_size(meta, index, clen); bit_spin_unlock(ZRAM_ACCESS, &meta->table[index].value); diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index caeff51..a7ae46c 100644 --- a/drivers/block/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h @@ -69,10 +69,14 @@ enum zram_pageflags { /*-- Data structures */ +struct zram_entry { + unsigned long handle; +}; + /* Allocated for each disk page */ struct zram_table_entry { union { - unsigned long handle; + struct zram_entry *entry; unsigned long element; }; unsigned long value; -- 1.9.1