Blame view

fs/btrfs/file-item.c 22.4 KB
6cbd55707   Chris Mason   Btrfs: add GPLv2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * Copyright (C) 2007 Oracle.  All rights reserved.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public
   * License v2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public
   * License along with this program; if not, write to the
   * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   * Boston, MA 021110-1307, USA.
   */
065631f6d   Chris Mason   Btrfs: checksum f...
18
  #include <linux/bio.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
065631f6d   Chris Mason   Btrfs: checksum f...
20
21
  #include <linux/pagemap.h>
  #include <linux/highmem.h>
1e1d27017   Chris Mason   Btrfs: add inode ...
22
  #include "ctree.h"
dee26a9f7   Chris Mason   btrfs_get_block, ...
23
  #include "disk-io.h"
9f5fae2fe   Chris Mason   Btrfs: Add inode ...
24
  #include "transaction.h"
1de037a43   Chris Mason   Btrfs: fixup vari...
25
  #include "print-tree.h"
1e1d27017   Chris Mason   Btrfs: add inode ...
26

d397712bc   Chris Mason   Btrfs: Fix checkp...
27
  #define MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r) - \
607d432da   Josef Bacik   Btrfs: add suppor...
28
29
  				   sizeof(struct btrfs_item) * 2) / \
  				  size) - 1))
07d400a6d   Yan Zheng   Btrfs: tree loggi...
30
31
32
33
34
  
  #define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \
  				   sizeof(struct btrfs_ordered_sum)) / \
  				   sizeof(struct btrfs_sector_sum) * \
  				   (r)->sectorsize - (r)->sectorsize)
b18c66858   Chris Mason   Btrfs: progress o...
35
  int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
f2eb0a241   Sage Weil   Btrfs: Clone file...
36
37
38
  			     struct btrfs_root *root,
  			     u64 objectid, u64 pos,
  			     u64 disk_offset, u64 disk_num_bytes,
c8b978188   Chris Mason   Btrfs: Add zlib c...
39
40
  			     u64 num_bytes, u64 offset, u64 ram_bytes,
  			     u8 compression, u8 encryption, u16 other_encoding)
9f5fae2fe   Chris Mason   Btrfs: Add inode ...
41
  {
dee26a9f7   Chris Mason   btrfs_get_block, ...
42
43
44
  	int ret = 0;
  	struct btrfs_file_extent_item *item;
  	struct btrfs_key file_key;
5caf2a002   Chris Mason   Btrfs: dynamic al...
45
  	struct btrfs_path *path;
5f39d397d   Chris Mason   Btrfs: Create ext...
46
  	struct extent_buffer *leaf;
dee26a9f7   Chris Mason   btrfs_get_block, ...
47

5caf2a002   Chris Mason   Btrfs: dynamic al...
48
  	path = btrfs_alloc_path();
db5b493ac   Tsutomu Itoh   Btrfs: cleanup so...
49
50
  	if (!path)
  		return -ENOMEM;
dee26a9f7   Chris Mason   btrfs_get_block, ...
51
  	file_key.objectid = objectid;
b18c66858   Chris Mason   Btrfs: progress o...
52
  	file_key.offset = pos;
dee26a9f7   Chris Mason   btrfs_get_block, ...
53
  	btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
b9473439d   Chris Mason   Btrfs: leave btre...
54
  	path->leave_spinning = 1;
5caf2a002   Chris Mason   Btrfs: dynamic al...
55
  	ret = btrfs_insert_empty_item(trans, root, path, &file_key,
dee26a9f7   Chris Mason   btrfs_get_block, ...
56
  				      sizeof(*item));
54aa1f4df   Chris Mason   Btrfs: Audit call...
57
58
  	if (ret < 0)
  		goto out;
9773a7886   Chris Mason   Btrfs: byte offse...
59
  	BUG_ON(ret);
5f39d397d   Chris Mason   Btrfs: Create ext...
60
61
  	leaf = path->nodes[0];
  	item = btrfs_item_ptr(leaf, path->slots[0],
dee26a9f7   Chris Mason   btrfs_get_block, ...
62
  			      struct btrfs_file_extent_item);
f2eb0a241   Sage Weil   Btrfs: Clone file...
63
  	btrfs_set_file_extent_disk_bytenr(leaf, item, disk_offset);
db94535db   Chris Mason   Btrfs: Allow tree...
64
  	btrfs_set_file_extent_disk_num_bytes(leaf, item, disk_num_bytes);
f2eb0a241   Sage Weil   Btrfs: Clone file...
65
  	btrfs_set_file_extent_offset(leaf, item, offset);
db94535db   Chris Mason   Btrfs: Allow tree...
66
  	btrfs_set_file_extent_num_bytes(leaf, item, num_bytes);
c8b978188   Chris Mason   Btrfs: Add zlib c...
67
  	btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes);
5f39d397d   Chris Mason   Btrfs: Create ext...
68
69
  	btrfs_set_file_extent_generation(leaf, item, trans->transid);
  	btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
c8b978188   Chris Mason   Btrfs: Add zlib c...
70
71
72
  	btrfs_set_file_extent_compression(leaf, item, compression);
  	btrfs_set_file_extent_encryption(leaf, item, encryption);
  	btrfs_set_file_extent_other_encoding(leaf, item, other_encoding);
5f39d397d   Chris Mason   Btrfs: Create ext...
73
  	btrfs_mark_buffer_dirty(leaf);
54aa1f4df   Chris Mason   Btrfs: Audit call...
74
  out:
5caf2a002   Chris Mason   Btrfs: dynamic al...
75
  	btrfs_free_path(path);
54aa1f4df   Chris Mason   Btrfs: Audit call...
76
  	return ret;
9f5fae2fe   Chris Mason   Btrfs: Add inode ...
77
  }
dee26a9f7   Chris Mason   btrfs_get_block, ...
78

b18c66858   Chris Mason   Btrfs: progress o...
79
80
81
  struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
  					  struct btrfs_root *root,
  					  struct btrfs_path *path,
d20f7043f   Chris Mason   Btrfs: move data ...
82
  					  u64 bytenr, int cow)
6567e837d   Chris Mason   Btrfs: early work...
83
84
85
86
87
  {
  	int ret;
  	struct btrfs_key file_key;
  	struct btrfs_key found_key;
  	struct btrfs_csum_item *item;
5f39d397d   Chris Mason   Btrfs: Create ext...
88
  	struct extent_buffer *leaf;
6567e837d   Chris Mason   Btrfs: early work...
89
  	u64 csum_offset = 0;
6c41761fc   David Sterba   btrfs: separate s...
90
  	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
a429e5137   Chris Mason   Btrfs: working fi...
91
  	int csums_in_item;
6567e837d   Chris Mason   Btrfs: early work...
92

d20f7043f   Chris Mason   Btrfs: move data ...
93
94
95
  	file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
  	file_key.offset = bytenr;
  	btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY);
b18c66858   Chris Mason   Btrfs: progress o...
96
  	ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
6567e837d   Chris Mason   Btrfs: early work...
97
98
  	if (ret < 0)
  		goto fail;
5f39d397d   Chris Mason   Btrfs: Create ext...
99
  	leaf = path->nodes[0];
6567e837d   Chris Mason   Btrfs: early work...
100
101
  	if (ret > 0) {
  		ret = 1;
70b2befd0   Chris Mason   Btrfs: rework csu...
102
  		if (path->slots[0] == 0)
6567e837d   Chris Mason   Btrfs: early work...
103
104
  			goto fail;
  		path->slots[0]--;
5f39d397d   Chris Mason   Btrfs: Create ext...
105
  		btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
d20f7043f   Chris Mason   Btrfs: move data ...
106
  		if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY)
6567e837d   Chris Mason   Btrfs: early work...
107
  			goto fail;
d20f7043f   Chris Mason   Btrfs: move data ...
108
109
  
  		csum_offset = (bytenr - found_key.offset) >>
6567e837d   Chris Mason   Btrfs: early work...
110
  				root->fs_info->sb->s_blocksize_bits;
5f39d397d   Chris Mason   Btrfs: Create ext...
111
  		csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
607d432da   Josef Bacik   Btrfs: add suppor...
112
  		csums_in_item /= csum_size;
a429e5137   Chris Mason   Btrfs: working fi...
113
114
115
  
  		if (csum_offset >= csums_in_item) {
  			ret = -EFBIG;
6567e837d   Chris Mason   Btrfs: early work...
116
117
118
119
  			goto fail;
  		}
  	}
  	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
509659cde   Chris Mason   Btrfs: switch to ...
120
  	item = (struct btrfs_csum_item *)((unsigned char *)item +
607d432da   Josef Bacik   Btrfs: add suppor...
121
  					  csum_offset * csum_size);
6567e837d   Chris Mason   Btrfs: early work...
122
123
124
  	return item;
  fail:
  	if (ret > 0)
b18c66858   Chris Mason   Btrfs: progress o...
125
  		ret = -ENOENT;
6567e837d   Chris Mason   Btrfs: early work...
126
127
  	return ERR_PTR(ret);
  }
dee26a9f7   Chris Mason   btrfs_get_block, ...
128
129
130
  int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
  			     struct btrfs_root *root,
  			     struct btrfs_path *path, u64 objectid,
9773a7886   Chris Mason   Btrfs: byte offse...
131
  			     u64 offset, int mod)
dee26a9f7   Chris Mason   btrfs_get_block, ...
132
133
134
135
136
137
138
  {
  	int ret;
  	struct btrfs_key file_key;
  	int ins_len = mod < 0 ? -1 : 0;
  	int cow = mod != 0;
  
  	file_key.objectid = objectid;
70b2befd0   Chris Mason   Btrfs: rework csu...
139
  	file_key.offset = offset;
dee26a9f7   Chris Mason   btrfs_get_block, ...
140
141
142
143
  	btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
  	ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
  	return ret;
  }
f254e52c1   Chris Mason   Btrfs: verify csu...
144

17d217fe9   Yan Zheng   Btrfs: fix nodata...
145

4b46fce23   Josef Bacik   Btrfs: add basic ...
146
147
148
  static int __btrfs_lookup_bio_sums(struct btrfs_root *root,
  				   struct inode *inode, struct bio *bio,
  				   u64 logical_offset, u32 *dst, int dio)
61b494401   Chris Mason   Btrfs: Fix stream...
149
150
151
152
  {
  	u32 sum;
  	struct bio_vec *bvec = bio->bi_io_vec;
  	int bio_index = 0;
4b46fce23   Josef Bacik   Btrfs: add basic ...
153
  	u64 offset = 0;
61b494401   Chris Mason   Btrfs: Fix stream...
154
155
  	u64 item_start_offset = 0;
  	u64 item_last_offset = 0;
d20f7043f   Chris Mason   Btrfs: move data ...
156
  	u64 disk_bytenr;
61b494401   Chris Mason   Btrfs: Fix stream...
157
  	u32 diff;
6c41761fc   David Sterba   btrfs: separate s...
158
  	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
61b494401   Chris Mason   Btrfs: Fix stream...
159
160
161
162
163
164
  	int ret;
  	struct btrfs_path *path;
  	struct btrfs_csum_item *item = NULL;
  	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
  
  	path = btrfs_alloc_path();
c2db1073f   Tsutomu Itoh   Btrfs: check retu...
165
166
  	if (!path)
  		return -ENOMEM;
4d1b5fb4d   Chris Mason   Btrfs: Lookup rea...
167
168
  	if (bio->bi_size > PAGE_CACHE_SIZE * 8)
  		path->reada = 2;
61b494401   Chris Mason   Btrfs: Fix stream...
169
170
  
  	WARN_ON(bio->bi_vcnt <= 0);
2cf8572da   Chris Mason   Btrfs: use the co...
171
172
173
174
175
176
  	/*
  	 * the free space stuff is only read when it hasn't been
  	 * updated in the current transaction.  So, we can safely
  	 * read from the commit root and sidestep a nasty deadlock
  	 * between reading the free space cache and updating the csum tree.
  	 */
ddf23b3fc   Josef Bacik   Btrfs: skip locki...
177
  	if (btrfs_is_free_space_inode(root, inode)) {
2cf8572da   Chris Mason   Btrfs: use the co...
178
  		path->search_commit_root = 1;
ddf23b3fc   Josef Bacik   Btrfs: skip locki...
179
180
  		path->skip_locking = 1;
  	}
2cf8572da   Chris Mason   Btrfs: use the co...
181

d20f7043f   Chris Mason   Btrfs: move data ...
182
  	disk_bytenr = (u64)bio->bi_sector << 9;
4b46fce23   Josef Bacik   Btrfs: add basic ...
183
184
  	if (dio)
  		offset = logical_offset;
d397712bc   Chris Mason   Btrfs: Fix checkp...
185
  	while (bio_index < bio->bi_vcnt) {
4b46fce23   Josef Bacik   Btrfs: add basic ...
186
187
  		if (!dio)
  			offset = page_offset(bvec->bv_page) + bvec->bv_offset;
d20f7043f   Chris Mason   Btrfs: move data ...
188
  		ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum);
61b494401   Chris Mason   Btrfs: Fix stream...
189
190
  		if (ret == 0)
  			goto found;
d20f7043f   Chris Mason   Btrfs: move data ...
191
192
  		if (!item || disk_bytenr < item_start_offset ||
  		    disk_bytenr >= item_last_offset) {
61b494401   Chris Mason   Btrfs: Fix stream...
193
194
195
196
  			struct btrfs_key found_key;
  			u32 item_size;
  
  			if (item)
b3b4aa74b   David Sterba   btrfs: drop unuse...
197
  				btrfs_release_path(path);
d20f7043f   Chris Mason   Btrfs: move data ...
198
199
  			item = btrfs_lookup_csum(NULL, root->fs_info->csum_root,
  						 path, disk_bytenr, 0);
61b494401   Chris Mason   Btrfs: Fix stream...
200
201
202
203
204
  			if (IS_ERR(item)) {
  				ret = PTR_ERR(item);
  				if (ret == -ENOENT || ret == -EFBIG)
  					ret = 0;
  				sum = 0;
17d217fe9   Yan Zheng   Btrfs: fix nodata...
205
206
207
208
209
210
  				if (BTRFS_I(inode)->root->root_key.objectid ==
  				    BTRFS_DATA_RELOC_TREE_OBJECTID) {
  					set_extent_bits(io_tree, offset,
  						offset + bvec->bv_len - 1,
  						EXTENT_NODATASUM, GFP_NOFS);
  				} else {
d397712bc   Chris Mason   Btrfs: Fix checkp...
211
  					printk(KERN_INFO "btrfs no csum found "
33345d015   Li Zefan   Btrfs: Always use...
212
213
214
215
  					       "for inode %llu start %llu
  ",
  					       (unsigned long long)
  					       btrfs_ino(inode),
17d217fe9   Yan Zheng   Btrfs: fix nodata...
216
217
  					       (unsigned long long)offset);
  				}
6dab81574   Chris Mason   Btrfs: Hold csum ...
218
  				item = NULL;
b3b4aa74b   David Sterba   btrfs: drop unuse...
219
  				btrfs_release_path(path);
61b494401   Chris Mason   Btrfs: Fix stream...
220
221
222
223
224
225
226
227
228
  				goto found;
  			}
  			btrfs_item_key_to_cpu(path->nodes[0], &found_key,
  					      path->slots[0]);
  
  			item_start_offset = found_key.offset;
  			item_size = btrfs_item_size_nr(path->nodes[0],
  						       path->slots[0]);
  			item_last_offset = item_start_offset +
607d432da   Josef Bacik   Btrfs: add suppor...
229
  				(item_size / csum_size) *
61b494401   Chris Mason   Btrfs: Fix stream...
230
231
232
233
234
235
236
237
  				root->sectorsize;
  			item = btrfs_item_ptr(path->nodes[0], path->slots[0],
  					      struct btrfs_csum_item);
  		}
  		/*
  		 * this byte range must be able to fit inside
  		 * a single leaf so it will also fit inside a u32
  		 */
d20f7043f   Chris Mason   Btrfs: move data ...
238
  		diff = disk_bytenr - item_start_offset;
61b494401   Chris Mason   Btrfs: Fix stream...
239
  		diff = diff / root->sectorsize;
607d432da   Josef Bacik   Btrfs: add suppor...
240
  		diff = diff * csum_size;
61b494401   Chris Mason   Btrfs: Fix stream...
241
242
  
  		read_extent_buffer(path->nodes[0], &sum,
3de9d6b64   Chris Mason   btrfs_lookup_bio_...
243
  				   ((unsigned long)item) + diff,
607d432da   Josef Bacik   Btrfs: add suppor...
244
  				   csum_size);
61b494401   Chris Mason   Btrfs: Fix stream...
245
  found:
d20f7043f   Chris Mason   Btrfs: move data ...
246
247
248
249
250
  		if (dst)
  			*dst++ = sum;
  		else
  			set_state_private(io_tree, offset, sum);
  		disk_bytenr += bvec->bv_len;
4b46fce23   Josef Bacik   Btrfs: add basic ...
251
  		offset += bvec->bv_len;
61b494401   Chris Mason   Btrfs: Fix stream...
252
253
254
255
256
257
  		bio_index++;
  		bvec++;
  	}
  	btrfs_free_path(path);
  	return 0;
  }
4b46fce23   Josef Bacik   Btrfs: add basic ...
258
259
260
261
262
263
264
265
266
267
268
  int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
  			  struct bio *bio, u32 *dst)
  {
  	return __btrfs_lookup_bio_sums(root, inode, bio, 0, dst, 0);
  }
  
  int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
  			      struct bio *bio, u64 offset, u32 *dst)
  {
  	return __btrfs_lookup_bio_sums(root, inode, bio, offset, dst, 1);
  }
17d217fe9   Yan Zheng   Btrfs: fix nodata...
269
  int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
a2de733c7   Arne Jansen   btrfs: scrub
270
  			     struct list_head *list, int search_commit)
17d217fe9   Yan Zheng   Btrfs: fix nodata...
271
272
273
274
275
276
277
278
279
280
281
  {
  	struct btrfs_key key;
  	struct btrfs_path *path;
  	struct extent_buffer *leaf;
  	struct btrfs_ordered_sum *sums;
  	struct btrfs_sector_sum *sector_sum;
  	struct btrfs_csum_item *item;
  	unsigned long offset;
  	int ret;
  	size_t size;
  	u64 csum_end;
6c41761fc   David Sterba   btrfs: separate s...
282
  	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
17d217fe9   Yan Zheng   Btrfs: fix nodata...
283
284
  
  	path = btrfs_alloc_path();
d8926bb3b   Mark Fasheh   btrfs: don't BUG_...
285
286
  	if (!path)
  		return -ENOMEM;
17d217fe9   Yan Zheng   Btrfs: fix nodata...
287

a2de733c7   Arne Jansen   btrfs: scrub
288
289
290
291
292
  	if (search_commit) {
  		path->skip_locking = 1;
  		path->reada = 2;
  		path->search_commit_root = 1;
  	}
17d217fe9   Yan Zheng   Btrfs: fix nodata...
293
294
295
  	key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
  	key.offset = start;
  	key.type = BTRFS_EXTENT_CSUM_KEY;
07d400a6d   Yan Zheng   Btrfs: tree loggi...
296
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
17d217fe9   Yan Zheng   Btrfs: fix nodata...
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  	if (ret < 0)
  		goto fail;
  	if (ret > 0 && path->slots[0] > 0) {
  		leaf = path->nodes[0];
  		btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
  		if (key.objectid == BTRFS_EXTENT_CSUM_OBJECTID &&
  		    key.type == BTRFS_EXTENT_CSUM_KEY) {
  			offset = (start - key.offset) >>
  				 root->fs_info->sb->s_blocksize_bits;
  			if (offset * csum_size <
  			    btrfs_item_size_nr(leaf, path->slots[0] - 1))
  				path->slots[0]--;
  		}
  	}
  
  	while (start <= end) {
  		leaf = path->nodes[0];
  		if (path->slots[0] >= btrfs_header_nritems(leaf)) {
07d400a6d   Yan Zheng   Btrfs: tree loggi...
315
  			ret = btrfs_next_leaf(root, path);
17d217fe9   Yan Zheng   Btrfs: fix nodata...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  			if (ret < 0)
  				goto fail;
  			if (ret > 0)
  				break;
  			leaf = path->nodes[0];
  		}
  
  		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
  		if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
  		    key.type != BTRFS_EXTENT_CSUM_KEY)
  			break;
  
  		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
  		if (key.offset > end)
  			break;
  
  		if (key.offset > start)
  			start = key.offset;
  
  		size = btrfs_item_size_nr(leaf, path->slots[0]);
  		csum_end = key.offset + (size / csum_size) * root->sectorsize;
87b29b208   Yan Zheng   Btrfs: properly c...
337
338
339
340
  		if (csum_end <= start) {
  			path->slots[0]++;
  			continue;
  		}
17d217fe9   Yan Zheng   Btrfs: fix nodata...
341

07d400a6d   Yan Zheng   Btrfs: tree loggi...
342
  		csum_end = min(csum_end, end + 1);
17d217fe9   Yan Zheng   Btrfs: fix nodata...
343
344
  		item = btrfs_item_ptr(path->nodes[0], path->slots[0],
  				      struct btrfs_csum_item);
07d400a6d   Yan Zheng   Btrfs: tree loggi...
345
346
347
348
349
350
  		while (start < csum_end) {
  			size = min_t(size_t, csum_end - start,
  					MAX_ORDERED_SUM_BYTES(root));
  			sums = kzalloc(btrfs_ordered_sum_size(root, size),
  					GFP_NOFS);
  			BUG_ON(!sums);
17d217fe9   Yan Zheng   Btrfs: fix nodata...
351

07d400a6d   Yan Zheng   Btrfs: tree loggi...
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
  			sector_sum = sums->sums;
  			sums->bytenr = start;
  			sums->len = size;
  
  			offset = (start - key.offset) >>
  				root->fs_info->sb->s_blocksize_bits;
  			offset *= csum_size;
  
  			while (size > 0) {
  				read_extent_buffer(path->nodes[0],
  						&sector_sum->sum,
  						((unsigned long)item) +
  						offset, csum_size);
  				sector_sum->bytenr = start;
  
  				size -= root->sectorsize;
  				start += root->sectorsize;
  				offset += csum_size;
  				sector_sum++;
  			}
  			list_add_tail(&sums->list, list);
  		}
17d217fe9   Yan Zheng   Btrfs: fix nodata...
374
375
376
377
378
379
380
  		path->slots[0]++;
  	}
  	ret = 0;
  fail:
  	btrfs_free_path(path);
  	return ret;
  }
3edf7d33f   Chris Mason   Btrfs: Handle dat...
381
  int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode,
d20f7043f   Chris Mason   Btrfs: move data ...
382
  		       struct bio *bio, u64 file_start, int contig)
e015640f9   Chris Mason   Btrfs: Write bio ...
383
  {
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
384
385
  	struct btrfs_ordered_sum *sums;
  	struct btrfs_sector_sum *sector_sum;
3edf7d33f   Chris Mason   Btrfs: Handle dat...
386
  	struct btrfs_ordered_extent *ordered;
e015640f9   Chris Mason   Btrfs: Write bio ...
387
388
389
  	char *data;
  	struct bio_vec *bvec = bio->bi_io_vec;
  	int bio_index = 0;
3edf7d33f   Chris Mason   Btrfs: Handle dat...
390
391
392
  	unsigned long total_bytes = 0;
  	unsigned long this_sum_bytes = 0;
  	u64 offset;
d20f7043f   Chris Mason   Btrfs: move data ...
393
  	u64 disk_bytenr;
e015640f9   Chris Mason   Btrfs: Write bio ...
394

e6dcd2dc9   Chris Mason   Btrfs: New data=o...
395
396
  	WARN_ON(bio->bi_vcnt <= 0);
  	sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS);
e015640f9   Chris Mason   Btrfs: Write bio ...
397
398
  	if (!sums)
  		return -ENOMEM;
3edf7d33f   Chris Mason   Btrfs: Handle dat...
399

ed98b56a6   Chris Mason   Btrfs: Take the c...
400
  	sector_sum = sums->sums;
d20f7043f   Chris Mason   Btrfs: move data ...
401
  	disk_bytenr = (u64)bio->bi_sector << 9;
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
402
403
  	sums->len = bio->bi_size;
  	INIT_LIST_HEAD(&sums->list);
d20f7043f   Chris Mason   Btrfs: move data ...
404
405
406
407
408
409
410
  
  	if (contig)
  		offset = file_start;
  	else
  		offset = page_offset(bvec->bv_page) + bvec->bv_offset;
  
  	ordered = btrfs_lookup_ordered_extent(inode, offset);
3edf7d33f   Chris Mason   Btrfs: Handle dat...
411
  	BUG_ON(!ordered);
d20f7043f   Chris Mason   Btrfs: move data ...
412
  	sums->bytenr = ordered->start;
e015640f9   Chris Mason   Btrfs: Write bio ...
413

d397712bc   Chris Mason   Btrfs: Fix checkp...
414
  	while (bio_index < bio->bi_vcnt) {
d20f7043f   Chris Mason   Btrfs: move data ...
415
416
417
418
419
  		if (!contig)
  			offset = page_offset(bvec->bv_page) + bvec->bv_offset;
  
  		if (!contig && (offset >= ordered->file_offset + ordered->len ||
  		    offset < ordered->file_offset)) {
3edf7d33f   Chris Mason   Btrfs: Handle dat...
420
421
422
423
424
425
426
427
428
429
430
  			unsigned long bytes_left;
  			sums->len = this_sum_bytes;
  			this_sum_bytes = 0;
  			btrfs_add_ordered_sum(inode, ordered, sums);
  			btrfs_put_ordered_extent(ordered);
  
  			bytes_left = bio->bi_size - total_bytes;
  
  			sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left),
  				       GFP_NOFS);
  			BUG_ON(!sums);
ed98b56a6   Chris Mason   Btrfs: Take the c...
431
  			sector_sum = sums->sums;
3edf7d33f   Chris Mason   Btrfs: Handle dat...
432
  			sums->len = bytes_left;
d20f7043f   Chris Mason   Btrfs: move data ...
433
  			ordered = btrfs_lookup_ordered_extent(inode, offset);
3edf7d33f   Chris Mason   Btrfs: Handle dat...
434
  			BUG_ON(!ordered);
d20f7043f   Chris Mason   Btrfs: move data ...
435
  			sums->bytenr = ordered->start;
3edf7d33f   Chris Mason   Btrfs: Handle dat...
436
  		}
e015640f9   Chris Mason   Btrfs: Write bio ...
437
  		data = kmap_atomic(bvec->bv_page, KM_USER0);
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
438
439
440
441
442
  		sector_sum->sum = ~(u32)0;
  		sector_sum->sum = btrfs_csum_data(root,
  						  data + bvec->bv_offset,
  						  sector_sum->sum,
  						  bvec->bv_len);
e015640f9   Chris Mason   Btrfs: Write bio ...
443
  		kunmap_atomic(data, KM_USER0);
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
444
445
  		btrfs_csum_final(sector_sum->sum,
  				 (char *)&sector_sum->sum);
d20f7043f   Chris Mason   Btrfs: move data ...
446
  		sector_sum->bytenr = disk_bytenr;
ed98b56a6   Chris Mason   Btrfs: Take the c...
447

e6dcd2dc9   Chris Mason   Btrfs: New data=o...
448
  		sector_sum++;
e015640f9   Chris Mason   Btrfs: Write bio ...
449
  		bio_index++;
3edf7d33f   Chris Mason   Btrfs: Handle dat...
450
451
  		total_bytes += bvec->bv_len;
  		this_sum_bytes += bvec->bv_len;
d20f7043f   Chris Mason   Btrfs: move data ...
452
453
  		disk_bytenr += bvec->bv_len;
  		offset += bvec->bv_len;
e015640f9   Chris Mason   Btrfs: Write bio ...
454
455
  		bvec++;
  	}
ed98b56a6   Chris Mason   Btrfs: Take the c...
456
  	this_sum_bytes = 0;
3edf7d33f   Chris Mason   Btrfs: Handle dat...
457
458
  	btrfs_add_ordered_sum(inode, ordered, sums);
  	btrfs_put_ordered_extent(ordered);
e015640f9   Chris Mason   Btrfs: Write bio ...
459
460
  	return 0;
  }
459931eca   Chris Mason   Btrfs: Delete csu...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
  /*
   * helper function for csum removal, this expects the
   * key to describe the csum pointed to by the path, and it expects
   * the csum to overlap the range [bytenr, len]
   *
   * The csum should not be entirely contained in the range and the
   * range should not be entirely contained in the csum.
   *
   * This calls btrfs_truncate_item with the correct args based on the
   * overlap, and fixes up the key as required.
   */
  static noinline int truncate_one_csum(struct btrfs_trans_handle *trans,
  				      struct btrfs_root *root,
  				      struct btrfs_path *path,
  				      struct btrfs_key *key,
  				      u64 bytenr, u64 len)
  {
  	struct extent_buffer *leaf;
6c41761fc   David Sterba   btrfs: separate s...
479
  	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
459931eca   Chris Mason   Btrfs: Delete csu...
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
  	u64 csum_end;
  	u64 end_byte = bytenr + len;
  	u32 blocksize_bits = root->fs_info->sb->s_blocksize_bits;
  	int ret;
  
  	leaf = path->nodes[0];
  	csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
  	csum_end <<= root->fs_info->sb->s_blocksize_bits;
  	csum_end += key->offset;
  
  	if (key->offset < bytenr && csum_end <= end_byte) {
  		/*
  		 *         [ bytenr - len ]
  		 *         [   ]
  		 *   [csum     ]
  		 *   A simple truncate off the end of the item
  		 */
  		u32 new_size = (bytenr - key->offset) >> blocksize_bits;
  		new_size *= csum_size;
  		ret = btrfs_truncate_item(trans, root, path, new_size, 1);
459931eca   Chris Mason   Btrfs: Delete csu...
500
501
502
503
504
505
506
507
508
509
510
511
  	} else if (key->offset >= bytenr && csum_end > end_byte &&
  		   end_byte > key->offset) {
  		/*
  		 *         [ bytenr - len ]
  		 *                 [ ]
  		 *                 [csum     ]
  		 * we need to truncate from the beginning of the csum
  		 */
  		u32 new_size = (csum_end - end_byte) >> blocksize_bits;
  		new_size *= csum_size;
  
  		ret = btrfs_truncate_item(trans, root, path, new_size, 0);
459931eca   Chris Mason   Btrfs: Delete csu...
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
  
  		key->offset = end_byte;
  		ret = btrfs_set_item_key_safe(trans, root, path, key);
  		BUG_ON(ret);
  	} else {
  		BUG();
  	}
  	return 0;
  }
  
  /*
   * deletes the csum items from the csum tree for a given
   * range of bytes.
   */
  int btrfs_del_csums(struct btrfs_trans_handle *trans,
  		    struct btrfs_root *root, u64 bytenr, u64 len)
  {
  	struct btrfs_path *path;
  	struct btrfs_key key;
  	u64 end_byte = bytenr + len;
  	u64 csum_end;
  	struct extent_buffer *leaf;
  	int ret;
6c41761fc   David Sterba   btrfs: separate s...
535
  	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
459931eca   Chris Mason   Btrfs: Delete csu...
536
537
538
539
540
  	int blocksize_bits = root->fs_info->sb->s_blocksize_bits;
  
  	root = root->fs_info->csum_root;
  
  	path = btrfs_alloc_path();
2a29edc6b   liubo   btrfs: fix severa...
541
542
  	if (!path)
  		return -ENOMEM;
459931eca   Chris Mason   Btrfs: Delete csu...
543

d397712bc   Chris Mason   Btrfs: Fix checkp...
544
  	while (1) {
459931eca   Chris Mason   Btrfs: Delete csu...
545
546
547
  		key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
  		key.offset = end_byte - 1;
  		key.type = BTRFS_EXTENT_CSUM_KEY;
b9473439d   Chris Mason   Btrfs: leave btre...
548
  		path->leave_spinning = 1;
459931eca   Chris Mason   Btrfs: Delete csu...
549
550
551
  		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
  		if (ret > 0) {
  			if (path->slots[0] == 0)
65a246c5f   Tsutomu Itoh   Btrfs: return err...
552
  				break;
459931eca   Chris Mason   Btrfs: Delete csu...
553
  			path->slots[0]--;
ad0397a7a   Josef Bacik   Btrfs: do error c...
554
  		} else if (ret < 0) {
65a246c5f   Tsutomu Itoh   Btrfs: return err...
555
  			break;
459931eca   Chris Mason   Btrfs: Delete csu...
556
  		}
ad0397a7a   Josef Bacik   Btrfs: do error c...
557

459931eca   Chris Mason   Btrfs: Delete csu...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
  		leaf = path->nodes[0];
  		btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
  
  		if (key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
  		    key.type != BTRFS_EXTENT_CSUM_KEY) {
  			break;
  		}
  
  		if (key.offset >= end_byte)
  			break;
  
  		csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
  		csum_end <<= blocksize_bits;
  		csum_end += key.offset;
  
  		/* this csum ends before we start, we're done */
  		if (csum_end <= bytenr)
  			break;
  
  		/* delete the entire item, it is inside our range */
  		if (key.offset >= bytenr && csum_end <= end_byte) {
  			ret = btrfs_del_item(trans, root, path);
65a246c5f   Tsutomu Itoh   Btrfs: return err...
580
581
  			if (ret)
  				goto out;
dcbdd4dcb   Chris Mason   Btrfs: delete che...
582
583
  			if (key.offset == bytenr)
  				break;
459931eca   Chris Mason   Btrfs: Delete csu...
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
  		} else if (key.offset < bytenr && csum_end > end_byte) {
  			unsigned long offset;
  			unsigned long shift_len;
  			unsigned long item_offset;
  			/*
  			 *        [ bytenr - len ]
  			 *     [csum                ]
  			 *
  			 * Our bytes are in the middle of the csum,
  			 * we need to split this item and insert a new one.
  			 *
  			 * But we can't drop the path because the
  			 * csum could change, get removed, extended etc.
  			 *
  			 * The trick here is the max size of a csum item leaves
  			 * enough room in the tree block for a single
  			 * item header.  So, we split the item in place,
  			 * adding a new header pointing to the existing
  			 * bytes.  Then we loop around again and we have
  			 * a nicely formed csum item that we can neatly
  			 * truncate.
  			 */
  			offset = (bytenr - key.offset) >> blocksize_bits;
  			offset *= csum_size;
  
  			shift_len = (len >> blocksize_bits) * csum_size;
  
  			item_offset = btrfs_item_ptr_offset(leaf,
  							    path->slots[0]);
  
  			memset_extent_buffer(leaf, 0, item_offset + offset,
  					     shift_len);
  			key.offset = bytenr;
  
  			/*
  			 * btrfs_split_item returns -EAGAIN when the
  			 * item changed size or key
  			 */
  			ret = btrfs_split_item(trans, root, path, &key, offset);
  			BUG_ON(ret && ret != -EAGAIN);
  
  			key.offset = end_byte - 1;
  		} else {
  			ret = truncate_one_csum(trans, root, path,
  						&key, bytenr, len);
  			BUG_ON(ret);
dcbdd4dcb   Chris Mason   Btrfs: delete che...
630
631
  			if (key.offset < bytenr)
  				break;
459931eca   Chris Mason   Btrfs: Delete csu...
632
  		}
b3b4aa74b   David Sterba   btrfs: drop unuse...
633
  		btrfs_release_path(path);
459931eca   Chris Mason   Btrfs: Delete csu...
634
  	}
65a246c5f   Tsutomu Itoh   Btrfs: return err...
635
  	ret = 0;
459931eca   Chris Mason   Btrfs: Delete csu...
636
637
  out:
  	btrfs_free_path(path);
65a246c5f   Tsutomu Itoh   Btrfs: return err...
638
  	return ret;
459931eca   Chris Mason   Btrfs: Delete csu...
639
  }
065631f6d   Chris Mason   Btrfs: checksum f...
640
  int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
d20f7043f   Chris Mason   Btrfs: move data ...
641
  			   struct btrfs_root *root,
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
642
  			   struct btrfs_ordered_sum *sums)
f254e52c1   Chris Mason   Btrfs: verify csu...
643
  {
d20f7043f   Chris Mason   Btrfs: move data ...
644
  	u64 bytenr;
f254e52c1   Chris Mason   Btrfs: verify csu...
645
646
  	int ret;
  	struct btrfs_key file_key;
6567e837d   Chris Mason   Btrfs: early work...
647
  	struct btrfs_key found_key;
065631f6d   Chris Mason   Btrfs: checksum f...
648
  	u64 next_offset;
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
649
  	u64 total_bytes = 0;
065631f6d   Chris Mason   Btrfs: checksum f...
650
  	int found_next;
5caf2a002   Chris Mason   Btrfs: dynamic al...
651
  	struct btrfs_path *path;
f254e52c1   Chris Mason   Btrfs: verify csu...
652
  	struct btrfs_csum_item *item;
065631f6d   Chris Mason   Btrfs: checksum f...
653
  	struct btrfs_csum_item *item_end;
ff79f8190   Chris Mason   Btrfs: Add back f...
654
  	struct extent_buffer *leaf = NULL;
6567e837d   Chris Mason   Btrfs: early work...
655
  	u64 csum_offset;
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
656
  	struct btrfs_sector_sum *sector_sum;
f578d4bd7   Chris Mason   Btrfs: Optimize c...
657
658
  	u32 nritems;
  	u32 ins_size;
6c41761fc   David Sterba   btrfs: separate s...
659
  	u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
6e92f5e65   Chris Mason   Btrfs: While doin...
660

5caf2a002   Chris Mason   Btrfs: dynamic al...
661
  	path = btrfs_alloc_path();
d8926bb3b   Mark Fasheh   btrfs: don't BUG_...
662
663
  	if (!path)
  		return -ENOMEM;
ed98b56a6   Chris Mason   Btrfs: Take the c...
664
  	sector_sum = sums->sums;
065631f6d   Chris Mason   Btrfs: checksum f...
665
666
667
  again:
  	next_offset = (u64)-1;
  	found_next = 0;
d20f7043f   Chris Mason   Btrfs: move data ...
668
669
670
671
  	file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
  	file_key.offset = sector_sum->bytenr;
  	bytenr = sector_sum->bytenr;
  	btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY);
a429e5137   Chris Mason   Btrfs: working fi...
672

d20f7043f   Chris Mason   Btrfs: move data ...
673
  	item = btrfs_lookup_csum(trans, root, path, sector_sum->bytenr, 1);
ff79f8190   Chris Mason   Btrfs: Add back f...
674
675
  	if (!IS_ERR(item)) {
  		leaf = path->nodes[0];
639cb5867   Chris Mason   Btrfs: Fix variab...
676
  		ret = 0;
a429e5137   Chris Mason   Btrfs: working fi...
677
  		goto found;
ff79f8190   Chris Mason   Btrfs: Add back f...
678
  	}
a429e5137   Chris Mason   Btrfs: working fi...
679
  	ret = PTR_ERR(item);
4a500fd17   Yan, Zheng   Btrfs: Metadata E...
680
681
  	if (ret != -EFBIG && ret != -ENOENT)
  		goto fail_unlock;
a429e5137   Chris Mason   Btrfs: working fi...
682
683
684
  	if (ret == -EFBIG) {
  		u32 item_size;
  		/* we found one, but it isn't big enough yet */
5f39d397d   Chris Mason   Btrfs: Create ext...
685
686
  		leaf = path->nodes[0];
  		item_size = btrfs_item_size_nr(leaf, path->slots[0]);
607d432da   Josef Bacik   Btrfs: add suppor...
687
688
  		if ((item_size / csum_size) >=
  		    MAX_CSUM_ITEMS(root, csum_size)) {
a429e5137   Chris Mason   Btrfs: working fi...
689
690
691
692
  			/* already at max size, make a new one */
  			goto insert;
  		}
  	} else {
f578d4bd7   Chris Mason   Btrfs: Optimize c...
693
  		int slot = path->slots[0] + 1;
a429e5137   Chris Mason   Btrfs: working fi...
694
  		/* we didn't find a csum item, insert one */
f578d4bd7   Chris Mason   Btrfs: Optimize c...
695
696
697
  		nritems = btrfs_header_nritems(path->nodes[0]);
  		if (path->slots[0] >= nritems - 1) {
  			ret = btrfs_next_leaf(root, path);
b56baf5be   Yan   Minor fix for btr...
698
  			if (ret == 1)
f578d4bd7   Chris Mason   Btrfs: Optimize c...
699
  				found_next = 1;
b56baf5be   Yan   Minor fix for btr...
700
  			if (ret != 0)
f578d4bd7   Chris Mason   Btrfs: Optimize c...
701
  				goto insert;
b56baf5be   Yan   Minor fix for btr...
702
  			slot = 0;
f578d4bd7   Chris Mason   Btrfs: Optimize c...
703
704
  		}
  		btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot);
d20f7043f   Chris Mason   Btrfs: move data ...
705
706
  		if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
  		    found_key.type != BTRFS_EXTENT_CSUM_KEY) {
f578d4bd7   Chris Mason   Btrfs: Optimize c...
707
708
709
710
711
  			found_next = 1;
  			goto insert;
  		}
  		next_offset = found_key.offset;
  		found_next = 1;
a429e5137   Chris Mason   Btrfs: working fi...
712
713
714
715
716
717
718
  		goto insert;
  	}
  
  	/*
  	 * at this point, we know the tree has an item, but it isn't big
  	 * enough yet to put our csum in.  Grow it
  	 */
b3b4aa74b   David Sterba   btrfs: drop unuse...
719
  	btrfs_release_path(path);
6567e837d   Chris Mason   Btrfs: early work...
720
  	ret = btrfs_search_slot(trans, root, &file_key, path,
607d432da   Josef Bacik   Btrfs: add suppor...
721
  				csum_size, 1);
6567e837d   Chris Mason   Btrfs: early work...
722
  	if (ret < 0)
53863232e   Chris Mason   Btrfs: Lower cont...
723
  		goto fail_unlock;
459931eca   Chris Mason   Btrfs: Delete csu...
724
725
726
727
728
  
  	if (ret > 0) {
  		if (path->slots[0] == 0)
  			goto insert;
  		path->slots[0]--;
6567e837d   Chris Mason   Btrfs: early work...
729
  	}
459931eca   Chris Mason   Btrfs: Delete csu...
730

5f39d397d   Chris Mason   Btrfs: Create ext...
731
732
  	leaf = path->nodes[0];
  	btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
d20f7043f   Chris Mason   Btrfs: move data ...
733
  	csum_offset = (bytenr - found_key.offset) >>
6567e837d   Chris Mason   Btrfs: early work...
734
  			root->fs_info->sb->s_blocksize_bits;
459931eca   Chris Mason   Btrfs: Delete csu...
735

d20f7043f   Chris Mason   Btrfs: move data ...
736
737
  	if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY ||
  	    found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
607d432da   Josef Bacik   Btrfs: add suppor...
738
  	    csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) {
6567e837d   Chris Mason   Btrfs: early work...
739
740
  		goto insert;
  	}
459931eca   Chris Mason   Btrfs: Delete csu...
741

5f39d397d   Chris Mason   Btrfs: Create ext...
742
  	if (csum_offset >= btrfs_item_size_nr(leaf, path->slots[0]) /
607d432da   Josef Bacik   Btrfs: add suppor...
743
744
  	    csum_size) {
  		u32 diff = (csum_offset + 1) * csum_size;
459931eca   Chris Mason   Btrfs: Delete csu...
745
746
747
748
749
750
751
  
  		/*
  		 * is the item big enough already?  we dropped our lock
  		 * before and need to recheck
  		 */
  		if (diff < btrfs_item_size_nr(leaf, path->slots[0]))
  			goto csum;
5f39d397d   Chris Mason   Btrfs: Create ext...
752
  		diff = diff - btrfs_item_size_nr(leaf, path->slots[0]);
d397712bc   Chris Mason   Btrfs: Fix checkp...
753
  		if (diff != csum_size)
3a6863756   Chris Mason   Btrfs: sparse files!
754
  			goto insert;
459931eca   Chris Mason   Btrfs: Delete csu...
755

a429e5137   Chris Mason   Btrfs: working fi...
756
  		ret = btrfs_extend_item(trans, root, path, diff);
6567e837d   Chris Mason   Btrfs: early work...
757
758
759
760
  		goto csum;
  	}
  
  insert:
b3b4aa74b   David Sterba   btrfs: drop unuse...
761
  	btrfs_release_path(path);
6567e837d   Chris Mason   Btrfs: early work...
762
  	csum_offset = 0;
f578d4bd7   Chris Mason   Btrfs: Optimize c...
763
  	if (found_next) {
d20f7043f   Chris Mason   Btrfs: move data ...
764
765
766
  		u64 tmp = total_bytes + root->sectorsize;
  		u64 next_sector = sector_sum->bytenr;
  		struct btrfs_sector_sum *next = sector_sum + 1;
d397712bc   Chris Mason   Btrfs: Fix checkp...
767
  		while (tmp < sums->len) {
d20f7043f   Chris Mason   Btrfs: move data ...
768
769
770
771
772
773
774
  			if (next_sector + root->sectorsize != next->bytenr)
  				break;
  			tmp += root->sectorsize;
  			next_sector = next->bytenr;
  			next++;
  		}
  		tmp = min(tmp, next_offset - file_key.offset);
f578d4bd7   Chris Mason   Btrfs: Optimize c...
775
776
  		tmp >>= root->fs_info->sb->s_blocksize_bits;
  		tmp = max((u64)1, tmp);
607d432da   Josef Bacik   Btrfs: add suppor...
777
778
  		tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size));
  		ins_size = csum_size * tmp;
f578d4bd7   Chris Mason   Btrfs: Optimize c...
779
  	} else {
607d432da   Josef Bacik   Btrfs: add suppor...
780
  		ins_size = csum_size;
f578d4bd7   Chris Mason   Btrfs: Optimize c...
781
  	}
b9473439d   Chris Mason   Btrfs: leave btre...
782
  	path->leave_spinning = 1;
5caf2a002   Chris Mason   Btrfs: dynamic al...
783
  	ret = btrfs_insert_empty_item(trans, root, path, &file_key,
f578d4bd7   Chris Mason   Btrfs: Optimize c...
784
  				      ins_size);
b9473439d   Chris Mason   Btrfs: leave btre...
785
  	path->leave_spinning = 0;
54aa1f4df   Chris Mason   Btrfs: Audit call...
786
  	if (ret < 0)
53863232e   Chris Mason   Btrfs: Lower cont...
787
  		goto fail_unlock;
a429e5137   Chris Mason   Btrfs: working fi...
788
  	if (ret != 0) {
a429e5137   Chris Mason   Btrfs: working fi...
789
  		WARN_ON(1);
53863232e   Chris Mason   Btrfs: Lower cont...
790
  		goto fail_unlock;
a429e5137   Chris Mason   Btrfs: working fi...
791
  	}
6567e837d   Chris Mason   Btrfs: early work...
792
  csum:
5f39d397d   Chris Mason   Btrfs: Create ext...
793
794
  	leaf = path->nodes[0];
  	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
f254e52c1   Chris Mason   Btrfs: verify csu...
795
  	ret = 0;
509659cde   Chris Mason   Btrfs: switch to ...
796
  	item = (struct btrfs_csum_item *)((unsigned char *)item +
607d432da   Josef Bacik   Btrfs: add suppor...
797
  					  csum_offset * csum_size);
b18c66858   Chris Mason   Btrfs: progress o...
798
  found:
065631f6d   Chris Mason   Btrfs: checksum f...
799
800
801
  	item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
  	item_end = (struct btrfs_csum_item *)((unsigned char *)item_end +
  				      btrfs_item_size_nr(leaf, path->slots[0]));
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
802
  next_sector:
aadfeb6e3   Chris Mason   Btrfs: Add some e...
803

a65917156   Chris Mason   Btrfs: stop using...
804
  	write_extent_buffer(leaf, &sector_sum->sum, (unsigned long)item, csum_size);
7f3c74fb8   Chris Mason   Btrfs: Keep exten...
805

e6dcd2dc9   Chris Mason   Btrfs: New data=o...
806
807
808
  	total_bytes += root->sectorsize;
  	sector_sum++;
  	if (total_bytes < sums->len) {
6e92f5e65   Chris Mason   Btrfs: While doin...
809
  		item = (struct btrfs_csum_item *)((char *)item +
607d432da   Josef Bacik   Btrfs: add suppor...
810
  						  csum_size);
d20f7043f   Chris Mason   Btrfs: move data ...
811
812
813
  		if (item < item_end && bytenr + PAGE_CACHE_SIZE ==
  		    sector_sum->bytenr) {
  			bytenr = sector_sum->bytenr;
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
814
  			goto next_sector;
2e1a992e3   Chris Mason   Btrfs: Make sure ...
815
  		}
065631f6d   Chris Mason   Btrfs: checksum f...
816
  	}
a65917156   Chris Mason   Btrfs: stop using...
817

5caf2a002   Chris Mason   Btrfs: dynamic al...
818
  	btrfs_mark_buffer_dirty(path->nodes[0]);
e6dcd2dc9   Chris Mason   Btrfs: New data=o...
819
  	if (total_bytes < sums->len) {
b3b4aa74b   David Sterba   btrfs: drop unuse...
820
  		btrfs_release_path(path);
b9473439d   Chris Mason   Btrfs: leave btre...
821
  		cond_resched();
065631f6d   Chris Mason   Btrfs: checksum f...
822
823
  		goto again;
  	}
53863232e   Chris Mason   Btrfs: Lower cont...
824
  out:
5caf2a002   Chris Mason   Btrfs: dynamic al...
825
  	btrfs_free_path(path);
f254e52c1   Chris Mason   Btrfs: verify csu...
826
  	return ret;
53863232e   Chris Mason   Btrfs: Lower cont...
827
828
  
  fail_unlock:
53863232e   Chris Mason   Btrfs: Lower cont...
829
  	goto out;
f254e52c1   Chris Mason   Btrfs: verify csu...
830
  }