aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file-item.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2008-07-18 06:17:13 -0400
committerChris Mason <chris.mason@oracle.com>2008-09-25 11:04:05 -0400
commit3edf7d33f4edb1e4a9bb0a4c0a84d95fb4d22a09 (patch)
tree8698a6dd1d0d038f1b56f79c92783518d36f2145 /fs/btrfs/file-item.c
parenteb84ae039e10f1f80443d846ba1350122bbdc753 (diff)
Btrfs: Handle data checksumming on bios that span multiple ordered extents
Data checksumming is done right before the bio is sent down the IO stack, which means a single bio might span more than one ordered extent. In this case, the checksumming data is split between two ordered extents. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r--fs/btrfs/file-item.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index 345caf8ff516..e02f1e5acb0a 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -134,26 +134,53 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
134 return ret; 134 return ret;
135} 135}
136 136
137int btrfs_csum_one_bio(struct btrfs_root *root, 137int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
138 struct bio *bio, struct btrfs_ordered_sum **sums_ret) 138 struct bio *bio)
139{ 139{
140 struct btrfs_ordered_sum *sums; 140 struct btrfs_ordered_sum *sums;
141 struct btrfs_sector_sum *sector_sum; 141 struct btrfs_sector_sum *sector_sum;
142 struct btrfs_ordered_extent *ordered;
142 char *data; 143 char *data;
143 struct bio_vec *bvec = bio->bi_io_vec; 144 struct bio_vec *bvec = bio->bi_io_vec;
144 int bio_index = 0; 145 int bio_index = 0;
146 unsigned long total_bytes = 0;
147 unsigned long this_sum_bytes = 0;
148 u64 offset;
145 149
146 WARN_ON(bio->bi_vcnt <= 0); 150 WARN_ON(bio->bi_vcnt <= 0);
147 sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS); 151 sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS);
148 if (!sums) 152 if (!sums)
149 return -ENOMEM; 153 return -ENOMEM;
150 *sums_ret = sums; 154
151 sector_sum = &sums->sums; 155 sector_sum = &sums->sums;
152 sums->file_offset = page_offset(bvec->bv_page); 156 sums->file_offset = page_offset(bvec->bv_page) + bvec->bv_offset;
153 sums->len = bio->bi_size; 157 sums->len = bio->bi_size;
154 INIT_LIST_HEAD(&sums->list); 158 INIT_LIST_HEAD(&sums->list);
159 ordered = btrfs_lookup_ordered_extent(inode, sums->file_offset);
160 BUG_ON(!ordered);
155 161
156 while(bio_index < bio->bi_vcnt) { 162 while(bio_index < bio->bi_vcnt) {
163 offset = page_offset(bvec->bv_page) + bvec->bv_offset;
164 if (offset >= ordered->file_offset + ordered->len) {
165 unsigned long bytes_left;
166 sums->len = this_sum_bytes;
167 this_sum_bytes = 0;
168 btrfs_add_ordered_sum(inode, ordered, sums);
169 btrfs_put_ordered_extent(ordered);
170
171 bytes_left = bio->bi_size - total_bytes;
172
173 sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
174 GFP_NOFS);
175 BUG_ON(!sums);
176 sector_sum = &sums->sums;
177 sums->len = bytes_left;
178 sums->file_offset = offset;
179 ordered = btrfs_lookup_ordered_extent(inode,
180 sums->file_offset);
181 BUG_ON(!ordered);
182 }
183
157 data = kmap_atomic(bvec->bv_page, KM_USER0); 184 data = kmap_atomic(bvec->bv_page, KM_USER0);
158 sector_sum->sum = ~(u32)0; 185 sector_sum->sum = ~(u32)0;
159 sector_sum->sum = btrfs_csum_data(root, 186 sector_sum->sum = btrfs_csum_data(root,
@@ -165,10 +192,18 @@ int btrfs_csum_one_bio(struct btrfs_root *root,
165 (char *)&sector_sum->sum); 192 (char *)&sector_sum->sum);
166 sector_sum->offset = page_offset(bvec->bv_page) + 193 sector_sum->offset = page_offset(bvec->bv_page) +
167 bvec->bv_offset; 194 bvec->bv_offset;
195
168 sector_sum++; 196 sector_sum++;
169 bio_index++; 197 bio_index++;
198 total_bytes += bvec->bv_len;
199 this_sum_bytes += bvec->bv_len;
170 bvec++; 200 bvec++;
171 } 201 }
202 btrfs_add_ordered_sum(inode, ordered, sums);
203 btrfs_put_ordered_extent(ordered);
204 if (total_bytes != bio->bi_size) {
205printk("warning, total bytes %lu bio size %u\n", total_bytes, bio->bi_size);
206 }
172 return 0; 207 return 0;
173} 208}
174 209