file-item.c 26.5 KB
Newer Older
C
Chris Mason 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * 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.
 */

19
#include <linux/bio.h>
20
#include <linux/slab.h>
21 22
#include <linux/pagemap.h>
#include <linux/highmem.h>
C
Chris Mason 已提交
23
#include "ctree.h"
C
Chris Mason 已提交
24
#include "disk-io.h"
25
#include "transaction.h"
26
#include "volumes.h"
C
Chris Mason 已提交
27
#include "print-tree.h"
28
#include "compression.h"
C
Chris Mason 已提交
29

C
Chris Mason 已提交
30 31 32
#define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \
				   sizeof(struct btrfs_item) * 2) / \
				  size) - 1))
Y
Yan Zheng 已提交
33

34
#define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \
35
				       PAGE_SIZE))
36

37
#define MAX_ORDERED_SUM_BYTES(fs_info) ((PAGE_SIZE - \
Y
Yan Zheng 已提交
38
				   sizeof(struct btrfs_ordered_sum)) / \
39
				   sizeof(u32) * (fs_info)->sectorsize)
Y
Yan Zheng 已提交
40

C
Chris Mason 已提交
41
int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
S
Sage Weil 已提交
42 43 44
			     struct btrfs_root *root,
			     u64 objectid, u64 pos,
			     u64 disk_offset, u64 disk_num_bytes,
C
Chris Mason 已提交
45 46
			     u64 num_bytes, u64 offset, u64 ram_bytes,
			     u8 compression, u8 encryption, u16 other_encoding)
47
{
C
Chris Mason 已提交
48 49 50
	int ret = 0;
	struct btrfs_file_extent_item *item;
	struct btrfs_key file_key;
51
	struct btrfs_path *path;
52
	struct extent_buffer *leaf;
C
Chris Mason 已提交
53

54
	path = btrfs_alloc_path();
T
Tsutomu Itoh 已提交
55 56
	if (!path)
		return -ENOMEM;
C
Chris Mason 已提交
57
	file_key.objectid = objectid;
C
Chris Mason 已提交
58
	file_key.offset = pos;
59
	file_key.type = BTRFS_EXTENT_DATA_KEY;
C
Chris Mason 已提交
60

61
	path->leave_spinning = 1;
62
	ret = btrfs_insert_empty_item(trans, root, path, &file_key,
C
Chris Mason 已提交
63
				      sizeof(*item));
64 65
	if (ret < 0)
		goto out;
66
	BUG_ON(ret); /* Can't happen */
67 68
	leaf = path->nodes[0];
	item = btrfs_item_ptr(leaf, path->slots[0],
C
Chris Mason 已提交
69
			      struct btrfs_file_extent_item);
S
Sage Weil 已提交
70
	btrfs_set_file_extent_disk_bytenr(leaf, item, disk_offset);
71
	btrfs_set_file_extent_disk_num_bytes(leaf, item, disk_num_bytes);
S
Sage Weil 已提交
72
	btrfs_set_file_extent_offset(leaf, item, offset);
73
	btrfs_set_file_extent_num_bytes(leaf, item, num_bytes);
C
Chris Mason 已提交
74
	btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes);
75 76
	btrfs_set_file_extent_generation(leaf, item, trans->transid);
	btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
C
Chris Mason 已提交
77 78 79 80
	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);

81
	btrfs_mark_buffer_dirty(leaf);
82
out:
83
	btrfs_free_path(path);
84
	return ret;
85
}
C
Chris Mason 已提交
86

87 88 89 90 91
static struct btrfs_csum_item *
btrfs_lookup_csum(struct btrfs_trans_handle *trans,
		  struct btrfs_root *root,
		  struct btrfs_path *path,
		  u64 bytenr, int cow)
92
{
93
	struct btrfs_fs_info *fs_info = root->fs_info;
94 95 96 97
	int ret;
	struct btrfs_key file_key;
	struct btrfs_key found_key;
	struct btrfs_csum_item *item;
98
	struct extent_buffer *leaf;
99
	u64 csum_offset = 0;
100
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
101
	int csums_in_item;
102

103 104
	file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
	file_key.offset = bytenr;
105
	file_key.type = BTRFS_EXTENT_CSUM_KEY;
C
Chris Mason 已提交
106
	ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
107 108
	if (ret < 0)
		goto fail;
109
	leaf = path->nodes[0];
110 111
	if (ret > 0) {
		ret = 1;
112
		if (path->slots[0] == 0)
113 114
			goto fail;
		path->slots[0]--;
115
		btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
116
		if (found_key.type != BTRFS_EXTENT_CSUM_KEY)
117
			goto fail;
118 119

		csum_offset = (bytenr - found_key.offset) >>
120
				fs_info->sb->s_blocksize_bits;
121
		csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
122
		csums_in_item /= csum_size;
123

124
		if (csum_offset == csums_in_item) {
125
			ret = -EFBIG;
126
			goto fail;
127 128
		} else if (csum_offset > csums_in_item) {
			goto fail;
129 130 131
		}
	}
	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
132
	item = (struct btrfs_csum_item *)((unsigned char *)item +
133
					  csum_offset * csum_size);
134 135 136
	return item;
fail:
	if (ret > 0)
C
Chris Mason 已提交
137
		ret = -ENOENT;
138 139 140
	return ERR_PTR(ret);
}

C
Chris Mason 已提交
141 142 143
int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
			     struct btrfs_root *root,
			     struct btrfs_path *path, u64 objectid,
C
Chris Mason 已提交
144
			     u64 offset, int mod)
C
Chris Mason 已提交
145 146 147 148 149 150 151
{
	int ret;
	struct btrfs_key file_key;
	int ins_len = mod < 0 ? -1 : 0;
	int cow = mod != 0;

	file_key.objectid = objectid;
152
	file_key.offset = offset;
153
	file_key.type = BTRFS_EXTENT_DATA_KEY;
C
Chris Mason 已提交
154 155 156
	ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
	return ret;
}
C
Chris Mason 已提交
157

158 159 160 161 162
static void btrfs_io_bio_endio_readpage(struct btrfs_io_bio *bio, int err)
{
	kfree(bio->csum_allocated);
}

163
static int __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
164
				   u64 logical_offset, u32 *dst, int dio)
165
{
166
	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
167
	struct bio_vec *bvec;
168 169 170 171 172
	struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio);
	struct btrfs_csum_item *item = NULL;
	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
	struct btrfs_path *path;
	u8 *csum;
173
	u64 offset = 0;
174 175
	u64 item_start_offset = 0;
	u64 item_last_offset = 0;
176
	u64 disk_bytenr;
177
	u64 page_bytes_left;
178
	u32 diff;
179
	int nblocks;
180
	int count = 0, i;
181
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
182 183

	path = btrfs_alloc_path();
184 185
	if (!path)
		return -ENOMEM;
186

187
	nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits;
188 189
	if (!dst) {
		if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
190 191
			btrfs_bio->csum_allocated = kmalloc_array(nblocks,
					csum_size, GFP_NOFS);
192 193 194 195 196 197 198 199 200 201 202 203 204 205
			if (!btrfs_bio->csum_allocated) {
				btrfs_free_path(path);
				return -ENOMEM;
			}
			btrfs_bio->csum = btrfs_bio->csum_allocated;
			btrfs_bio->end_io = btrfs_io_bio_endio_readpage;
		} else {
			btrfs_bio->csum = btrfs_bio->csum_inline;
		}
		csum = btrfs_bio->csum;
	} else {
		csum = (u8 *)dst;
	}

206
	if (bio->bi_iter.bi_size > PAGE_SIZE * 8)
207
		path->reada = READA_FORWARD;
208 209 210

	WARN_ON(bio->bi_vcnt <= 0);

211 212 213 214 215 216
	/*
	 * 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.
	 */
217
	if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
218
		path->search_commit_root = 1;
219 220
		path->skip_locking = 1;
	}
221

222
	disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
223 224
	if (dio)
		offset = logical_offset;
225

226 227 228 229 230
	bio_for_each_segment_all(bvec, bio, i) {
		page_bytes_left = bvec->bv_len;
		if (count)
			goto next;

231 232
		if (!dio)
			offset = page_offset(bvec->bv_page) + bvec->bv_offset;
233 234
		count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
					       (u32 *)csum, nblocks);
235
		if (count)
236 237
			goto found;

238 239
		if (!item || disk_bytenr < item_start_offset ||
		    disk_bytenr >= item_last_offset) {
240 241 242 243
			struct btrfs_key found_key;
			u32 item_size;

			if (item)
244
				btrfs_release_path(path);
245
			item = btrfs_lookup_csum(NULL, fs_info->csum_root,
246
						 path, disk_bytenr, 0);
247
			if (IS_ERR(item)) {
248
				count = 1;
249
				memset(csum, 0, csum_size);
250 251 252
				if (BTRFS_I(inode)->root->root_key.objectid ==
				    BTRFS_DATA_RELOC_TREE_OBJECTID) {
					set_extent_bits(io_tree, offset,
253
						offset + fs_info->sectorsize - 1,
254
						EXTENT_NODATASUM);
255
				} else {
256
					btrfs_info_rl(fs_info,
257
						   "no csum found for inode %llu start %llu",
258
					       btrfs_ino(BTRFS_I(inode)), offset);
259
				}
260
				item = NULL;
261
				btrfs_release_path(path);
262 263 264 265 266 267 268 269 270
				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 +
271
				(item_size / csum_size) *
272
				fs_info->sectorsize;
273 274 275 276 277 278 279
			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
		 */
280
		diff = disk_bytenr - item_start_offset;
281
		diff = diff / fs_info->sectorsize;
282
		diff = diff * csum_size;
283 284 285
		count = min_t(int, nblocks, (item_last_offset - disk_bytenr) >>
					    inode->i_sb->s_blocksize_bits);
		read_extent_buffer(path->nodes[0], csum,
286
				   ((unsigned long)item) + diff,
287
				   csum_size * count);
288
found:
289 290
		csum += count * csum_size;
		nblocks -= count;
291
next:
292
		while (count--) {
293 294 295
			disk_bytenr += fs_info->sectorsize;
			offset += fs_info->sectorsize;
			page_bytes_left -= fs_info->sectorsize;
296 297
			if (!page_bytes_left)
				break; /* move to next bio */
298
		}
299
	}
300

301
	WARN_ON_ONCE(count);
302 303 304 305
	btrfs_free_path(path);
	return 0;
}

306
int btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u32 *dst)
307
{
308
	return __btrfs_lookup_bio_sums(inode, bio, 0, dst, 0);
309 310
}

311
int btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio, u64 offset)
312
{
313
	return __btrfs_lookup_bio_sums(inode, bio, offset, NULL, 1);
314 315
}

316
int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
A
Arne Jansen 已提交
317
			     struct list_head *list, int search_commit)
318
{
319
	struct btrfs_fs_info *fs_info = root->fs_info;
320 321 322 323 324
	struct btrfs_key key;
	struct btrfs_path *path;
	struct extent_buffer *leaf;
	struct btrfs_ordered_sum *sums;
	struct btrfs_csum_item *item;
325
	LIST_HEAD(tmplist);
326 327 328 329
	unsigned long offset;
	int ret;
	size_t size;
	u64 csum_end;
330
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
331

332 333
	ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
	       IS_ALIGNED(end + 1, fs_info->sectorsize));
334

335
	path = btrfs_alloc_path();
336 337
	if (!path)
		return -ENOMEM;
338

A
Arne Jansen 已提交
339 340
	if (search_commit) {
		path->skip_locking = 1;
341
		path->reada = READA_FORWARD;
A
Arne Jansen 已提交
342 343 344
		path->search_commit_root = 1;
	}

345 346 347 348
	key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
	key.offset = start;
	key.type = BTRFS_EXTENT_CSUM_KEY;

Y
Yan Zheng 已提交
349
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
350 351 352 353 354 355 356 357
	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) >>
358
				 fs_info->sb->s_blocksize_bits;
359 360 361 362 363 364 365 366 367
			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)) {
Y
Yan Zheng 已提交
368
			ret = btrfs_next_leaf(root, path);
369 370 371 372 373 374 375 376 377
			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 ||
378 379
		    key.type != BTRFS_EXTENT_CSUM_KEY ||
		    key.offset > end)
380 381 382 383 384 385
			break;

		if (key.offset > start)
			start = key.offset;

		size = btrfs_item_size_nr(leaf, path->slots[0]);
386
		csum_end = key.offset + (size / csum_size) * fs_info->sectorsize;
387 388 389 390
		if (csum_end <= start) {
			path->slots[0]++;
			continue;
		}
391

Y
Yan Zheng 已提交
392
		csum_end = min(csum_end, end + 1);
393 394
		item = btrfs_item_ptr(path->nodes[0], path->slots[0],
				      struct btrfs_csum_item);
Y
Yan Zheng 已提交
395 396
		while (start < csum_end) {
			size = min_t(size_t, csum_end - start,
397 398
				     MAX_ORDERED_SUM_BYTES(fs_info));
			sums = kzalloc(btrfs_ordered_sum_size(fs_info, size),
399
				       GFP_NOFS);
400 401 402 403
			if (!sums) {
				ret = -ENOMEM;
				goto fail;
			}
404

Y
Yan Zheng 已提交
405
			sums->bytenr = start;
406
			sums->len = (int)size;
Y
Yan Zheng 已提交
407 408

			offset = (start - key.offset) >>
409
				fs_info->sb->s_blocksize_bits;
Y
Yan Zheng 已提交
410
			offset *= csum_size;
411
			size >>= fs_info->sb->s_blocksize_bits;
Y
Yan Zheng 已提交
412

413 414 415 416 417
			read_extent_buffer(path->nodes[0],
					   sums->sums,
					   ((unsigned long)item) + offset,
					   csum_size * size);

418
			start += fs_info->sectorsize * size;
419
			list_add_tail(&sums->list, &tmplist);
Y
Yan Zheng 已提交
420
		}
421 422 423 424
		path->slots[0]++;
	}
	ret = 0;
fail:
425
	while (ret < 0 && !list_empty(&tmplist)) {
426
		sums = list_entry(tmplist.next, struct btrfs_ordered_sum, list);
427 428 429 430 431
		list_del(&sums->list);
		kfree(sums);
	}
	list_splice_tail(&tmplist, list);

432 433 434 435
	btrfs_free_path(path);
	return ret;
}

436 437
int btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
		       u64 file_start, int contig)
438
{
439
	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
440
	struct btrfs_ordered_sum *sums;
441
	struct btrfs_ordered_extent *ordered = NULL;
442
	char *data;
443
	struct bio_vec *bvec;
444
	int index;
445
	int nr_sectors;
446
	int i, j;
447 448 449
	unsigned long total_bytes = 0;
	unsigned long this_sum_bytes = 0;
	u64 offset;
450

451
	WARN_ON(bio->bi_vcnt <= 0);
452
	sums = kzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
453
		       GFP_NOFS);
454 455
	if (!sums)
		return -ENOMEM;
456

457
	sums->len = bio->bi_iter.bi_size;
458
	INIT_LIST_HEAD(&sums->list);
459 460 461 462

	if (contig)
		offset = file_start;
	else
463
		offset = 0; /* shut up gcc */
464

465
	sums->bytenr = (u64)bio->bi_iter.bi_sector << 9;
466
	index = 0;
467

468
	bio_for_each_segment_all(bvec, bio, j) {
469 470 471
		if (!contig)
			offset = page_offset(bvec->bv_page) + bvec->bv_offset;

472 473 474 475 476
		if (!ordered) {
			ordered = btrfs_lookup_ordered_extent(inode, offset);
			BUG_ON(!ordered); /* Logic error */
		}

477
		data = kmap_atomic(bvec->bv_page);
478

479 480 481
		nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info,
						 bvec->bv_len + fs_info->sectorsize
						 - 1);
482 483 484 485 486 487 488 489 490 491 492 493 494 495

		for (i = 0; i < nr_sectors; i++) {
			if (offset >= ordered->file_offset + ordered->len ||
				offset < ordered->file_offset) {
				unsigned long bytes_left;

				kunmap_atomic(data);
				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_iter.bi_size - total_bytes;

496 497
				sums = kzalloc(btrfs_ordered_sum_size(fs_info, bytes_left),
					       GFP_NOFS);
498 499 500 501 502 503 504 505 506 507 508
				BUG_ON(!sums); /* -ENOMEM */
				sums->len = bytes_left;
				ordered = btrfs_lookup_ordered_extent(inode,
								offset);
				ASSERT(ordered); /* Logic error */
				sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9)
					+ total_bytes;
				index = 0;

				data = kmap_atomic(bvec->bv_page);
			}
509

510 511 512
			sums->sums[index] = ~(u32)0;
			sums->sums[index]
				= btrfs_csum_data(data + bvec->bv_offset
513
						+ (i * fs_info->sectorsize),
514
						sums->sums[index],
515
						fs_info->sectorsize);
516 517 518
			btrfs_csum_final(sums->sums[index],
					(char *)(sums->sums + index));
			index++;
519 520 521
			offset += fs_info->sectorsize;
			this_sum_bytes += fs_info->sectorsize;
			total_bytes += fs_info->sectorsize;
522 523
		}

524
		kunmap_atomic(data);
525
	}
526
	this_sum_bytes = 0;
527 528
	btrfs_add_ordered_sum(inode, ordered, sums);
	btrfs_put_ordered_extent(ordered);
529 530 531
	return 0;
}

532 533 534 535 536 537 538 539 540 541 542
/*
 * 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.
 */
543
static noinline void truncate_one_csum(struct btrfs_fs_info *fs_info,
544 545 546
				       struct btrfs_path *path,
				       struct btrfs_key *key,
				       u64 bytenr, u64 len)
547 548
{
	struct extent_buffer *leaf;
549
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
550 551
	u64 csum_end;
	u64 end_byte = bytenr + len;
552
	u32 blocksize_bits = fs_info->sb->s_blocksize_bits;
553 554 555

	leaf = path->nodes[0];
	csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
556
	csum_end <<= fs_info->sb->s_blocksize_bits;
557 558 559 560 561 562 563 564 565 566 567
	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;
568
		btrfs_truncate_item(fs_info, path, new_size, 1);
569 570 571 572 573 574 575 576 577 578 579
	} 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;

580
		btrfs_truncate_item(fs_info, path, new_size, 0);
581 582

		key->offset = end_byte;
583
		btrfs_set_item_key_safe(fs_info, path, key);
584 585 586 587 588 589 590 591 592 593
	} else {
		BUG();
	}
}

/*
 * deletes the csum items from the csum tree for a given
 * range of bytes.
 */
int btrfs_del_csums(struct btrfs_trans_handle *trans,
594
		    struct btrfs_fs_info *fs_info, u64 bytenr, u64 len)
595
{
596
	struct btrfs_root *root = fs_info->csum_root;
597 598 599 600 601 602
	struct btrfs_path *path;
	struct btrfs_key key;
	u64 end_byte = bytenr + len;
	u64 csum_end;
	struct extent_buffer *leaf;
	int ret;
603 604
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
	int blocksize_bits = fs_info->sb->s_blocksize_bits;
605 606

	path = btrfs_alloc_path();
607 608
	if (!path)
		return -ENOMEM;
609

C
Chris Mason 已提交
610
	while (1) {
611 612 613 614
		key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
		key.offset = end_byte - 1;
		key.type = BTRFS_EXTENT_CSUM_KEY;

615
		path->leave_spinning = 1;
616 617 618
		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
		if (ret > 0) {
			if (path->slots[0] == 0)
619
				break;
620
			path->slots[0]--;
621
		} else if (ret < 0) {
622
			break;
623
		}
624

625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
		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);
647 648
			if (ret)
				goto out;
649 650
			if (key.offset == bytenr)
				break;
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
		} 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]);

681
			memzero_extent_buffer(leaf, item_offset + offset,
682 683 684 685 686 687 688 689
					     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);
690
			if (ret && ret != -EAGAIN) {
691
				btrfs_abort_transaction(trans, ret);
692 693
				goto out;
			}
694 695 696

			key.offset = end_byte - 1;
		} else {
697
			truncate_one_csum(fs_info, path, &key, bytenr, len);
698 699
			if (key.offset < bytenr)
				break;
700
		}
701
		btrfs_release_path(path);
702
	}
703
	ret = 0;
704 705
out:
	btrfs_free_path(path);
706
	return ret;
707 708
}

709
int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
710
			   struct btrfs_root *root,
711
			   struct btrfs_ordered_sum *sums)
C
Chris Mason 已提交
712
{
713
	struct btrfs_fs_info *fs_info = root->fs_info;
C
Chris Mason 已提交
714
	struct btrfs_key file_key;
715
	struct btrfs_key found_key;
716
	struct btrfs_path *path;
C
Chris Mason 已提交
717
	struct btrfs_csum_item *item;
718
	struct btrfs_csum_item *item_end;
719
	struct extent_buffer *leaf = NULL;
720 721
	u64 next_offset;
	u64 total_bytes = 0;
722
	u64 csum_offset;
723
	u64 bytenr;
724 725
	u32 nritems;
	u32 ins_size;
726 727 728
	int index = 0;
	int found_next;
	int ret;
729
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
730

731
	path = btrfs_alloc_path();
732 733
	if (!path)
		return -ENOMEM;
734 735 736
again:
	next_offset = (u64)-1;
	found_next = 0;
737
	bytenr = sums->bytenr + total_bytes;
738
	file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
739
	file_key.offset = bytenr;
740
	file_key.type = BTRFS_EXTENT_CSUM_KEY;
741

742
	item = btrfs_lookup_csum(trans, root, path, bytenr, 1);
743
	if (!IS_ERR(item)) {
744
		ret = 0;
745 746 747 748 749
		leaf = path->nodes[0];
		item_end = btrfs_item_ptr(leaf, path->slots[0],
					  struct btrfs_csum_item);
		item_end = (struct btrfs_csum_item *)((char *)item_end +
			   btrfs_item_size_nr(leaf, path->slots[0]));
750
		goto found;
751
	}
752
	ret = PTR_ERR(item);
753 754 755
	if (ret != -EFBIG && ret != -ENOENT)
		goto fail_unlock;

756 757 758
	if (ret == -EFBIG) {
		u32 item_size;
		/* we found one, but it isn't big enough yet */
759 760
		leaf = path->nodes[0];
		item_size = btrfs_item_size_nr(leaf, path->slots[0]);
761
		if ((item_size / csum_size) >=
762
		    MAX_CSUM_ITEMS(fs_info, csum_size)) {
763 764 765 766
			/* already at max size, make a new one */
			goto insert;
		}
	} else {
767
		int slot = path->slots[0] + 1;
768
		/* we didn't find a csum item, insert one */
769
		nritems = btrfs_header_nritems(path->nodes[0]);
770
		if (!nritems || (path->slots[0] >= nritems - 1)) {
771
			ret = btrfs_next_leaf(root, path);
Y
Yan 已提交
772
			if (ret == 1)
773
				found_next = 1;
Y
Yan 已提交
774
			if (ret != 0)
775
				goto insert;
776
			slot = path->slots[0];
777 778
		}
		btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot);
779 780
		if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
		    found_key.type != BTRFS_EXTENT_CSUM_KEY) {
781 782 783 784 785
			found_next = 1;
			goto insert;
		}
		next_offset = found_key.offset;
		found_next = 1;
786 787 788 789 790 791 792
		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
	 */
793
	btrfs_release_path(path);
794
	ret = btrfs_search_slot(trans, root, &file_key, path,
795
				csum_size, 1);
796
	if (ret < 0)
797
		goto fail_unlock;
798 799 800 801 802

	if (ret > 0) {
		if (path->slots[0] == 0)
			goto insert;
		path->slots[0]--;
803
	}
804

805 806
	leaf = path->nodes[0];
	btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
807
	csum_offset = (bytenr - found_key.offset) >>
808
			fs_info->sb->s_blocksize_bits;
809

810
	if (found_key.type != BTRFS_EXTENT_CSUM_KEY ||
811
	    found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
812
	    csum_offset >= MAX_CSUM_ITEMS(fs_info, csum_size)) {
813 814
		goto insert;
	}
815

816
	if (csum_offset == btrfs_item_size_nr(leaf, path->slots[0]) /
817
	    csum_size) {
818 819 820 821
		int extend_nr;
		u64 tmp;
		u32 diff;
		u32 free_space;
822

823
		if (btrfs_leaf_free_space(fs_info, leaf) <
824 825 826
				 sizeof(struct btrfs_item) + csum_size * 2)
			goto insert;

827
		free_space = btrfs_leaf_free_space(fs_info, leaf) -
828
					 sizeof(struct btrfs_item) - csum_size;
829
		tmp = sums->len - total_bytes;
830
		tmp >>= fs_info->sb->s_blocksize_bits;
831 832 833 834
		WARN_ON(tmp < 1);

		extend_nr = max_t(int, 1, (int)tmp);
		diff = (csum_offset + extend_nr) * csum_size;
835 836
		diff = min(diff,
			   MAX_CSUM_ITEMS(fs_info, csum_size) * csum_size);
837

838
		diff = diff - btrfs_item_size_nr(leaf, path->slots[0]);
839 840 841
		diff = min(free_space, diff);
		diff /= csum_size;
		diff *= csum_size;
842

843
		btrfs_extend_item(fs_info, path, diff);
844
		ret = 0;
845 846 847 848
		goto csum;
	}

insert:
849
	btrfs_release_path(path);
850
	csum_offset = 0;
851
	if (found_next) {
852
		u64 tmp;
853

854
		tmp = sums->len - total_bytes;
855
		tmp >>= fs_info->sb->s_blocksize_bits;
856
		tmp = min(tmp, (next_offset - file_key.offset) >>
857
					 fs_info->sb->s_blocksize_bits);
858

859 860
		tmp = max_t(u64, 1, tmp);
		tmp = min_t(u64, tmp, MAX_CSUM_ITEMS(fs_info, csum_size));
861
		ins_size = csum_size * tmp;
862
	} else {
863
		ins_size = csum_size;
864
	}
865
	path->leave_spinning = 1;
866
	ret = btrfs_insert_empty_item(trans, root, path, &file_key,
867
				      ins_size);
868
	path->leave_spinning = 0;
869
	if (ret < 0)
870
		goto fail_unlock;
871
	if (WARN_ON(ret != 0))
872
		goto fail_unlock;
873
	leaf = path->nodes[0];
874
csum:
875
	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
876 877
	item_end = (struct btrfs_csum_item *)((unsigned char *)item +
				      btrfs_item_size_nr(leaf, path->slots[0]));
878
	item = (struct btrfs_csum_item *)((unsigned char *)item +
879
					  csum_offset * csum_size);
C
Chris Mason 已提交
880
found:
881
	ins_size = (u32)(sums->len - total_bytes) >>
882
		   fs_info->sb->s_blocksize_bits;
883 884 885 886 887 888 889
	ins_size *= csum_size;
	ins_size = min_t(u32, (unsigned long)item_end - (unsigned long)item,
			      ins_size);
	write_extent_buffer(leaf, sums->sums + index, (unsigned long)item,
			    ins_size);

	ins_size /= csum_size;
890
	total_bytes += ins_size * fs_info->sectorsize;
891
	index += ins_size;
892

893
	btrfs_mark_buffer_dirty(path->nodes[0]);
894
	if (total_bytes < sums->len) {
895
		btrfs_release_path(path);
896
		cond_resched();
897 898
		goto again;
	}
899
out:
900
	btrfs_free_path(path);
C
Chris Mason 已提交
901
	return ret;
902 903 904

fail_unlock:
	goto out;
C
Chris Mason 已提交
905
}
906 907 908 909 910 911 912

void btrfs_extent_item_to_extent_map(struct inode *inode,
				     const struct btrfs_path *path,
				     struct btrfs_file_extent_item *fi,
				     const bool new_inline,
				     struct extent_map *em)
{
913
	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
914 915 916 917 918 919 920 921 922
	struct btrfs_root *root = BTRFS_I(inode)->root;
	struct extent_buffer *leaf = path->nodes[0];
	const int slot = path->slots[0];
	struct btrfs_key key;
	u64 extent_start, extent_end;
	u64 bytenr;
	u8 type = btrfs_file_extent_type(leaf, fi);
	int compress_type = btrfs_file_extent_compression(leaf, fi);

923
	em->bdev = fs_info->fs_devices->latest_bdev;
924 925 926 927 928 929 930 931 932 933
	btrfs_item_key_to_cpu(leaf, &key, slot);
	extent_start = key.offset;

	if (type == BTRFS_FILE_EXTENT_REG ||
	    type == BTRFS_FILE_EXTENT_PREALLOC) {
		extent_end = extent_start +
			btrfs_file_extent_num_bytes(leaf, fi);
	} else if (type == BTRFS_FILE_EXTENT_INLINE) {
		size_t size;
		size = btrfs_file_extent_inline_len(leaf, slot, fi);
934
		extent_end = ALIGN(extent_start + size,
935
				   fs_info->sectorsize);
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
	}

	em->ram_bytes = btrfs_file_extent_ram_bytes(leaf, fi);
	if (type == BTRFS_FILE_EXTENT_REG ||
	    type == BTRFS_FILE_EXTENT_PREALLOC) {
		em->start = extent_start;
		em->len = extent_end - extent_start;
		em->orig_start = extent_start -
			btrfs_file_extent_offset(leaf, fi);
		em->orig_block_len = btrfs_file_extent_disk_num_bytes(leaf, fi);
		bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
		if (bytenr == 0) {
			em->block_start = EXTENT_MAP_HOLE;
			return;
		}
		if (compress_type != BTRFS_COMPRESS_NONE) {
			set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
			em->compress_type = compress_type;
			em->block_start = bytenr;
			em->block_len = em->orig_block_len;
		} else {
			bytenr += btrfs_file_extent_offset(leaf, fi);
			em->block_start = bytenr;
			em->block_len = em->len;
			if (type == BTRFS_FILE_EXTENT_PREALLOC)
				set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
		}
	} else if (type == BTRFS_FILE_EXTENT_INLINE) {
		em->block_start = EXTENT_MAP_INLINE;
		em->start = extent_start;
		em->len = extent_end - extent_start;
		/*
		 * Initialize orig_start and block_len with the same values
		 * as in inode.c:btrfs_get_extent().
		 */
		em->orig_start = EXTENT_MAP_HOLE;
		em->block_len = (u64)-1;
		if (!new_inline && compress_type != BTRFS_COMPRESS_NONE) {
			set_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
			em->compress_type = compress_type;
		}
	} else {
978
		btrfs_err(fs_info,
979
			  "unknown file extent item type %d, inode %llu, offset %llu, root %llu",
980
			  type, btrfs_ino(BTRFS_I(inode)), extent_start,
981 982 983
			  root->root_key.objectid);
	}
}