linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chandra Seetharaman <sekharan@us.ibm.com>
To: linux-btrfs@vger.kernel.org
Cc: Chandra Seetharaman <sekharan@us.ibm.com>
Subject: [PATCH 5/7] btrfs: subpagesize-blocksize: handle checksum calculations properly
Date: Wed, 11 Dec 2013 17:38:40 -0600	[thread overview]
Message-ID: <1386805122-23972-6-git-send-email-sekharan@us.ibm.com> (raw)
In-Reply-To: <1386805122-23972-1-git-send-email-sekharan@us.ibm.com>

With subpagesize-blocksize, the IO is done in pages but checksums are
calculated in blocks.

This patch makes sure the checksums are calculated, stored, and verfied
from proper indexes in the page.

Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
 fs/btrfs/file-item.c | 45 ++++++++++++++++++++++++++++++++++++---------
 fs/btrfs/inode.c     | 26 ++++++++++++++++++++------
 2 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 6f38488..d75bda3 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -175,14 +175,16 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
 	u32 diff;
 	int nblocks;
 	int bio_index = 0;
-	int count;
+	int count, bvec_count;
 	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
+	unsigned int blocks_per_bvec;
 
 	path = btrfs_alloc_path();
 	if (!path)
 		return -ENOMEM;
 
 	nblocks = bio->bi_size >> inode->i_sb->s_blocksize_bits;
+	blocks_per_bvec =  bvec->bv_len >> inode->i_sb->s_blocksize_bits;
 	if (!dst) {
 		if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
 			btrfs_bio->csum_allocated = kmalloc(nblocks * csum_size,
@@ -221,8 +223,10 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
 	if (dio)
 		offset = logical_offset;
 	while (bio_index < bio->bi_vcnt) {
+		bvec_count = 0;
 		if (!dio)
 			offset = page_offset(bvec->bv_page) + bvec->bv_offset;
+same_bvec:
 		count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
 					       (u32 *)csum, nblocks);
 		if (count)
@@ -281,12 +285,26 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
 found:
 		csum += count * csum_size;
 		nblocks -= count;
-		while (count--) {
+		while (count >= blocks_per_bvec) {
+			count -= blocks_per_bvec;
 			disk_bytenr += bvec->bv_len;
 			offset += bvec->bv_len;
 			bio_index++;
 			bvec++;
 		}
+			
+		if (count) {
+			while (count--) {
+				bvec_count++;
+				disk_bytenr += inode->i_sb->s_blocksize;
+				offset += inode->i_sb->s_blocksize;
+			}
+			if (bvec_count == blocks_per_bvec) {
+				bio_index++;
+				bvec++;
+			} else
+				goto same_bvec;
+		}
 	}
 	btrfs_free_path(path);
 	return 0;
@@ -444,7 +462,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
 	int index;
 	unsigned long total_bytes = 0;
 	unsigned long this_sum_bytes = 0;
-	u64 offset;
+	u64 offset, pg_offset;
+	size_t csum_size;
 
 	WARN_ON(bio->bi_vcnt <= 0);
 	sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS);
@@ -489,17 +508,25 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
 			index = 0;
 		}
 
+		if ((inode->i_sb->s_blocksize) < bvec->bv_len)
+			csum_size = inode->i_sb->s_blocksize;
+		else
+			csum_size = bvec->bv_len;
 		data = kmap_atomic(bvec->bv_page);
-		sums->sums[index] = ~(u32)0;
-		sums->sums[index] = btrfs_csum_data(data + bvec->bv_offset,
+		pg_offset = bvec->bv_offset;
+		while (pg_offset < bvec->bv_offset + bvec->bv_len) {
+			sums->sums[index] = ~(u32)0;
+			sums->sums[index] = btrfs_csum_data(data + pg_offset,
 						    sums->sums[index],
-						    bvec->bv_len);
+						    csum_size);
+			btrfs_csum_final(sums->sums[index],
+					(char *)(sums->sums + index));
+			index++;
+			pg_offset += csum_size;
+		}
 		kunmap_atomic(data);
-		btrfs_csum_final(sums->sums[index],
-				 (char *)(sums->sums + index));
 
 		bio_index++;
-		index++;
 		total_bytes += bvec->bv_len;
 		this_sum_bytes += bvec->bv_len;
 		offset += bvec->bv_len;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c0c18ca..a87d0d0 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2781,6 +2781,7 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	u32 csum_expected;
 	u32 csum = ~(u32)0;
+	u64 total_len, csum_len, csum_index;
 	static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
 	                              DEFAULT_RATELIMIT_BURST);
 
@@ -2799,14 +2800,27 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 		return 0;
 	}
 
-	phy_offset >>= inode->i_sb->s_blocksize_bits;
-	csum_expected = *(((u32 *)io_bio->csum) + phy_offset);
+	total_len = end - start + 1;
+	if (inode->i_sb->s_blocksize < PAGE_CACHE_SIZE)
+		csum_len = inode->i_sb->s_blocksize;
+	else
+		csum_len = end - start + 1;
+
+	csum_index = phy_offset >> inode->i_sb->s_blocksize_bits;
 
 	kaddr = kmap_atomic(page);
-	csum = btrfs_csum_data(kaddr + offset, csum,  end - start + 1);
-	btrfs_csum_final(csum, (char *)&csum);
-	if (csum != csum_expected)
-		goto zeroit;
+	while (total_len > 0) {
+		csum_expected = *(((u32 *)io_bio->csum) + csum_index);
+		csum = ~(u32)0;
+		csum = btrfs_csum_data(kaddr + offset, csum, csum_len);
+		btrfs_csum_final(csum, (char *)&csum);
+		if (csum != csum_expected)
+			goto zeroit;
+		offset += csum_len;
+		total_len -= csum_len;
+		csum_index += 1;
+		phy_offset += csum_len;
+	}
 
 	kunmap_atomic(kaddr);
 good:
-- 
1.7.12.4


  parent reply	other threads:[~2013-12-11 23:40 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-11 23:38 [PATCH 0/7] Patches to support subpagesize blocksize Chandra Seetharaman
2013-12-11 23:38 ` [PATCH 1/7] btrfs: subpagesize-blocksize: Define extent_buffer_head Chandra Seetharaman
2013-12-16 12:32   ` saeed bishara
2013-12-16 16:17     ` Chandra Seetharaman
2013-12-17 15:35       ` David Sterba
2013-12-11 23:38 ` [PATCH 2/7] btrfs: subpagesize-blocksize: Use a global alignment for size Chandra Seetharaman
2013-12-16 12:33   ` saeed bishara
2013-12-16 14:48     ` David Sterba
2013-12-16 16:18       ` Chandra Seetharaman
2013-12-11 23:38 ` [PATCH 3/7] btrfs: subpagesize-blocksize: Handle small extent maps properly Chandra Seetharaman
2013-12-11 23:38 ` [PATCH 4/7] btrfs: subpagesize-blocksize: Handle iosize properly in submit_extent_page() Chandra Seetharaman
2013-12-11 23:38 ` Chandra Seetharaman [this message]
2013-12-11 23:38 ` [PATCH 6/7] btrfs: subpagesize-blocksize: Handle relocation clusters appropriately Chandra Seetharaman
2013-12-11 23:38 ` [PATCH 7/7] btrfs: subpagesize-blocksize: Allow mounting filesystems where sectorsize != PAGE_SIZE Chandra Seetharaman
2013-12-13  1:07   ` David Sterba
2013-12-16 12:50     ` saeed bishara
2013-12-12 20:40 ` [PATCH 0/7] Patches to support subpagesize blocksize Josef Bacik
2013-12-13  1:17 ` David Sterba
2013-12-13 15:17   ` Chandra Seetharaman
2013-12-13 15:58     ` David Sterba
2013-12-13 18:39 ` Josef Bacik
2013-12-13 22:09   ` Chandra Seetharaman
2014-01-08 20:06   ` Chandra Seetharaman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1386805122-23972-6-git-send-email-sekharan@us.ibm.com \
    --to=sekharan@us.ibm.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).