file-item.c 26.4 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0
C
Chris Mason 已提交
2 3 4 5
/*
 * Copyright (C) 2007 Oracle.  All rights reserved.
 */

6
#include <linux/bio.h>
7
#include <linux/slab.h>
8 9
#include <linux/pagemap.h>
#include <linux/highmem.h>
10
#include <linux/sched/mm.h>
C
Chris Mason 已提交
11
#include "ctree.h"
C
Chris Mason 已提交
12
#include "disk-io.h"
13
#include "transaction.h"
14
#include "volumes.h"
C
Chris Mason 已提交
15
#include "print-tree.h"
16
#include "compression.h"
C
Chris Mason 已提交
17

C
Chris Mason 已提交
18 19 20
#define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \
				   sizeof(struct btrfs_item) * 2) / \
				  size) - 1))
Y
Yan Zheng 已提交
21

22
#define MAX_CSUM_ITEMS(r, size) (min_t(u32, __MAX_CSUM_ITEMS(r, size), \
23
				       PAGE_SIZE))
24

25
#define MAX_ORDERED_SUM_BYTES(fs_info) ((PAGE_SIZE - \
Y
Yan Zheng 已提交
26
				   sizeof(struct btrfs_ordered_sum)) / \
27
				   sizeof(u32) * (fs_info)->sectorsize)
Y
Yan Zheng 已提交
28

C
Chris Mason 已提交
29
int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
S
Sage Weil 已提交
30 31 32
			     struct btrfs_root *root,
			     u64 objectid, u64 pos,
			     u64 disk_offset, u64 disk_num_bytes,
C
Chris Mason 已提交
33 34
			     u64 num_bytes, u64 offset, u64 ram_bytes,
			     u8 compression, u8 encryption, u16 other_encoding)
35
{
C
Chris Mason 已提交
36 37 38
	int ret = 0;
	struct btrfs_file_extent_item *item;
	struct btrfs_key file_key;
39
	struct btrfs_path *path;
40
	struct extent_buffer *leaf;
C
Chris Mason 已提交
41

42
	path = btrfs_alloc_path();
T
Tsutomu Itoh 已提交
43 44
	if (!path)
		return -ENOMEM;
C
Chris Mason 已提交
45
	file_key.objectid = objectid;
C
Chris Mason 已提交
46
	file_key.offset = pos;
47
	file_key.type = BTRFS_EXTENT_DATA_KEY;
C
Chris Mason 已提交
48

49
	path->leave_spinning = 1;
50
	ret = btrfs_insert_empty_item(trans, root, path, &file_key,
C
Chris Mason 已提交
51
				      sizeof(*item));
52 53
	if (ret < 0)
		goto out;
54
	BUG_ON(ret); /* Can't happen */
55 56
	leaf = path->nodes[0];
	item = btrfs_item_ptr(leaf, path->slots[0],
C
Chris Mason 已提交
57
			      struct btrfs_file_extent_item);
S
Sage Weil 已提交
58
	btrfs_set_file_extent_disk_bytenr(leaf, item, disk_offset);
59
	btrfs_set_file_extent_disk_num_bytes(leaf, item, disk_num_bytes);
S
Sage Weil 已提交
60
	btrfs_set_file_extent_offset(leaf, item, offset);
61
	btrfs_set_file_extent_num_bytes(leaf, item, num_bytes);
C
Chris Mason 已提交
62
	btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes);
63 64
	btrfs_set_file_extent_generation(leaf, item, trans->transid);
	btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
C
Chris Mason 已提交
65 66 67 68
	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);

69
	btrfs_mark_buffer_dirty(leaf);
70
out:
71
	btrfs_free_path(path);
72
	return ret;
73
}
C
Chris Mason 已提交
74

75 76 77 78 79
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)
80
{
81
	struct btrfs_fs_info *fs_info = root->fs_info;
82 83 84 85
	int ret;
	struct btrfs_key file_key;
	struct btrfs_key found_key;
	struct btrfs_csum_item *item;
86
	struct extent_buffer *leaf;
87
	u64 csum_offset = 0;
88
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
89
	int csums_in_item;
90

91 92
	file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
	file_key.offset = bytenr;
93
	file_key.type = BTRFS_EXTENT_CSUM_KEY;
C
Chris Mason 已提交
94
	ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
95 96
	if (ret < 0)
		goto fail;
97
	leaf = path->nodes[0];
98 99
	if (ret > 0) {
		ret = 1;
100
		if (path->slots[0] == 0)
101 102
			goto fail;
		path->slots[0]--;
103
		btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
104
		if (found_key.type != BTRFS_EXTENT_CSUM_KEY)
105
			goto fail;
106 107

		csum_offset = (bytenr - found_key.offset) >>
108
				fs_info->sb->s_blocksize_bits;
109
		csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
110
		csums_in_item /= csum_size;
111

112
		if (csum_offset == csums_in_item) {
113
			ret = -EFBIG;
114
			goto fail;
115 116
		} else if (csum_offset > csums_in_item) {
			goto fail;
117 118 119
		}
	}
	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
120
	item = (struct btrfs_csum_item *)((unsigned char *)item +
121
					  csum_offset * csum_size);
122 123 124
	return item;
fail:
	if (ret > 0)
C
Chris Mason 已提交
125
		ret = -ENOENT;
126 127 128
	return ERR_PTR(ret);
}

C
Chris Mason 已提交
129 130 131
int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
			     struct btrfs_root *root,
			     struct btrfs_path *path, u64 objectid,
C
Chris Mason 已提交
132
			     u64 offset, int mod)
C
Chris Mason 已提交
133 134 135 136 137 138 139
{
	int ret;
	struct btrfs_key file_key;
	int ins_len = mod < 0 ? -1 : 0;
	int cow = mod != 0;

	file_key.objectid = objectid;
140
	file_key.offset = offset;
141
	file_key.type = BTRFS_EXTENT_DATA_KEY;
C
Chris Mason 已提交
142 143 144
	ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
	return ret;
}
C
Chris Mason 已提交
145

146
static blk_status_t __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
147
				   u64 logical_offset, u32 *dst, int dio)
148
{
149
	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
150 151
	struct bio_vec bvec;
	struct bvec_iter iter;
152 153 154 155 156
	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;
157
	u64 offset = 0;
158 159
	u64 item_start_offset = 0;
	u64 item_last_offset = 0;
160
	u64 disk_bytenr;
161
	u64 page_bytes_left;
162
	u32 diff;
163
	int nblocks;
164
	int count = 0;
165
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
166 167

	path = btrfs_alloc_path();
168
	if (!path)
169
		return BLK_STS_RESOURCE;
170

171
	nblocks = bio->bi_iter.bi_size >> inode->i_sb->s_blocksize_bits;
172 173
	if (!dst) {
		if (nblocks * csum_size > BTRFS_BIO_INLINE_CSUM_SIZE) {
174 175 176
			btrfs_bio->csum = kmalloc_array(nblocks, csum_size,
							GFP_NOFS);
			if (!btrfs_bio->csum) {
177
				btrfs_free_path(path);
178
				return BLK_STS_RESOURCE;
179 180 181 182 183 184 185 186 187
			}
		} else {
			btrfs_bio->csum = btrfs_bio->csum_inline;
		}
		csum = btrfs_bio->csum;
	} else {
		csum = (u8 *)dst;
	}

188
	if (bio->bi_iter.bi_size > PAGE_SIZE * 8)
189
		path->reada = READA_FORWARD;
190

191 192 193 194 195 196
	/*
	 * 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.
	 */
197
	if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
198
		path->search_commit_root = 1;
199 200
		path->skip_locking = 1;
	}
201

202
	disk_bytenr = (u64)bio->bi_iter.bi_sector << 9;
203 204
	if (dio)
		offset = logical_offset;
205

206 207
	bio_for_each_segment(bvec, bio, iter) {
		page_bytes_left = bvec.bv_len;
208 209 210
		if (count)
			goto next;

211
		if (!dio)
212
			offset = page_offset(bvec.bv_page) + bvec.bv_offset;
213 214
		count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
					       (u32 *)csum, nblocks);
215
		if (count)
216 217
			goto found;

218 219
		if (!item || disk_bytenr < item_start_offset ||
		    disk_bytenr >= item_last_offset) {
220 221 222 223
			struct btrfs_key found_key;
			u32 item_size;

			if (item)
224
				btrfs_release_path(path);
225
			item = btrfs_lookup_csum(NULL, fs_info->csum_root,
226
						 path, disk_bytenr, 0);
227
			if (IS_ERR(item)) {
228
				count = 1;
229
				memset(csum, 0, csum_size);
230 231 232
				if (BTRFS_I(inode)->root->root_key.objectid ==
				    BTRFS_DATA_RELOC_TREE_OBJECTID) {
					set_extent_bits(io_tree, offset,
233
						offset + fs_info->sectorsize - 1,
234
						EXTENT_NODATASUM);
235
				} else {
236
					btrfs_info_rl(fs_info,
237
						   "no csum found for inode %llu start %llu",
238
					       btrfs_ino(BTRFS_I(inode)), offset);
239
				}
240
				item = NULL;
241
				btrfs_release_path(path);
242 243 244 245 246 247 248 249 250
				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 +
251
				(item_size / csum_size) *
252
				fs_info->sectorsize;
253 254 255 256 257 258 259
			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
		 */
260
		diff = disk_bytenr - item_start_offset;
261
		diff = diff / fs_info->sectorsize;
262
		diff = diff * csum_size;
263 264 265
		count = min_t(int, nblocks, (item_last_offset - disk_bytenr) >>
					    inode->i_sb->s_blocksize_bits);
		read_extent_buffer(path->nodes[0], csum,
266
				   ((unsigned long)item) + diff,
267
				   csum_size * count);
268
found:
269 270
		csum += count * csum_size;
		nblocks -= count;
271
next:
272
		while (count--) {
273 274 275
			disk_bytenr += fs_info->sectorsize;
			offset += fs_info->sectorsize;
			page_bytes_left -= fs_info->sectorsize;
276 277
			if (!page_bytes_left)
				break; /* move to next bio */
278
		}
279
	}
280

281
	WARN_ON_ONCE(count);
282 283 284 285
	btrfs_free_path(path);
	return 0;
}

286
blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio, u32 *dst)
287
{
288
	return __btrfs_lookup_bio_sums(inode, bio, 0, dst, 0);
289 290
}

291
blk_status_t btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio, u64 offset)
292
{
293
	return __btrfs_lookup_bio_sums(inode, bio, offset, NULL, 1);
294 295
}

296
int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
A
Arne Jansen 已提交
297
			     struct list_head *list, int search_commit)
298
{
299
	struct btrfs_fs_info *fs_info = root->fs_info;
300 301 302 303 304
	struct btrfs_key key;
	struct btrfs_path *path;
	struct extent_buffer *leaf;
	struct btrfs_ordered_sum *sums;
	struct btrfs_csum_item *item;
305
	LIST_HEAD(tmplist);
306 307 308 309
	unsigned long offset;
	int ret;
	size_t size;
	u64 csum_end;
310
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
311

312 313
	ASSERT(IS_ALIGNED(start, fs_info->sectorsize) &&
	       IS_ALIGNED(end + 1, fs_info->sectorsize));
314

315
	path = btrfs_alloc_path();
316 317
	if (!path)
		return -ENOMEM;
318

A
Arne Jansen 已提交
319 320
	if (search_commit) {
		path->skip_locking = 1;
321
		path->reada = READA_FORWARD;
A
Arne Jansen 已提交
322 323 324
		path->search_commit_root = 1;
	}

325 326 327 328
	key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
	key.offset = start;
	key.type = BTRFS_EXTENT_CSUM_KEY;

Y
Yan Zheng 已提交
329
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
330 331 332 333 334 335 336 337
	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) >>
338
				 fs_info->sb->s_blocksize_bits;
339 340 341 342 343 344 345 346 347
			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 已提交
348
			ret = btrfs_next_leaf(root, path);
349 350 351 352 353 354 355 356 357
			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 ||
358 359
		    key.type != BTRFS_EXTENT_CSUM_KEY ||
		    key.offset > end)
360 361 362 363 364 365
			break;

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

		size = btrfs_item_size_nr(leaf, path->slots[0]);
366
		csum_end = key.offset + (size / csum_size) * fs_info->sectorsize;
367 368 369 370
		if (csum_end <= start) {
			path->slots[0]++;
			continue;
		}
371

Y
Yan Zheng 已提交
372
		csum_end = min(csum_end, end + 1);
373 374
		item = btrfs_item_ptr(path->nodes[0], path->slots[0],
				      struct btrfs_csum_item);
Y
Yan Zheng 已提交
375 376
		while (start < csum_end) {
			size = min_t(size_t, csum_end - start,
377 378
				     MAX_ORDERED_SUM_BYTES(fs_info));
			sums = kzalloc(btrfs_ordered_sum_size(fs_info, size),
379
				       GFP_NOFS);
380 381 382 383
			if (!sums) {
				ret = -ENOMEM;
				goto fail;
			}
384

Y
Yan Zheng 已提交
385
			sums->bytenr = start;
386
			sums->len = (int)size;
Y
Yan Zheng 已提交
387 388

			offset = (start - key.offset) >>
389
				fs_info->sb->s_blocksize_bits;
Y
Yan Zheng 已提交
390
			offset *= csum_size;
391
			size >>= fs_info->sb->s_blocksize_bits;
Y
Yan Zheng 已提交
392

393 394 395 396 397
			read_extent_buffer(path->nodes[0],
					   sums->sums,
					   ((unsigned long)item) + offset,
					   csum_size * size);

398
			start += fs_info->sectorsize * size;
399
			list_add_tail(&sums->list, &tmplist);
Y
Yan Zheng 已提交
400
		}
401 402 403 404
		path->slots[0]++;
	}
	ret = 0;
fail:
405
	while (ret < 0 && !list_empty(&tmplist)) {
406
		sums = list_entry(tmplist.next, struct btrfs_ordered_sum, list);
407 408 409 410 411
		list_del(&sums->list);
		kfree(sums);
	}
	list_splice_tail(&tmplist, list);

412 413 414 415
	btrfs_free_path(path);
	return ret;
}

416
blk_status_t btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
417
		       u64 file_start, int contig)
418
{
419
	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
420
	struct btrfs_ordered_sum *sums;
421
	struct btrfs_ordered_extent *ordered = NULL;
422
	char *data;
423 424
	struct bvec_iter iter;
	struct bio_vec bvec;
425
	int index;
426
	int nr_sectors;
427 428
	unsigned long total_bytes = 0;
	unsigned long this_sum_bytes = 0;
429
	int i;
430
	u64 offset;
431 432 433 434 435 436
	unsigned nofs_flag;

	nofs_flag = memalloc_nofs_save();
	sums = kvzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
		       GFP_KERNEL);
	memalloc_nofs_restore(nofs_flag);
437 438

	if (!sums)
439
		return BLK_STS_RESOURCE;
440

441
	sums->len = bio->bi_iter.bi_size;
442
	INIT_LIST_HEAD(&sums->list);
443 444 445 446

	if (contig)
		offset = file_start;
	else
447
		offset = 0; /* shut up gcc */
448

449
	sums->bytenr = (u64)bio->bi_iter.bi_sector << 9;
450
	index = 0;
451

452
	bio_for_each_segment(bvec, bio, iter) {
453
		if (!contig)
454
			offset = page_offset(bvec.bv_page) + bvec.bv_offset;
455

456 457 458 459 460
		if (!ordered) {
			ordered = btrfs_lookup_ordered_extent(inode, offset);
			BUG_ON(!ordered); /* Logic error */
		}

461
		nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info,
462
						 bvec.bv_len + fs_info->sectorsize
463
						 - 1);
464 465 466 467 468 469 470 471

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

				sums->len = this_sum_bytes;
				this_sum_bytes = 0;
472
				btrfs_add_ordered_sum(ordered, sums);
473 474 475 476
				btrfs_put_ordered_extent(ordered);

				bytes_left = bio->bi_iter.bi_size - total_bytes;

477 478 479 480
				nofs_flag = memalloc_nofs_save();
				sums = kvzalloc(btrfs_ordered_sum_size(fs_info,
						      bytes_left), GFP_KERNEL);
				memalloc_nofs_restore(nofs_flag);
481 482 483 484 485 486 487 488 489
				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;
			}
490

491
			sums->sums[index] = ~(u32)0;
492
			data = kmap_atomic(bvec.bv_page);
493
			sums->sums[index]
494
				= btrfs_csum_data(data + bvec.bv_offset
495
						+ (i * fs_info->sectorsize),
496
						sums->sums[index],
497
						fs_info->sectorsize);
498
			kunmap_atomic(data);
499 500 501
			btrfs_csum_final(sums->sums[index],
					(char *)(sums->sums + index));
			index++;
502 503 504
			offset += fs_info->sectorsize;
			this_sum_bytes += fs_info->sectorsize;
			total_bytes += fs_info->sectorsize;
505 506
		}

507
	}
508
	this_sum_bytes = 0;
509
	btrfs_add_ordered_sum(ordered, sums);
510
	btrfs_put_ordered_extent(ordered);
511 512 513
	return 0;
}

514 515 516 517 518 519 520 521 522 523 524
/*
 * 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.
 */
525
static noinline void truncate_one_csum(struct btrfs_fs_info *fs_info,
526 527 528
				       struct btrfs_path *path,
				       struct btrfs_key *key,
				       u64 bytenr, u64 len)
529 530
{
	struct extent_buffer *leaf;
531
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
532 533
	u64 csum_end;
	u64 end_byte = bytenr + len;
534
	u32 blocksize_bits = fs_info->sb->s_blocksize_bits;
535 536 537

	leaf = path->nodes[0];
	csum_end = btrfs_item_size_nr(leaf, path->slots[0]) / csum_size;
538
	csum_end <<= fs_info->sb->s_blocksize_bits;
539 540 541 542 543 544 545 546 547 548 549
	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;
550
		btrfs_truncate_item(path, new_size, 1);
551 552 553 554 555 556 557 558 559 560 561
	} 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;

562
		btrfs_truncate_item(path, new_size, 0);
563 564

		key->offset = end_byte;
565
		btrfs_set_item_key_safe(fs_info, path, key);
566 567 568 569 570 571 572 573 574 575
	} 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,
576
		    struct btrfs_fs_info *fs_info, u64 bytenr, u64 len)
577
{
578
	struct btrfs_root *root = fs_info->csum_root;
579 580 581 582 583 584
	struct btrfs_path *path;
	struct btrfs_key key;
	u64 end_byte = bytenr + len;
	u64 csum_end;
	struct extent_buffer *leaf;
	int ret;
585 586
	u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
	int blocksize_bits = fs_info->sb->s_blocksize_bits;
587 588

	path = btrfs_alloc_path();
589 590
	if (!path)
		return -ENOMEM;
591

C
Chris Mason 已提交
592
	while (1) {
593 594 595 596
		key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
		key.offset = end_byte - 1;
		key.type = BTRFS_EXTENT_CSUM_KEY;

597
		path->leave_spinning = 1;
598 599 600
		ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
		if (ret > 0) {
			if (path->slots[0] == 0)
601
				break;
602
			path->slots[0]--;
603
		} else if (ret < 0) {
604
			break;
605
		}
606

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
		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) {
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
			int del_nr = 1;

			/*
			 * Check how many csum items preceding this one in this
			 * leaf correspond to our range and then delete them all
			 * at once.
			 */
			if (key.offset > bytenr && path->slots[0] > 0) {
				int slot = path->slots[0] - 1;

				while (slot >= 0) {
					struct btrfs_key pk;

					btrfs_item_key_to_cpu(leaf, &pk, slot);
					if (pk.offset < bytenr ||
					    pk.type != BTRFS_EXTENT_CSUM_KEY ||
					    pk.objectid !=
					    BTRFS_EXTENT_CSUM_OBJECTID)
						break;
					path->slots[0] = slot;
					del_nr++;
					key.offset = pk.offset;
					slot--;
				}
			}
			ret = btrfs_del_items(trans, root, path,
					      path->slots[0], del_nr);
655 656
			if (ret)
				goto out;
657 658
			if (key.offset == bytenr)
				break;
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
		} 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]);

689
			memzero_extent_buffer(leaf, item_offset + offset,
690 691 692 693 694 695 696 697
					     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);
698
			if (ret && ret != -EAGAIN) {
699
				btrfs_abort_transaction(trans, ret);
700 701
				goto out;
			}
702 703 704

			key.offset = end_byte - 1;
		} else {
705
			truncate_one_csum(fs_info, path, &key, bytenr, len);
706 707
			if (key.offset < bytenr)
				break;
708
		}
709
		btrfs_release_path(path);
710
	}
711
	ret = 0;
712 713
out:
	btrfs_free_path(path);
714
	return ret;
715 716
}

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

739
	path = btrfs_alloc_path();
740 741
	if (!path)
		return -ENOMEM;
742 743 744
again:
	next_offset = (u64)-1;
	found_next = 0;
745
	bytenr = sums->bytenr + total_bytes;
746
	file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID;
747
	file_key.offset = bytenr;
748
	file_key.type = BTRFS_EXTENT_CSUM_KEY;
749

750
	item = btrfs_lookup_csum(trans, root, path, bytenr, 1);
751
	if (!IS_ERR(item)) {
752
		ret = 0;
753 754 755 756 757
		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]));
758
		goto found;
759
	}
760
	ret = PTR_ERR(item);
761 762 763
	if (ret != -EFBIG && ret != -ENOENT)
		goto fail_unlock;

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

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

813 814
	leaf = path->nodes[0];
	btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
815
	csum_offset = (bytenr - found_key.offset) >>
816
			fs_info->sb->s_blocksize_bits;
817

818
	if (found_key.type != BTRFS_EXTENT_CSUM_KEY ||
819
	    found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID ||
820
	    csum_offset >= MAX_CSUM_ITEMS(fs_info, csum_size)) {
821 822
		goto insert;
	}
823

824
	if (csum_offset == btrfs_item_size_nr(leaf, path->slots[0]) /
825
	    csum_size) {
826 827 828 829
		int extend_nr;
		u64 tmp;
		u32 diff;
		u32 free_space;
830

831
		if (btrfs_leaf_free_space(leaf) <
832 833 834
				 sizeof(struct btrfs_item) + csum_size * 2)
			goto insert;

835
		free_space = btrfs_leaf_free_space(leaf) -
836
					 sizeof(struct btrfs_item) - csum_size;
837
		tmp = sums->len - total_bytes;
838
		tmp >>= fs_info->sb->s_blocksize_bits;
839 840 841 842
		WARN_ON(tmp < 1);

		extend_nr = max_t(int, 1, (int)tmp);
		diff = (csum_offset + extend_nr) * csum_size;
843 844
		diff = min(diff,
			   MAX_CSUM_ITEMS(fs_info, csum_size) * csum_size);
845

846
		diff = diff - btrfs_item_size_nr(leaf, path->slots[0]);
847 848 849
		diff = min(free_space, diff);
		diff /= csum_size;
		diff *= csum_size;
850

851
		btrfs_extend_item(path, diff);
852
		ret = 0;
853 854 855 856
		goto csum;
	}

insert:
857
	btrfs_release_path(path);
858
	csum_offset = 0;
859
	if (found_next) {
860
		u64 tmp;
861

862
		tmp = sums->len - total_bytes;
863
		tmp >>= fs_info->sb->s_blocksize_bits;
864
		tmp = min(tmp, (next_offset - file_key.offset) >>
865
					 fs_info->sb->s_blocksize_bits);
866

867 868
		tmp = max_t(u64, 1, tmp);
		tmp = min_t(u64, tmp, MAX_CSUM_ITEMS(fs_info, csum_size));
869
		ins_size = csum_size * tmp;
870
	} else {
871
		ins_size = csum_size;
872
	}
873
	path->leave_spinning = 1;
874
	ret = btrfs_insert_empty_item(trans, root, path, &file_key,
875
				      ins_size);
876
	path->leave_spinning = 0;
877
	if (ret < 0)
878
		goto fail_unlock;
879
	if (WARN_ON(ret != 0))
880
		goto fail_unlock;
881
	leaf = path->nodes[0];
882
csum:
883
	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
884 885
	item_end = (struct btrfs_csum_item *)((unsigned char *)item +
				      btrfs_item_size_nr(leaf, path->slots[0]));
886
	item = (struct btrfs_csum_item *)((unsigned char *)item +
887
					  csum_offset * csum_size);
C
Chris Mason 已提交
888
found:
889
	ins_size = (u32)(sums->len - total_bytes) >>
890
		   fs_info->sb->s_blocksize_bits;
891 892 893 894 895 896 897
	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;
898
	total_bytes += ins_size * fs_info->sectorsize;
899
	index += ins_size;
900

901
	btrfs_mark_buffer_dirty(path->nodes[0]);
902
	if (total_bytes < sums->len) {
903
		btrfs_release_path(path);
904
		cond_resched();
905 906
		goto again;
	}
907
out:
908
	btrfs_free_path(path);
C
Chris Mason 已提交
909
	return ret;
910 911 912

fail_unlock:
	goto out;
C
Chris Mason 已提交
913
}
914

915
void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode,
916 917 918 919 920
				     const struct btrfs_path *path,
				     struct btrfs_file_extent_item *fi,
				     const bool new_inline,
				     struct extent_map *em)
{
921
	struct btrfs_fs_info *fs_info = inode->root->fs_info;
922
	struct btrfs_root *root = inode->root;
923 924 925 926 927 928 929 930
	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);

931
	em->bdev = fs_info->fs_devices->latest_bdev;
932 933 934 935 936 937 938 939 940
	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;
941
		size = btrfs_file_extent_ram_bytes(leaf, fi);
942
		extent_end = ALIGN(extent_start + size,
943
				   fs_info->sectorsize);
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 978 979 980 981 982 983 984 985
	}

	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 {
986
		btrfs_err(fs_info,
987 988
			  "unknown file extent item type %d, inode %llu, offset %llu, "
			  "root %llu", type, btrfs_ino(inode), extent_start,
989 990 991
			  root->root_key.objectid);
	}
}