From patchwork Thu Apr 17 20:06:20 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasily Tarasov X-Patchwork-Id: 4082951 Return-Path: X-Original-To: patchwork-dm-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 13291BFF02 for ; Mon, 28 Apr 2014 22:10:54 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2CD8F201EC for ; Mon, 28 Apr 2014 22:10:53 +0000 (UTC) Received: from mx6-phx2.redhat.com (mx6-phx2.redhat.com [209.132.183.39]) by mail.kernel.org (Postfix) with ESMTP id 2AF36201BC for ; Mon, 28 Apr 2014 22:10:52 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx6-phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s3SM76xl026894; Mon, 28 Apr 2014 18:07:06 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id s3SM6Haw007576 for ; Mon, 28 Apr 2014 18:06:17 -0400 Received: from mx1.redhat.com (ext-mx13.extmail.prod.ext.phx2.redhat.com [10.5.110.18]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s3SM6HNQ028617 for ; Mon, 28 Apr 2014 18:06:17 -0400 Received: from mail-qa0-f53.google.com (mail-qa0-f53.google.com [209.85.216.53]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s3SM6G1d022041 for ; Mon, 28 Apr 2014 18:06:16 -0400 Received: by mail-qa0-f53.google.com with SMTP id i13so650618qae.26 for ; Mon, 28 Apr 2014 15:06:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:sender:from:date:subject:to:cc; bh=hQ56ggrekGtXdXWXNiqij/7MSgn/m/DprOn+oT7RiOw=; b=MTvCCPc9a++YdGp7HgUh/Eu5mYukgTqsJ4QXhVTDLR0nn/7FD8d1S13D3k42bqejQt 6/0O5eddFr85HvSzYpQG91xFQBp0CsM4iWgX/f8xveYDfvxLRjZpH8mebCdTvBo4jDur DRDOKOKEXKpAqrLPT6Gs0gHz0CevN0G6gY08s3dxFqL2VzkdGJs0LLeta7d5FJoZRtSX 5kvXIJCJiOEoVeB4MVQE/ZHqEwkcWIIc2CiXSi2l9cEu6gqYNjgckrNTg47492Knz4YU 76VcSrLxpfTywaKoiD3oj4+qKMrj165z6B3H9Ed1OeLV/ziGfm21tF486wITd3kNqocD dFsA== X-Received: by 10.224.69.130 with SMTP id z2mr8244084qai.87.1398722775628; Mon, 28 Apr 2014 15:06:15 -0700 (PDT) Received: from localhost (ool-18e4aba6.dyn.optonline.net. [24.228.171.166]) by mx.google.com with ESMTPSA id c90sm23778470qgd.3.2014.04.28.15.06.14 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 28 Apr 2014 15:06:15 -0700 (PDT) Message-ID: <535ed0d7.e3508c0a.0da6.ffffc9ca@mx.google.com> From: Vasily Tarasov Date: Thu, 17 Apr 2014 16:06:20 -0400 To: dm-devel@redhat.com X-RedHat-Spam-Score: 0.656 (BAYES_00, DATE_IN_PAST_96_XX, DCC_REPUT_00_12, DKIM_SIGNED, DKIM_VALID, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS, URIBL_BLOCKED) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Scanned-By: MIMEDefang 2.68 on 10.5.110.18 X-loop: dm-devel@redhat.com Cc: Christoph Hellwig , Philip Shilane , Sonam Mandal , Erez Zadok Subject: [dm-devel] [PATCH RFC 03/10] dm-dedup: hash computation X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Spam-Status: No, score=1.0 required=5.0 tests=BAYES_00, DATE_IN_PAST_96_XX, DKIM_SIGNED, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hash-computation functions. We preallocate a table of hash descriptors in advance to improve performance. Signed-off-by: Vasily Tarasov --- drivers/md/dm-dedup-hash.c | 148 ++++++++++++++++++++++++++++++++++++++++++++ drivers/md/dm-dedup-hash.h | 30 +++++++++ 2 files changed, 178 insertions(+), 0 deletions(-) create mode 100644 drivers/md/dm-dedup-hash.c create mode 100644 drivers/md/dm-dedup-hash.h diff --git a/drivers/md/dm-dedup-hash.c b/drivers/md/dm-dedup-hash.c new file mode 100644 index 0000000..0c8362c --- /dev/null +++ b/drivers/md/dm-dedup-hash.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2012-2014 Vasily Tarasov + * Copyright (C) 2012-2014 Geoff Kuenning + * Copyright (C) 2012-2014 Sonam Mandal + * Copyright (C) 2012-2014 Karthikeyani Palanisami + * Copyright (C) 2012-2014 Philip Shilane + * Copyright (C) 2012-2014 Sagar Trehan + * Copyright (C) 2012-2014 Erez Zadok + * + * This file is released under the GPL. + */ + +#include "dm-dedup-target.h" +#include "dm-dedup-hash.h" +#include +#include + +/* + * We are declaring and initalizaing global hash_desc, because + * we need to do hash computation in endio function, and this + * function is called in softirq context. Hence we are not + * allowed to perform any operation on that path which can sleep. + * And tfm allocation in hash_desc, at one point, tries to take + * semaphore and hence tries to sleep. And because of this we get + * BUG, which complains "Scheduling while atomic". Hence to avoid + * this scenario, we moved the declaration and initialization out + * of critical path. + */ +static struct hash_desc *slot_to_desc(struct hash_desc_table *desc_table, + unsigned long slot) +{ + BUG_ON(slot >= DEDUP_HASH_DESC_COUNT); + return &(desc_table->desc[slot]); +} + +struct hash_desc_table *desc_table_init(char *hash_alg) +{ + int i = 0; + struct hash_desc *desc; + struct hash_desc_table *desc_table; + + desc_table = kmalloc(sizeof(struct hash_desc_table), GFP_NOIO); + if (!desc_table) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < DEDUP_HASH_DESC_COUNT; i++) { + desc_table->free_bitmap[i] = true; + desc = desc_table->desc + i; + desc->flags = 0; + desc->tfm = crypto_alloc_hash(hash_alg, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(desc->tfm)) + return (struct hash_desc_table *)desc->tfm; + } + + atomic_long_set(&(desc_table->slot_counter), 0); + + return desc_table; +} + +void desc_table_deinit(struct hash_desc_table *desc_table) +{ + int i = 0; + struct hash_desc *desc; + + for (i = 0; i < DEDUP_HASH_DESC_COUNT; i++) { + desc = desc_table->desc + i; + crypto_free_hash(desc->tfm); + } + + kfree(desc_table); + desc_table = NULL; + + return; +} + +static int get_next_slot(struct hash_desc_table *desc_table) +{ + unsigned long num = 0; + int count = 0; + + do { + if (count == DEDUP_HASH_DESC_COUNT) + BUG(); + + count++; + num = atomic_long_inc_return(&(desc_table->slot_counter)); + num = num % DEDUP_HASH_DESC_COUNT; + + } while (!desc_table->free_bitmap[num]); + + /* XXX: Possibility of race condition here. As checking of bitmap + * and its setting is not happening in same step. But it will + * work for now, as we declare atleast twice more hash_desc + * then number of threads. + */ + desc_table->free_bitmap[num] = false; + + return num; +} + +static void put_slot(struct hash_desc_table *desc_table, unsigned long slot) +{ + BUG_ON(slot >= DEDUP_HASH_DESC_COUNT); + BUG_ON(desc_table->free_bitmap[slot]); + desc_table->free_bitmap[slot] = true; + return; +} + +unsigned int get_hash_digestsize(struct hash_desc_table *desc_table) +{ + unsigned long slot; + struct hash_desc *desc; + + slot = get_next_slot(desc_table); + desc = slot_to_desc(desc_table, slot); + + return crypto_hash_digestsize(desc->tfm); +} + +int compute_hash_bio(struct hash_desc_table *desc_table, + struct bio *bio, char *hash) +{ + struct scatterlist sg; + int ret = 0; + unsigned long slot; + struct bio_vec bvec; + struct bvec_iter iter; + struct hash_desc *desc; + + slot = get_next_slot(desc_table); + desc = slot_to_desc(desc_table, slot); + + ret = crypto_hash_init(desc); + if (ret) + goto out; + + sg_init_table(&sg, 1); + __bio_for_each_segment(bvec, bio, iter, bio->bi_iter) { + sg_set_page(&sg, bvec.bv_page, bvec.bv_len, + bvec.bv_offset); + crypto_hash_update(desc, &sg, sg.length); + } + + crypto_hash_final(desc, hash); +out: + put_slot(desc_table, slot); + return ret; +} diff --git a/drivers/md/dm-dedup-hash.h b/drivers/md/dm-dedup-hash.h new file mode 100644 index 0000000..9eb791d --- /dev/null +++ b/drivers/md/dm-dedup-hash.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2012-2014 Vasily Tarasov + * Copyright (C) 2012-2014 Geoff Kuenning + * Copyright (C) 2012-2014 Sonam Mandal + * Copyright (C) 2012-2014 Karthikeyani Palanisami + * Copyright (C) 2012-2014 Philip Shilane + * Copyright (C) 2012-2014 Sagar Trehan + * Copyright (C) 2012-2014 Erez Zadok + * + * This file is released under the GPL. + */ + +#ifndef DM_DEDUP_HASH_H +#define DM_DEDUP_HASH_H + +#define DEDUP_HASH_DESC_COUNT 128 + +struct hash_desc_table { + struct hash_desc desc[DEDUP_HASH_DESC_COUNT]; + bool free_bitmap[DEDUP_HASH_DESC_COUNT]; + atomic_long_t slot_counter; +} /*desc_table*/; + +extern void desc_table_deinit(struct hash_desc_table *desc_table); +extern struct hash_desc_table *desc_table_init(char *crypt_alg); +extern int compute_hash_bio(struct hash_desc_table *desc_table, + struct bio *bio, char *hash); +extern unsigned int get_hash_digestsize(struct hash_desc_table *desc_table); + +#endif /* DM_DEDUP_HASH_H */