aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorYan, Zheng <zheng.yan@oracle.com>2009-11-12 04:34:08 -0500
committerChris Mason <chris.mason@oracle.com>2009-12-15 21:24:52 -0500
commit920bbbfb05c9fce22e088d20eb9dcb8f96342de9 (patch)
treeb972b3f39ebefb9c026300c1981d18cad769e431 /fs/btrfs/file.c
parentad48fd754676bfae4139be1a897b1ea58f9aaf21 (diff)
Btrfs: Rewrite btrfs_drop_extents
Rewrite btrfs_drop_extents by using btrfs_duplicate_item, so we can avoid calling lock_extent within transaction. Signed-off-by: Yan Zheng <zheng.yan@oracle.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c659
1 files changed, 263 insertions, 396 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 06550affbd27..3d2e45ce5d25 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -265,319 +265,247 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
265 * If an extent intersects the range but is not entirely inside the range 265 * If an extent intersects the range but is not entirely inside the range
266 * it is either truncated or split. Anything entirely inside the range 266 * it is either truncated or split. Anything entirely inside the range
267 * is deleted from the tree. 267 * is deleted from the tree.
268 *
269 * inline_limit is used to tell this code which offsets in the file to keep
270 * if they contain inline extents.
271 */ 268 */
272noinline int btrfs_drop_extents(struct btrfs_trans_handle *trans, 269int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
273 struct btrfs_root *root, struct inode *inode, 270 u64 start, u64 end, u64 *hint_byte, int drop_cache)
274 u64 start, u64 end, u64 locked_end,
275 u64 inline_limit, u64 *hint_byte, int drop_cache)
276{ 271{
277 u64 extent_end = 0; 272 struct btrfs_root *root = BTRFS_I(inode)->root;
278 u64 search_start = start;
279 u64 ram_bytes = 0;
280 u64 disk_bytenr = 0;
281 u64 orig_locked_end = locked_end;
282 u8 compression;
283 u8 encryption;
284 u16 other_encoding = 0;
285 struct extent_buffer *leaf; 273 struct extent_buffer *leaf;
286 struct btrfs_file_extent_item *extent; 274 struct btrfs_file_extent_item *fi;
287 struct btrfs_path *path; 275 struct btrfs_path *path;
288 struct btrfs_key key; 276 struct btrfs_key key;
289 struct btrfs_file_extent_item old; 277 struct btrfs_key new_key;
290 int keep; 278 u64 search_start = start;
291 int slot; 279 u64 disk_bytenr = 0;
292 int bookend; 280 u64 num_bytes = 0;
293 int found_type = 0; 281 u64 extent_offset = 0;
294 int found_extent; 282 u64 extent_end = 0;
295 int found_inline; 283 int del_nr = 0;
284 int del_slot = 0;
285 int extent_type;
296 int recow; 286 int recow;
297 int ret; 287 int ret;
298 288
299 inline_limit = 0;
300 if (drop_cache) 289 if (drop_cache)
301 btrfs_drop_extent_cache(inode, start, end - 1, 0); 290 btrfs_drop_extent_cache(inode, start, end - 1, 0);
302 291
303 path = btrfs_alloc_path(); 292 path = btrfs_alloc_path();
304 if (!path) 293 if (!path)
305 return -ENOMEM; 294 return -ENOMEM;
295
306 while (1) { 296 while (1) {
307 recow = 0; 297 recow = 0;
308 btrfs_release_path(root, path);
309 ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino, 298 ret = btrfs_lookup_file_extent(trans, root, path, inode->i_ino,
310 search_start, -1); 299 search_start, -1);
311 if (ret < 0) 300 if (ret < 0)
312 goto out; 301 break;
313 if (ret > 0) { 302 if (ret > 0 && path->slots[0] > 0 && search_start == start) {
314 if (path->slots[0] == 0) { 303 leaf = path->nodes[0];
315 ret = 0; 304 btrfs_item_key_to_cpu(leaf, &key, path->slots[0] - 1);
316 goto out; 305 if (key.objectid == inode->i_ino &&
317 } 306 key.type == BTRFS_EXTENT_DATA_KEY)
318 path->slots[0]--; 307 path->slots[0]--;
319 } 308 }
309 ret = 0;
320next_slot: 310next_slot:
321 keep = 0;
322 bookend = 0;
323 found_extent = 0;
324 found_inline = 0;
325 compression = 0;
326 encryption = 0;
327 extent = NULL;
328 leaf = path->nodes[0]; 311 leaf = path->nodes[0];
329 slot = path->slots[0]; 312 if (path->slots[0] >= btrfs_header_nritems(leaf)) {
330 ret = 0; 313 BUG_ON(del_nr > 0);
331 btrfs_item_key_to_cpu(leaf, &key, slot); 314 ret = btrfs_next_leaf(root, path);
332 if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY && 315 if (ret < 0)
333 key.offset >= end) { 316 break;
334 goto out; 317 if (ret > 0) {
335 } 318 ret = 0;
336 if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY || 319 break;
337 key.objectid != inode->i_ino) {
338 goto out;
339 }
340 if (recow) {
341 search_start = max(key.offset, start);
342 continue;
343 }
344 if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
345 extent = btrfs_item_ptr(leaf, slot,
346 struct btrfs_file_extent_item);
347 found_type = btrfs_file_extent_type(leaf, extent);
348 compression = btrfs_file_extent_compression(leaf,
349 extent);
350 encryption = btrfs_file_extent_encryption(leaf,
351 extent);
352 other_encoding = btrfs_file_extent_other_encoding(leaf,
353 extent);
354 if (found_type == BTRFS_FILE_EXTENT_REG ||
355 found_type == BTRFS_FILE_EXTENT_PREALLOC) {
356 extent_end =
357 btrfs_file_extent_disk_bytenr(leaf,
358 extent);
359 if (extent_end)
360 *hint_byte = extent_end;
361
362 extent_end = key.offset +
363 btrfs_file_extent_num_bytes(leaf, extent);
364 ram_bytes = btrfs_file_extent_ram_bytes(leaf,
365 extent);
366 found_extent = 1;
367 } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
368 found_inline = 1;
369 extent_end = key.offset +
370 btrfs_file_extent_inline_len(leaf, extent);
371 } 320 }
321 leaf = path->nodes[0];
322 recow = 1;
323 }
324
325 btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
326 if (key.objectid > inode->i_ino ||
327 key.type > BTRFS_EXTENT_DATA_KEY || key.offset >= end)
328 break;
329
330 fi = btrfs_item_ptr(leaf, path->slots[0],
331 struct btrfs_file_extent_item);
332 extent_type = btrfs_file_extent_type(leaf, fi);
333
334 if (extent_type == BTRFS_FILE_EXTENT_REG ||
335 extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
336 disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
337 num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
338 extent_offset = btrfs_file_extent_offset(leaf, fi);
339 extent_end = key.offset +
340 btrfs_file_extent_num_bytes(leaf, fi);
341 } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
342 extent_end = key.offset +
343 btrfs_file_extent_inline_len(leaf, fi);
372 } else { 344 } else {
345 WARN_ON(1);
373 extent_end = search_start; 346 extent_end = search_start;
374 } 347 }
375 348
376 /* we found nothing we can drop */ 349 if (extent_end <= search_start) {
377 if ((!found_extent && !found_inline) || 350 path->slots[0]++;
378 search_start >= extent_end) {
379 int nextret;
380 u32 nritems;
381 nritems = btrfs_header_nritems(leaf);
382 if (slot >= nritems - 1) {
383 nextret = btrfs_next_leaf(root, path);
384 if (nextret)
385 goto out;
386 recow = 1;
387 } else {
388 path->slots[0]++;
389 }
390 goto next_slot; 351 goto next_slot;
391 } 352 }
392 353
393 if (end <= extent_end && start >= key.offset && found_inline) 354 search_start = max(key.offset, start);
394 *hint_byte = EXTENT_MAP_INLINE; 355 if (recow) {
395 356 btrfs_release_path(root, path);
396 if (found_extent) { 357 continue;
397 read_extent_buffer(leaf, &old, (unsigned long)extent,
398 sizeof(old));
399 }
400
401 if (end < extent_end && end >= key.offset) {
402 bookend = 1;
403 if (found_inline && start <= key.offset)
404 keep = 1;
405 } 358 }
406 359
407 if (bookend && found_extent) { 360 /*
408 if (locked_end < extent_end) { 361 * | - range to drop - |
409 ret = try_lock_extent(&BTRFS_I(inode)->io_tree, 362 * | -------- extent -------- |
410 locked_end, extent_end - 1, 363 */
411 GFP_NOFS); 364 if (start > key.offset && end < extent_end) {
412 if (!ret) { 365 BUG_ON(del_nr > 0);
413 btrfs_release_path(root, path); 366 BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
414 lock_extent(&BTRFS_I(inode)->io_tree, 367
415 locked_end, extent_end - 1, 368 memcpy(&new_key, &key, sizeof(new_key));
416 GFP_NOFS); 369 new_key.offset = start;
417 locked_end = extent_end; 370 ret = btrfs_duplicate_item(trans, root, path,
418 continue; 371 &new_key);
419 } 372 if (ret == -EAGAIN) {
420 locked_end = extent_end; 373 btrfs_release_path(root, path);
374 continue;
421 } 375 }
422 disk_bytenr = le64_to_cpu(old.disk_bytenr); 376 if (ret < 0)
423 if (disk_bytenr != 0) { 377 break;
378
379 leaf = path->nodes[0];
380 fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
381 struct btrfs_file_extent_item);
382 btrfs_set_file_extent_num_bytes(leaf, fi,
383 start - key.offset);
384
385 fi = btrfs_item_ptr(leaf, path->slots[0],
386 struct btrfs_file_extent_item);
387
388 extent_offset += start - key.offset;
389 btrfs_set_file_extent_offset(leaf, fi, extent_offset);
390 btrfs_set_file_extent_num_bytes(leaf, fi,
391 extent_end - start);
392 btrfs_mark_buffer_dirty(leaf);
393
394 if (disk_bytenr > 0) {
424 ret = btrfs_inc_extent_ref(trans, root, 395 ret = btrfs_inc_extent_ref(trans, root,
425 disk_bytenr, 396 disk_bytenr, num_bytes, 0,
426 le64_to_cpu(old.disk_num_bytes), 0, 397 root->root_key.objectid,
427 root->root_key.objectid, 398 new_key.objectid,
428 key.objectid, key.offset - 399 start - extent_offset);
429 le64_to_cpu(old.offset));
430 BUG_ON(ret); 400 BUG_ON(ret);
401 *hint_byte = disk_bytenr;
431 } 402 }
403 key.offset = start;
432 } 404 }
405 /*
406 * | ---- range to drop ----- |
407 * | -------- extent -------- |
408 */
409 if (start <= key.offset && end < extent_end) {
410 BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
411
412 memcpy(&new_key, &key, sizeof(new_key));
413 new_key.offset = end;
414 btrfs_set_item_key_safe(trans, root, path, &new_key);
433 415
434 if (found_inline) { 416 extent_offset += end - key.offset;
435 u64 mask = root->sectorsize - 1; 417 btrfs_set_file_extent_offset(leaf, fi, extent_offset);
436 search_start = (extent_end + mask) & ~mask; 418 btrfs_set_file_extent_num_bytes(leaf, fi,
437 } else 419 extent_end - end);
438 search_start = extent_end; 420 btrfs_mark_buffer_dirty(leaf);
439 421 if (disk_bytenr > 0) {
440 /* truncate existing extent */ 422 inode_sub_bytes(inode, end - key.offset);
441 if (start > key.offset) { 423 *hint_byte = disk_bytenr;
442 u64 new_num;
443 u64 old_num;
444 keep = 1;
445 WARN_ON(start & (root->sectorsize - 1));
446 if (found_extent) {
447 new_num = start - key.offset;
448 old_num = btrfs_file_extent_num_bytes(leaf,
449 extent);
450 *hint_byte =
451 btrfs_file_extent_disk_bytenr(leaf,
452 extent);
453 if (btrfs_file_extent_disk_bytenr(leaf,
454 extent)) {
455 inode_sub_bytes(inode, old_num -
456 new_num);
457 }
458 btrfs_set_file_extent_num_bytes(leaf,
459 extent, new_num);
460 btrfs_mark_buffer_dirty(leaf);
461 } else if (key.offset < inline_limit &&
462 (end > extent_end) &&
463 (inline_limit < extent_end)) {
464 u32 new_size;
465 new_size = btrfs_file_extent_calc_inline_size(
466 inline_limit - key.offset);
467 inode_sub_bytes(inode, extent_end -
468 inline_limit);
469 btrfs_set_file_extent_ram_bytes(leaf, extent,
470 new_size);
471 if (!compression && !encryption) {
472 btrfs_truncate_item(trans, root, path,
473 new_size, 1);
474 }
475 } 424 }
425 break;
476 } 426 }
477 /* delete the entire extent */
478 if (!keep) {
479 if (found_inline)
480 inode_sub_bytes(inode, extent_end -
481 key.offset);
482 ret = btrfs_del_item(trans, root, path);
483 /* TODO update progress marker and return */
484 BUG_ON(ret);
485 extent = NULL;
486 btrfs_release_path(root, path);
487 /* the extent will be freed later */
488 }
489 if (bookend && found_inline && start <= key.offset) {
490 u32 new_size;
491 new_size = btrfs_file_extent_calc_inline_size(
492 extent_end - end);
493 inode_sub_bytes(inode, end - key.offset);
494 btrfs_set_file_extent_ram_bytes(leaf, extent,
495 new_size);
496 if (!compression && !encryption)
497 ret = btrfs_truncate_item(trans, root, path,
498 new_size, 0);
499 BUG_ON(ret);
500 }
501 /* create bookend, splitting the extent in two */
502 if (bookend && found_extent) {
503 struct btrfs_key ins;
504 ins.objectid = inode->i_ino;
505 ins.offset = end;
506 btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY);
507 427
508 btrfs_release_path(root, path); 428 search_start = extent_end;
509 path->leave_spinning = 1; 429 /*
510 ret = btrfs_insert_empty_item(trans, root, path, &ins, 430 * | ---- range to drop ----- |
511 sizeof(*extent)); 431 * | -------- extent -------- |
512 BUG_ON(ret); 432 */
433 if (start > key.offset && end >= extent_end) {
434 BUG_ON(del_nr > 0);
435 BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE);
513 436
514 leaf = path->nodes[0]; 437 btrfs_set_file_extent_num_bytes(leaf, fi,
515 extent = btrfs_item_ptr(leaf, path->slots[0], 438 start - key.offset);
516 struct btrfs_file_extent_item); 439 btrfs_mark_buffer_dirty(leaf);
517 write_extent_buffer(leaf, &old, 440 if (disk_bytenr > 0) {
518 (unsigned long)extent, sizeof(old)); 441 inode_sub_bytes(inode, extent_end - start);
519 442 *hint_byte = disk_bytenr;
520 btrfs_set_file_extent_compression(leaf, extent, 443 }
521 compression); 444 if (end == extent_end)
522 btrfs_set_file_extent_encryption(leaf, extent, 445 break;
523 encryption);
524 btrfs_set_file_extent_other_encoding(leaf, extent,
525 other_encoding);
526 btrfs_set_file_extent_offset(leaf, extent,
527 le64_to_cpu(old.offset) + end - key.offset);
528 WARN_ON(le64_to_cpu(old.num_bytes) <
529 (extent_end - end));
530 btrfs_set_file_extent_num_bytes(leaf, extent,
531 extent_end - end);
532 446
533 /* 447 path->slots[0]++;
534 * set the ram bytes to the size of the full extent 448 goto next_slot;
535 * before splitting. This is a worst case flag,
536 * but its the best we can do because we don't know
537 * how splitting affects compression
538 */
539 btrfs_set_file_extent_ram_bytes(leaf, extent,
540 ram_bytes);
541 btrfs_set_file_extent_type(leaf, extent, found_type);
542
543 btrfs_unlock_up_safe(path, 1);
544 btrfs_mark_buffer_dirty(path->nodes[0]);
545 btrfs_set_lock_blocking(path->nodes[0]);
546
547 path->leave_spinning = 0;
548 btrfs_release_path(root, path);
549 if (disk_bytenr != 0)
550 inode_add_bytes(inode, extent_end - end);
551 } 449 }
552 450
553 if (found_extent && !keep) { 451 /*
554 u64 old_disk_bytenr = le64_to_cpu(old.disk_bytenr); 452 * | ---- range to drop ----- |
453 * | ------ extent ------ |
454 */
455 if (start <= key.offset && end >= extent_end) {
456 if (del_nr == 0) {
457 del_slot = path->slots[0];
458 del_nr = 1;
459 } else {
460 BUG_ON(del_slot + del_nr != path->slots[0]);
461 del_nr++;
462 }
555 463
556 if (old_disk_bytenr != 0) { 464 if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
557 inode_sub_bytes(inode, 465 inode_sub_bytes(inode,
558 le64_to_cpu(old.num_bytes)); 466 extent_end - key.offset);
467 extent_end = ALIGN(extent_end,
468 root->sectorsize);
469 } else if (disk_bytenr > 0) {
559 ret = btrfs_free_extent(trans, root, 470 ret = btrfs_free_extent(trans, root,
560 old_disk_bytenr, 471 disk_bytenr, num_bytes, 0,
561 le64_to_cpu(old.disk_num_bytes), 472 root->root_key.objectid,
562 0, root->root_key.objectid,
563 key.objectid, key.offset - 473 key.objectid, key.offset -
564 le64_to_cpu(old.offset)); 474 extent_offset);
565 BUG_ON(ret); 475 BUG_ON(ret);
566 *hint_byte = old_disk_bytenr; 476 inode_sub_bytes(inode,
477 extent_end - key.offset);
478 *hint_byte = disk_bytenr;
567 } 479 }
568 }
569 480
570 if (search_start >= end) { 481 if (end == extent_end)
571 ret = 0; 482 break;
572 goto out; 483
484 if (path->slots[0] + 1 < btrfs_header_nritems(leaf)) {
485 path->slots[0]++;
486 goto next_slot;
487 }
488
489 ret = btrfs_del_items(trans, root, path, del_slot,
490 del_nr);
491 BUG_ON(ret);
492
493 del_nr = 0;
494 del_slot = 0;
495
496 btrfs_release_path(root, path);
497 continue;
573 } 498 }
499
500 BUG_ON(1);
574 } 501 }
575out: 502
576 btrfs_free_path(path); 503 if (del_nr > 0) {
577 if (locked_end > orig_locked_end) { 504 ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
578 unlock_extent(&BTRFS_I(inode)->io_tree, orig_locked_end, 505 BUG_ON(ret);
579 locked_end - 1, GFP_NOFS);
580 } 506 }
507
508 btrfs_free_path(path);
581 return ret; 509 return ret;
582} 510}
583 511
@@ -620,23 +548,23 @@ static int extent_mergeable(struct extent_buffer *leaf, int slot,
620 * two or three. 548 * two or three.
621 */ 549 */
622int btrfs_mark_extent_written(struct btrfs_trans_handle *trans, 550int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
623 struct btrfs_root *root,
624 struct inode *inode, u64 start, u64 end) 551 struct inode *inode, u64 start, u64 end)
625{ 552{
553 struct btrfs_root *root = BTRFS_I(inode)->root;
626 struct extent_buffer *leaf; 554 struct extent_buffer *leaf;
627 struct btrfs_path *path; 555 struct btrfs_path *path;
628 struct btrfs_file_extent_item *fi; 556 struct btrfs_file_extent_item *fi;
629 struct btrfs_key key; 557 struct btrfs_key key;
558 struct btrfs_key new_key;
630 u64 bytenr; 559 u64 bytenr;
631 u64 num_bytes; 560 u64 num_bytes;
632 u64 extent_end; 561 u64 extent_end;
633 u64 orig_offset; 562 u64 orig_offset;
634 u64 other_start; 563 u64 other_start;
635 u64 other_end; 564 u64 other_end;
636 u64 split = start; 565 u64 split;
637 u64 locked_end = end; 566 int del_nr = 0;
638 int extent_type; 567 int del_slot = 0;
639 int split_end = 1;
640 int ret; 568 int ret;
641 569
642 btrfs_drop_extent_cache(inode, start, end - 1, 0); 570 btrfs_drop_extent_cache(inode, start, end - 1, 0);
@@ -644,12 +572,10 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
644 path = btrfs_alloc_path(); 572 path = btrfs_alloc_path();
645 BUG_ON(!path); 573 BUG_ON(!path);
646again: 574again:
575 split = start;
647 key.objectid = inode->i_ino; 576 key.objectid = inode->i_ino;
648 key.type = BTRFS_EXTENT_DATA_KEY; 577 key.type = BTRFS_EXTENT_DATA_KEY;
649 if (split == start) 578 key.offset = split;
650 key.offset = split;
651 else
652 key.offset = split - 1;
653 579
654 ret = btrfs_search_slot(trans, root, &key, path, -1, 1); 580 ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
655 if (ret > 0 && path->slots[0] > 0) 581 if (ret > 0 && path->slots[0] > 0)
@@ -661,8 +587,8 @@ again:
661 key.type != BTRFS_EXTENT_DATA_KEY); 587 key.type != BTRFS_EXTENT_DATA_KEY);
662 fi = btrfs_item_ptr(leaf, path->slots[0], 588 fi = btrfs_item_ptr(leaf, path->slots[0],
663 struct btrfs_file_extent_item); 589 struct btrfs_file_extent_item);
664 extent_type = btrfs_file_extent_type(leaf, fi); 590 BUG_ON(btrfs_file_extent_type(leaf, fi) !=
665 BUG_ON(extent_type != BTRFS_FILE_EXTENT_PREALLOC); 591 BTRFS_FILE_EXTENT_PREALLOC);
666 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi); 592 extent_end = key.offset + btrfs_file_extent_num_bytes(leaf, fi);
667 BUG_ON(key.offset > start || extent_end < end); 593 BUG_ON(key.offset > start || extent_end < end);
668 594
@@ -670,150 +596,91 @@ again:
670 num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi); 596 num_bytes = btrfs_file_extent_disk_num_bytes(leaf, fi);
671 orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi); 597 orig_offset = key.offset - btrfs_file_extent_offset(leaf, fi);
672 598
673 if (key.offset == start) 599 while (start > key.offset || end < extent_end) {
674 split = end; 600 if (key.offset == start)
675 601 split = end;
676 if (key.offset == start && extent_end == end) { 602
677 int del_nr = 0; 603 memcpy(&new_key, &key, sizeof(new_key));
678 int del_slot = 0; 604 new_key.offset = split;
679 other_start = end; 605 ret = btrfs_duplicate_item(trans, root, path, &new_key);
680 other_end = 0; 606 if (ret == -EAGAIN) {
681 if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino, 607 btrfs_release_path(root, path);
682 bytenr, &other_start, &other_end)) { 608 goto again;
683 extent_end = other_end;
684 del_slot = path->slots[0] + 1;
685 del_nr++;
686 ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
687 0, root->root_key.objectid,
688 inode->i_ino, orig_offset);
689 BUG_ON(ret);
690 }
691 other_start = 0;
692 other_end = start;
693 if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino,
694 bytenr, &other_start, &other_end)) {
695 key.offset = other_start;
696 del_slot = path->slots[0];
697 del_nr++;
698 ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
699 0, root->root_key.objectid,
700 inode->i_ino, orig_offset);
701 BUG_ON(ret);
702 }
703 split_end = 0;
704 if (del_nr == 0) {
705 btrfs_set_file_extent_type(leaf, fi,
706 BTRFS_FILE_EXTENT_REG);
707 goto done;
708 } 609 }
610 BUG_ON(ret < 0);
709 611
710 fi = btrfs_item_ptr(leaf, del_slot - 1, 612 leaf = path->nodes[0];
613 fi = btrfs_item_ptr(leaf, path->slots[0] - 1,
711 struct btrfs_file_extent_item); 614 struct btrfs_file_extent_item);
712 btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
713 btrfs_set_file_extent_num_bytes(leaf, fi, 615 btrfs_set_file_extent_num_bytes(leaf, fi,
714 extent_end - key.offset); 616 split - key.offset);
617
618 fi = btrfs_item_ptr(leaf, path->slots[0],
619 struct btrfs_file_extent_item);
620
621 btrfs_set_file_extent_offset(leaf, fi, split - orig_offset);
622 btrfs_set_file_extent_num_bytes(leaf, fi,
623 extent_end - split);
715 btrfs_mark_buffer_dirty(leaf); 624 btrfs_mark_buffer_dirty(leaf);
716 625
717 ret = btrfs_del_items(trans, root, path, del_slot, del_nr); 626 ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
627 root->root_key.objectid,
628 inode->i_ino, orig_offset);
718 BUG_ON(ret); 629 BUG_ON(ret);
719 goto release;
720 } else if (split == start) {
721 if (locked_end < extent_end) {
722 ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
723 locked_end, extent_end - 1, GFP_NOFS);
724 if (!ret) {
725 btrfs_release_path(root, path);
726 lock_extent(&BTRFS_I(inode)->io_tree,
727 locked_end, extent_end - 1, GFP_NOFS);
728 locked_end = extent_end;
729 goto again;
730 }
731 locked_end = extent_end;
732 }
733 btrfs_set_file_extent_num_bytes(leaf, fi, split - key.offset);
734 } else {
735 BUG_ON(key.offset != start);
736 key.offset = split;
737 btrfs_set_file_extent_offset(leaf, fi, key.offset -
738 orig_offset);
739 btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - split);
740 btrfs_set_item_key_safe(trans, root, path, &key);
741 extent_end = split;
742 }
743 630
744 if (extent_end == end) { 631 if (split == start) {
745 split_end = 0; 632 key.offset = start;
746 extent_type = BTRFS_FILE_EXTENT_REG; 633 } else {
747 } 634 BUG_ON(start != key.offset);
748 if (extent_end == end && split == start) {
749 other_start = end;
750 other_end = 0;
751 if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
752 bytenr, &other_start, &other_end)) {
753 path->slots[0]++;
754 fi = btrfs_item_ptr(leaf, path->slots[0],
755 struct btrfs_file_extent_item);
756 key.offset = split;
757 btrfs_set_item_key_safe(trans, root, path, &key);
758 btrfs_set_file_extent_offset(leaf, fi, key.offset -
759 orig_offset);
760 btrfs_set_file_extent_num_bytes(leaf, fi,
761 other_end - split);
762 goto done;
763 }
764 }
765 if (extent_end == end && split == end) {
766 other_start = 0;
767 other_end = start;
768 if (extent_mergeable(leaf, path->slots[0] - 1 , inode->i_ino,
769 bytenr, &other_start, &other_end)) {
770 path->slots[0]--; 635 path->slots[0]--;
771 fi = btrfs_item_ptr(leaf, path->slots[0], 636 extent_end = end;
772 struct btrfs_file_extent_item);
773 btrfs_set_file_extent_num_bytes(leaf, fi, extent_end -
774 other_start);
775 goto done;
776 } 637 }
777 } 638 }
778 639
779 btrfs_mark_buffer_dirty(leaf);
780
781 ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
782 root->root_key.objectid,
783 inode->i_ino, orig_offset);
784 BUG_ON(ret);
785 btrfs_release_path(root, path);
786
787 key.offset = start;
788 ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(*fi));
789 BUG_ON(ret);
790
791 leaf = path->nodes[0];
792 fi = btrfs_item_ptr(leaf, path->slots[0], 640 fi = btrfs_item_ptr(leaf, path->slots[0],
793 struct btrfs_file_extent_item); 641 struct btrfs_file_extent_item);
794 btrfs_set_file_extent_generation(leaf, fi, trans->transid);
795 btrfs_set_file_extent_type(leaf, fi, extent_type);
796 btrfs_set_file_extent_disk_bytenr(leaf, fi, bytenr);
797 btrfs_set_file_extent_disk_num_bytes(leaf, fi, num_bytes);
798 btrfs_set_file_extent_offset(leaf, fi, key.offset - orig_offset);
799 btrfs_set_file_extent_num_bytes(leaf, fi, extent_end - key.offset);
800 btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
801 btrfs_set_file_extent_compression(leaf, fi, 0);
802 btrfs_set_file_extent_encryption(leaf, fi, 0);
803 btrfs_set_file_extent_other_encoding(leaf, fi, 0);
804done:
805 btrfs_mark_buffer_dirty(leaf);
806 642
807release: 643 other_start = end;
808 btrfs_release_path(root, path); 644 other_end = 0;
809 if (split_end && split == start) { 645 if (extent_mergeable(leaf, path->slots[0] + 1, inode->i_ino,
810 split = end; 646 bytenr, &other_start, &other_end)) {
811 goto again; 647 extent_end = other_end;
648 del_slot = path->slots[0] + 1;
649 del_nr++;
650 ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
651 0, root->root_key.objectid,
652 inode->i_ino, orig_offset);
653 BUG_ON(ret);
812 } 654 }
813 if (locked_end > end) { 655 other_start = 0;
814 unlock_extent(&BTRFS_I(inode)->io_tree, end, locked_end - 1, 656 other_end = start;
815 GFP_NOFS); 657 if (extent_mergeable(leaf, path->slots[0] - 1, inode->i_ino,
658 bytenr, &other_start, &other_end)) {
659 key.offset = other_start;
660 del_slot = path->slots[0];
661 del_nr++;
662 ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
663 0, root->root_key.objectid,
664 inode->i_ino, orig_offset);
665 BUG_ON(ret);
816 } 666 }
667 if (del_nr == 0) {
668 btrfs_set_file_extent_type(leaf, fi,
669 BTRFS_FILE_EXTENT_REG);
670 btrfs_mark_buffer_dirty(leaf);
671 goto out;
672 }
673
674 fi = btrfs_item_ptr(leaf, del_slot - 1,
675 struct btrfs_file_extent_item);
676 btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
677 btrfs_set_file_extent_num_bytes(leaf, fi,
678 extent_end - key.offset);
679 btrfs_mark_buffer_dirty(leaf);
680
681 ret = btrfs_del_items(trans, root, path, del_slot, del_nr);
682 BUG_ON(ret);
683out:
817 btrfs_free_path(path); 684 btrfs_free_path(path);
818 return 0; 685 return 0;
819} 686}