[v4,07/18] btrfs: dedup: Implement btrfs_dedup_calc_hash interface
diff mbox

Message ID 1452751054-2365-8-git-send-email-quwenruo@cn.fujitsu.com
State New
Headers show

Commit Message

Qu Wenruo Jan. 14, 2016, 5:57 a.m. UTC
From: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>

Unlike in-memory or on-disk dedup method, only SHA256 hash method is
supported yet, so implement btrfs_dedup_calc_hash() interface using
SHA256.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
---
 fs/btrfs/dedup.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

Comments

Filipe Manana Jan. 14, 2016, 10:08 a.m. UTC | #1
On Thu, Jan 14, 2016 at 5:57 AM, Qu Wenruo <quwenruo@cn.fujitsu.com> wrote:
> From: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
>
> Unlike in-memory or on-disk dedup method, only SHA256 hash method is
> supported yet, so implement btrfs_dedup_calc_hash() interface using
> SHA256.
>
> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
> Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
> ---
>  fs/btrfs/dedup.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 57 insertions(+)
>
> diff --git a/fs/btrfs/dedup.c b/fs/btrfs/dedup.c
> index d6ee576..8860916 100644
> --- a/fs/btrfs/dedup.c
> +++ b/fs/btrfs/dedup.c
> @@ -465,3 +465,60 @@ int btrfs_dedup_search(struct inode *inode, u64 file_pos,
>         }
>         return ret;
>  }
> +
> +static int hash_data(struct btrfs_dedup_info *dedup_info, const char *data,
> +                    u64 length, struct btrfs_dedup_hash *hash)
> +{
> +       struct crypto_shash *tfm = dedup_info->dedup_driver;
> +       struct {
> +               struct shash_desc desc;
> +               char ctx[crypto_shash_descsize(tfm)];
> +       } sdesc;
> +       int ret;
> +
> +       sdesc.desc.tfm = tfm;
> +       sdesc.desc.flags = 0;
> +
> +       ret = crypto_shash_digest(&sdesc.desc, data, length,
> +                                 (char *)(hash->hash));
> +       return ret;
> +}
> +
> +int btrfs_dedup_calc_hash(struct btrfs_root *root, struct inode *inode,
> +                         u64 start, struct btrfs_dedup_hash *hash)
> +{
> +       struct page *p;
> +       struct btrfs_dedup_info *dedup_info = root->fs_info->dedup_info;
> +       char *data;
> +       int i;
> +       int ret;
> +       u64 dedup_bs;
> +       u64 sectorsize = root->sectorsize;
> +
> +       if (!dedup_info || !hash)
> +               return 0;
> +
> +       WARN_ON(!IS_ALIGNED(start, sectorsize));
> +
> +       dedup_bs = dedup_info->blocksize;
> +       sectorsize = root->sectorsize;
> +
> +       data = kmalloc(dedup_bs, GFP_NOFS);
> +       if (!data)
> +               return -ENOMEM;
> +       for (i = 0; sectorsize * i < dedup_bs; i++) {
> +               char *d;
> +
> +               /* TODO: Add support for subpage size case */
> +               p = find_get_page(inode->i_mapping,
> +                                 (start >> PAGE_CACHE_SHIFT) + i);
> +               WARN_ON(!p);

If !p, we should return with an error too, otherwise we'll get a null
pointer dereference below.

> +               d = kmap_atomic(p);
> +               memcpy((data + sectorsize * i), d, sectorsize);
> +               kunmap_atomic(d);
> +               page_cache_release(p);
> +       }
> +       ret = hash_data(dedup_info, data, dedup_bs, hash);
> +       kfree(data);
> +       return ret;
> +}
> --
> 2.7.0
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
Qu Wenruo Jan. 15, 2016, 1:41 a.m. UTC | #2
Filipe Manana wrote on 2016/01/14 10:08 +0000:
> On Thu, Jan 14, 2016 at 5:57 AM, Qu Wenruo <quwenruo@cn.fujitsu.com> wrote:
>> From: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
>>
>> Unlike in-memory or on-disk dedup method, only SHA256 hash method is
>> supported yet, so implement btrfs_dedup_calc_hash() interface using
>> SHA256.
>>
>> Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
>> Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
>> ---
>>   fs/btrfs/dedup.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 57 insertions(+)
>>
>> diff --git a/fs/btrfs/dedup.c b/fs/btrfs/dedup.c
>> index d6ee576..8860916 100644
>> --- a/fs/btrfs/dedup.c
>> +++ b/fs/btrfs/dedup.c
>> @@ -465,3 +465,60 @@ int btrfs_dedup_search(struct inode *inode, u64 file_pos,
>>          }
>>          return ret;
>>   }
>> +
>> +static int hash_data(struct btrfs_dedup_info *dedup_info, const char *data,
>> +                    u64 length, struct btrfs_dedup_hash *hash)
>> +{
>> +       struct crypto_shash *tfm = dedup_info->dedup_driver;
>> +       struct {
>> +               struct shash_desc desc;
>> +               char ctx[crypto_shash_descsize(tfm)];
>> +       } sdesc;
>> +       int ret;
>> +
>> +       sdesc.desc.tfm = tfm;
>> +       sdesc.desc.flags = 0;
>> +
>> +       ret = crypto_shash_digest(&sdesc.desc, data, length,
>> +                                 (char *)(hash->hash));
>> +       return ret;
>> +}
>> +
>> +int btrfs_dedup_calc_hash(struct btrfs_root *root, struct inode *inode,
>> +                         u64 start, struct btrfs_dedup_hash *hash)
>> +{
>> +       struct page *p;
>> +       struct btrfs_dedup_info *dedup_info = root->fs_info->dedup_info;
>> +       char *data;
>> +       int i;
>> +       int ret;
>> +       u64 dedup_bs;
>> +       u64 sectorsize = root->sectorsize;
>> +
>> +       if (!dedup_info || !hash)
>> +               return 0;
>> +
>> +       WARN_ON(!IS_ALIGNED(start, sectorsize));
>> +
>> +       dedup_bs = dedup_info->blocksize;
>> +       sectorsize = root->sectorsize;
>> +
>> +       data = kmalloc(dedup_bs, GFP_NOFS);
>> +       if (!data)
>> +               return -ENOMEM;
>> +       for (i = 0; sectorsize * i < dedup_bs; i++) {
>> +               char *d;
>> +
>> +               /* TODO: Add support for subpage size case */
>> +               p = find_get_page(inode->i_mapping,
>> +                                 (start >> PAGE_CACHE_SHIFT) + i);
>> +               WARN_ON(!p);
>
> If !p, we should return with an error too, otherwise we'll get a null
> pointer dereference below.

Right, and that's also true for all the caller of find_get_page() in btrfs.

I'll also locate and fix them in another patch before btrfs dedup patchset.

Thanks for the review and hint.
Qu

>
>> +               d = kmap_atomic(p);
>> +               memcpy((data + sectorsize * i), d, sectorsize);
>> +               kunmap_atomic(d);
>> +               page_cache_release(p);
>> +       }
>> +       ret = hash_data(dedup_info, data, dedup_bs, hash);
>> +       kfree(data);
>> +       return ret;
>> +}
>> --
>> 2.7.0
>>
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>


--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch
diff mbox

diff --git a/fs/btrfs/dedup.c b/fs/btrfs/dedup.c
index d6ee576..8860916 100644
--- a/fs/btrfs/dedup.c
+++ b/fs/btrfs/dedup.c
@@ -465,3 +465,60 @@  int btrfs_dedup_search(struct inode *inode, u64 file_pos,
 	}
 	return ret;
 }
+
+static int hash_data(struct btrfs_dedup_info *dedup_info, const char *data,
+		     u64 length, struct btrfs_dedup_hash *hash)
+{
+	struct crypto_shash *tfm = dedup_info->dedup_driver;
+	struct {
+		struct shash_desc desc;
+		char ctx[crypto_shash_descsize(tfm)];
+	} sdesc;
+	int ret;
+
+	sdesc.desc.tfm = tfm;
+	sdesc.desc.flags = 0;
+
+	ret = crypto_shash_digest(&sdesc.desc, data, length,
+				  (char *)(hash->hash));
+	return ret;
+}
+
+int btrfs_dedup_calc_hash(struct btrfs_root *root, struct inode *inode,
+			  u64 start, struct btrfs_dedup_hash *hash)
+{
+	struct page *p;
+	struct btrfs_dedup_info *dedup_info = root->fs_info->dedup_info;
+	char *data;
+	int i;
+	int ret;
+	u64 dedup_bs;
+	u64 sectorsize = root->sectorsize;
+
+	if (!dedup_info || !hash)
+		return 0;
+
+	WARN_ON(!IS_ALIGNED(start, sectorsize));
+
+	dedup_bs = dedup_info->blocksize;
+	sectorsize = root->sectorsize;
+
+	data = kmalloc(dedup_bs, GFP_NOFS);
+	if (!data)
+		return -ENOMEM;
+	for (i = 0; sectorsize * i < dedup_bs; i++) {
+		char *d;
+
+		/* TODO: Add support for subpage size case */
+		p = find_get_page(inode->i_mapping,
+				  (start >> PAGE_CACHE_SHIFT) + i);
+		WARN_ON(!p);
+		d = kmap_atomic(p);
+		memcpy((data + sectorsize * i), d, sectorsize);
+		kunmap_atomic(d);
+		page_cache_release(p);
+	}
+	ret = hash_data(dedup_info, data, dedup_bs, hash);
+	kfree(data);
+	return ret;
+}