aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_bmap.c416
1 files changed, 173 insertions, 243 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index d9de5ae1fd5c..0c9be0ed606e 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -50,17 +50,22 @@
50#include "xfs_trace.h" 50#include "xfs_trace.h"
51 51
52 52
53#ifdef DEBUG
54STATIC void
55xfs_bmap_check_leaf_extents(xfs_btree_cur_t *cur, xfs_inode_t *ip, int whichfork);
56#endif
57
58kmem_zone_t *xfs_bmap_free_item_zone; 53kmem_zone_t *xfs_bmap_free_item_zone;
59 54
60/* 55/*
61 * Prototypes for internal bmap routines. 56 * Prototypes for internal bmap routines.
62 */ 57 */
63 58
59#ifdef DEBUG
60STATIC void
61xfs_bmap_check_leaf_extents(
62 struct xfs_btree_cur *cur,
63 struct xfs_inode *ip,
64 int whichfork);
65#else
66#define xfs_bmap_check_leaf_extents(cur, ip, whichfork) do { } while (0)
67#endif
68
64 69
65/* 70/*
66 * Called from xfs_bmap_add_attrfork to handle extents format files. 71 * Called from xfs_bmap_add_attrfork to handle extents format files.
@@ -85,47 +90,6 @@ xfs_bmap_add_attrfork_local(
85 int *flags); /* inode logging flags */ 90 int *flags); /* inode logging flags */
86 91
87/* 92/*
88 * Called by xfs_bmap_add_extent to handle cases converting a delayed
89 * allocation to a real allocation.
90 */
91STATIC int /* error */
92xfs_bmap_add_extent_delay_real(
93 struct xfs_trans *tp, /* transaction pointer */
94 xfs_inode_t *ip, /* incore inode pointer */
95 xfs_extnum_t *idx, /* extent number to update/insert */
96 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */
97 xfs_bmbt_irec_t *new, /* new data to add to file extents */
98 xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */
99 xfs_fsblock_t *first, /* pointer to firstblock variable */
100 xfs_bmap_free_t *flist, /* list of extents to be freed */
101 int *logflagsp); /* inode logging flags */
102
103/*
104 * Called by xfs_bmap_add_extent to handle cases converting a hole
105 * to a real allocation.
106 */
107STATIC int /* error */
108xfs_bmap_add_extent_hole_real(
109 xfs_inode_t *ip, /* incore inode pointer */
110 xfs_extnum_t *idx, /* extent number to update/insert */
111 xfs_btree_cur_t *cur, /* if null, not a btree */
112 xfs_bmbt_irec_t *new, /* new data to add to file extents */
113 int *logflagsp, /* inode logging flags */
114 int whichfork); /* data or attr fork */
115
116/*
117 * Called by xfs_bmap_add_extent to handle cases converting an unwritten
118 * allocation to a real allocation or vice versa.
119 */
120STATIC int /* error */
121xfs_bmap_add_extent_unwritten_real(
122 xfs_inode_t *ip, /* incore inode pointer */
123 xfs_extnum_t *idx, /* extent number to update/insert */
124 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */
125 xfs_bmbt_irec_t *new, /* new data to add to file extents */
126 int *logflagsp); /* inode logging flags */
127
128/*
129 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. 93 * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file.
130 * It figures out where to ask the underlying allocator to put the new extent. 94 * It figures out where to ask the underlying allocator to put the new extent.
131 */ 95 */
@@ -407,147 +371,7 @@ xfs_bmap_add_attrfork_local(
407} 371}
408 372
409/* 373/*
410 * Update file extent records and the btree after allocating space. 374 * Convert a delayed allocation to a real allocation.
411 */
412STATIC int /* error */
413xfs_bmap_add_extent(
414 struct xfs_trans *tp, /* transaction pointer */
415 xfs_inode_t *ip, /* incore inode pointer */
416 xfs_extnum_t *idx, /* extent number to update/insert */
417 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */
418 xfs_bmbt_irec_t *new, /* new data to add to file extents */
419 xfs_fsblock_t *first, /* pointer to firstblock variable */
420 xfs_bmap_free_t *flist, /* list of extents to be freed */
421 int *logflagsp, /* inode logging flags */
422 int whichfork) /* data or attr fork */
423{
424 xfs_btree_cur_t *cur; /* btree cursor or null */
425 xfs_filblks_t da_new; /* new count del alloc blocks used */
426 xfs_filblks_t da_old; /* old count del alloc blocks used */
427 int error; /* error return value */
428 xfs_ifork_t *ifp; /* inode fork ptr */
429 int logflags; /* returned value */
430 xfs_extnum_t nextents; /* number of extents in file now */
431
432 XFS_STATS_INC(xs_add_exlist);
433
434 cur = *curp;
435 ifp = XFS_IFORK_PTR(ip, whichfork);
436 nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
437 da_old = da_new = 0;
438 error = 0;
439
440 ASSERT(*idx >= 0);
441 ASSERT(*idx <= nextents);
442 ASSERT(!isnullstartblock(new->br_startblock));
443
444 /*
445 * Real allocation off the end of the file.
446 */
447 if (*idx == nextents) {
448 if (cur)
449 ASSERT((cur->bc_private.b.flags &
450 XFS_BTCUR_BPRV_WASDEL) == 0);
451 error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new,
452 &logflags, whichfork);
453 } else {
454 xfs_bmbt_irec_t prev; /* old extent at offset idx */
455
456 /*
457 * Get the record referred to by idx.
458 */
459 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &prev);
460 /*
461 * If it's a real allocation record, and the new allocation ends
462 * after the start of the referred to record, then we're filling
463 * in a delayed or unwritten allocation with a real one, or
464 * converting real back to unwritten.
465 */
466 if (!isnullstartblock(new->br_startblock) &&
467 new->br_startoff + new->br_blockcount > prev.br_startoff) {
468 if (prev.br_state != XFS_EXT_UNWRITTEN &&
469 isnullstartblock(prev.br_startblock)) {
470 da_old = startblockval(prev.br_startblock);
471 if (cur)
472 ASSERT(cur->bc_private.b.flags &
473 XFS_BTCUR_BPRV_WASDEL);
474 error = xfs_bmap_add_extent_delay_real(tp, ip,
475 idx, &cur, new, &da_new,
476 first, flist, &logflags);
477 } else {
478 ASSERT(new->br_state == XFS_EXT_NORM ||
479 new->br_state == XFS_EXT_UNWRITTEN);
480
481 error = xfs_bmap_add_extent_unwritten_real(ip,
482 idx, &cur, new, &logflags);
483 if (error)
484 goto done;
485 }
486 }
487 /*
488 * Otherwise we're filling in a hole with an allocation.
489 */
490 else {
491 if (cur)
492 ASSERT((cur->bc_private.b.flags &
493 XFS_BTCUR_BPRV_WASDEL) == 0);
494 error = xfs_bmap_add_extent_hole_real(ip, idx, cur,
495 new, &logflags, whichfork);
496 }
497 }
498
499 if (error)
500 goto done;
501 ASSERT(*curp == cur || *curp == NULL);
502
503 /*
504 * Convert to a btree if necessary.
505 */
506 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
507 XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
508 int tmp_logflags; /* partial log flag return val */
509
510 ASSERT(cur == NULL);
511 error = xfs_bmap_extents_to_btree(tp, ip, first,
512 flist, &cur, da_old > 0, &tmp_logflags, whichfork);
513 logflags |= tmp_logflags;
514 if (error)
515 goto done;
516 }
517 /*
518 * Adjust for changes in reserved delayed indirect blocks.
519 * Nothing to do for disk quotas here.
520 */
521 if (da_old || da_new) {
522 xfs_filblks_t nblks;
523
524 nblks = da_new;
525 if (cur)
526 nblks += cur->bc_private.b.allocated;
527 ASSERT(nblks <= da_old);
528 if (nblks < da_old)
529 xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
530 (int64_t)(da_old - nblks), 0);
531 }
532 /*
533 * Clear out the allocated field, done with it now in any case.
534 */
535 if (cur) {
536 cur->bc_private.b.allocated = 0;
537 *curp = cur;
538 }
539done:
540#ifdef DEBUG
541 if (!error)
542 xfs_bmap_check_leaf_extents(*curp, ip, whichfork);
543#endif
544 *logflagsp = logflags;
545 return error;
546}
547
548/*
549 * Called by xfs_bmap_add_extent to handle cases converting a delayed
550 * allocation to a real allocation.
551 */ 375 */
552STATIC int /* error */ 376STATIC int /* error */
553xfs_bmap_add_extent_delay_real( 377xfs_bmap_add_extent_delay_real(
@@ -556,7 +380,6 @@ xfs_bmap_add_extent_delay_real(
556 xfs_extnum_t *idx, /* extent number to update/insert */ 380 xfs_extnum_t *idx, /* extent number to update/insert */
557 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ 381 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */
558 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 382 xfs_bmbt_irec_t *new, /* new data to add to file extents */
559 xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */
560 xfs_fsblock_t *first, /* pointer to firstblock variable */ 383 xfs_fsblock_t *first, /* pointer to firstblock variable */
561 xfs_bmap_free_t *flist, /* list of extents to be freed */ 384 xfs_bmap_free_t *flist, /* list of extents to be freed */
562 int *logflagsp) /* inode logging flags */ 385 int *logflagsp) /* inode logging flags */
@@ -572,10 +395,24 @@ xfs_bmap_add_extent_delay_real(
572 /* left is 0, right is 1, prev is 2 */ 395 /* left is 0, right is 1, prev is 2 */
573 int rval=0; /* return value (logging flags) */ 396 int rval=0; /* return value (logging flags) */
574 int state = 0;/* state bits, accessed thru macros */ 397 int state = 0;/* state bits, accessed thru macros */
575 xfs_filblks_t temp=0; /* value for dnew calculations */ 398 xfs_filblks_t da_new; /* new count del alloc blocks used */
576 xfs_filblks_t temp2=0;/* value for dnew calculations */ 399 xfs_filblks_t da_old; /* old count del alloc blocks used */
400 xfs_filblks_t temp=0; /* value for da_new calculations */
401 xfs_filblks_t temp2=0;/* value for da_new calculations */
577 int tmp_rval; /* partial logging flags */ 402 int tmp_rval; /* partial logging flags */
578 403
404 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
405 cur = *curp;
406
407 ASSERT(*idx >= 0);
408 ASSERT(*idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
409 ASSERT(!isnullstartblock(new->br_startblock));
410 ASSERT(!cur || (cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL));
411
412 XFS_STATS_INC(xs_add_exlist);
413
414 *logflagsp = 0;
415
579#define LEFT r[0] 416#define LEFT r[0]
580#define RIGHT r[1] 417#define RIGHT r[1]
581#define PREV r[2] 418#define PREV r[2]
@@ -583,14 +420,15 @@ xfs_bmap_add_extent_delay_real(
583 /* 420 /*
584 * Set up a bunch of variables to make the tests simpler. 421 * Set up a bunch of variables to make the tests simpler.
585 */ 422 */
586 cur = *curp;
587 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
588 ep = xfs_iext_get_ext(ifp, *idx); 423 ep = xfs_iext_get_ext(ifp, *idx);
589 xfs_bmbt_get_all(ep, &PREV); 424 xfs_bmbt_get_all(ep, &PREV);
590 new_endoff = new->br_startoff + new->br_blockcount; 425 new_endoff = new->br_startoff + new->br_blockcount;
591 ASSERT(PREV.br_startoff <= new->br_startoff); 426 ASSERT(PREV.br_startoff <= new->br_startoff);
592 ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff); 427 ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);
593 428
429 da_old = startblockval(PREV.br_startblock);
430 da_new = 0;
431
594 /* 432 /*
595 * Set flags determining what part of the previous delayed allocation 433 * Set flags determining what part of the previous delayed allocation
596 * extent is being replaced by a real allocation. 434 * extent is being replaced by a real allocation.
@@ -688,7 +526,6 @@ xfs_bmap_add_extent_delay_real(
688 RIGHT.br_blockcount, LEFT.br_state))) 526 RIGHT.br_blockcount, LEFT.br_state)))
689 goto done; 527 goto done;
690 } 528 }
691 *dnew = 0;
692 break; 529 break;
693 530
694 case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: 531 case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG:
@@ -719,7 +556,6 @@ xfs_bmap_add_extent_delay_real(
719 PREV.br_blockcount, LEFT.br_state))) 556 PREV.br_blockcount, LEFT.br_state)))
720 goto done; 557 goto done;
721 } 558 }
722 *dnew = 0;
723 break; 559 break;
724 560
725 case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: 561 case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
@@ -749,8 +585,6 @@ xfs_bmap_add_extent_delay_real(
749 RIGHT.br_blockcount, PREV.br_state))) 585 RIGHT.br_blockcount, PREV.br_state)))
750 goto done; 586 goto done;
751 } 587 }
752
753 *dnew = 0;
754 break; 588 break;
755 589
756 case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: 590 case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING:
@@ -778,8 +612,6 @@ xfs_bmap_add_extent_delay_real(
778 goto done; 612 goto done;
779 XFS_WANT_CORRUPTED_GOTO(i == 1, done); 613 XFS_WANT_CORRUPTED_GOTO(i == 1, done);
780 } 614 }
781
782 *dnew = 0;
783 break; 615 break;
784 616
785 case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: 617 case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG:
@@ -813,13 +645,12 @@ xfs_bmap_add_extent_delay_real(
813 LEFT.br_state))) 645 LEFT.br_state)))
814 goto done; 646 goto done;
815 } 647 }
816 temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), 648 da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
817 startblockval(PREV.br_startblock)); 649 startblockval(PREV.br_startblock));
818 xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); 650 xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
819 trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); 651 trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
820 652
821 --*idx; 653 --*idx;
822 *dnew = temp;
823 break; 654 break;
824 655
825 case BMAP_LEFT_FILLING: 656 case BMAP_LEFT_FILLING:
@@ -856,14 +687,12 @@ xfs_bmap_add_extent_delay_real(
856 if (error) 687 if (error)
857 goto done; 688 goto done;
858 } 689 }
859 temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), 690 da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
860 startblockval(PREV.br_startblock) - 691 startblockval(PREV.br_startblock) -
861 (cur ? cur->bc_private.b.allocated : 0)); 692 (cur ? cur->bc_private.b.allocated : 0));
862 ep = xfs_iext_get_ext(ifp, *idx + 1); 693 ep = xfs_iext_get_ext(ifp, *idx + 1);
863 xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); 694 xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
864 trace_xfs_bmap_post_update(ip, *idx + 1, state, _THIS_IP_); 695 trace_xfs_bmap_post_update(ip, *idx + 1, state, _THIS_IP_);
865
866 *dnew = temp;
867 break; 696 break;
868 697
869 case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: 698 case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG:
@@ -896,14 +725,13 @@ xfs_bmap_add_extent_delay_real(
896 goto done; 725 goto done;
897 } 726 }
898 727
899 temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), 728 da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
900 startblockval(PREV.br_startblock)); 729 startblockval(PREV.br_startblock));
901 trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); 730 trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_);
902 xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); 731 xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
903 trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); 732 trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
904 733
905 ++*idx; 734 ++*idx;
906 *dnew = temp;
907 break; 735 break;
908 736
909 case BMAP_RIGHT_FILLING: 737 case BMAP_RIGHT_FILLING:
@@ -939,15 +767,14 @@ xfs_bmap_add_extent_delay_real(
939 if (error) 767 if (error)
940 goto done; 768 goto done;
941 } 769 }
942 temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), 770 da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp),
943 startblockval(PREV.br_startblock) - 771 startblockval(PREV.br_startblock) -
944 (cur ? cur->bc_private.b.allocated : 0)); 772 (cur ? cur->bc_private.b.allocated : 0));
945 ep = xfs_iext_get_ext(ifp, *idx); 773 ep = xfs_iext_get_ext(ifp, *idx);
946 xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); 774 xfs_bmbt_set_startblock(ep, nullstartblock(da_new));
947 trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); 775 trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_);
948 776
949 ++*idx; 777 ++*idx;
950 *dnew = temp;
951 break; 778 break;
952 779
953 case 0: 780 case 0:
@@ -1029,7 +856,7 @@ xfs_bmap_add_extent_delay_real(
1029 trace_xfs_bmap_post_update(ip, *idx + 2, state, _THIS_IP_); 856 trace_xfs_bmap_post_update(ip, *idx + 2, state, _THIS_IP_);
1030 857
1031 ++*idx; 858 ++*idx;
1032 *dnew = temp + temp2; 859 da_new = temp + temp2;
1033 break; 860 break;
1034 861
1035 case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: 862 case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG:
@@ -1044,9 +871,39 @@ xfs_bmap_add_extent_delay_real(
1044 */ 871 */
1045 ASSERT(0); 872 ASSERT(0);
1046 } 873 }
1047 *curp = cur; 874
875 /* convert to a btree if necessary */
876 if (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS &&
877 XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > ifp->if_ext_max) {
878 int tmp_logflags; /* partial log flag return val */
879
880 ASSERT(cur == NULL);
881 error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur,
882 da_old > 0, &tmp_logflags, XFS_DATA_FORK);
883 *logflagsp |= tmp_logflags;
884 if (error)
885 goto done;
886 }
887
888 /* adjust for changes in reserved delayed indirect blocks */
889 if (da_old || da_new) {
890 temp = da_new;
891 if (cur)
892 temp += cur->bc_private.b.allocated;
893 ASSERT(temp <= da_old);
894 if (temp < da_old)
895 xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS,
896 (int64_t)(da_old - temp), 0);
897 }
898
899 /* clear out the allocated field, done with it now in any case. */
900 if (cur) {
901 cur->bc_private.b.allocated = 0;
902 *curp = cur;
903 }
904 xfs_bmap_check_leaf_extents(cur, ip, XFS_DATA_FORK);
1048done: 905done:
1049 *logflagsp = rval; 906 *logflagsp |= rval;
1050 return error; 907 return error;
1051#undef LEFT 908#undef LEFT
1052#undef RIGHT 909#undef RIGHT
@@ -1054,15 +911,17 @@ done:
1054} 911}
1055 912
1056/* 913/*
1057 * Called by xfs_bmap_add_extent to handle cases converting an unwritten 914 * Convert an unwritten allocation to a real allocation or vice versa.
1058 * allocation to a real allocation or vice versa.
1059 */ 915 */
1060STATIC int /* error */ 916STATIC int /* error */
1061xfs_bmap_add_extent_unwritten_real( 917xfs_bmap_add_extent_unwritten_real(
918 struct xfs_trans *tp,
1062 xfs_inode_t *ip, /* incore inode pointer */ 919 xfs_inode_t *ip, /* incore inode pointer */
1063 xfs_extnum_t *idx, /* extent number to update/insert */ 920 xfs_extnum_t *idx, /* extent number to update/insert */
1064 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ 921 xfs_btree_cur_t **curp, /* if *curp is null, not a btree */
1065 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 922 xfs_bmbt_irec_t *new, /* new data to add to file extents */
923 xfs_fsblock_t *first, /* pointer to firstblock variable */
924 xfs_bmap_free_t *flist, /* list of extents to be freed */
1066 int *logflagsp) /* inode logging flags */ 925 int *logflagsp) /* inode logging flags */
1067{ 926{
1068 xfs_btree_cur_t *cur; /* btree cursor */ 927 xfs_btree_cur_t *cur; /* btree cursor */
@@ -1078,15 +937,25 @@ xfs_bmap_add_extent_unwritten_real(
1078 int rval=0; /* return value (logging flags) */ 937 int rval=0; /* return value (logging flags) */
1079 int state = 0;/* state bits, accessed thru macros */ 938 int state = 0;/* state bits, accessed thru macros */
1080 939
940 *logflagsp = 0;
941
942 cur = *curp;
943 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
944
945 ASSERT(*idx >= 0);
946 ASSERT(*idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
947 ASSERT(!isnullstartblock(new->br_startblock));
948
949 XFS_STATS_INC(xs_add_exlist);
950
1081#define LEFT r[0] 951#define LEFT r[0]
1082#define RIGHT r[1] 952#define RIGHT r[1]
1083#define PREV r[2] 953#define PREV r[2]
954
1084 /* 955 /*
1085 * Set up a bunch of variables to make the tests simpler. 956 * Set up a bunch of variables to make the tests simpler.
1086 */ 957 */
1087 error = 0; 958 error = 0;
1088 cur = *curp;
1089 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1090 ep = xfs_iext_get_ext(ifp, *idx); 959 ep = xfs_iext_get_ext(ifp, *idx);
1091 xfs_bmbt_get_all(ep, &PREV); 960 xfs_bmbt_get_all(ep, &PREV);
1092 newext = new->br_state; 961 newext = new->br_state;
@@ -1537,9 +1406,29 @@ xfs_bmap_add_extent_unwritten_real(
1537 */ 1406 */
1538 ASSERT(0); 1407 ASSERT(0);
1539 } 1408 }
1540 *curp = cur; 1409
1410 /* convert to a btree if necessary */
1411 if (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS &&
1412 XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > ifp->if_ext_max) {
1413 int tmp_logflags; /* partial log flag return val */
1414
1415 ASSERT(cur == NULL);
1416 error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur,
1417 0, &tmp_logflags, XFS_DATA_FORK);
1418 *logflagsp |= tmp_logflags;
1419 if (error)
1420 goto done;
1421 }
1422
1423 /* clear out the allocated field, done with it now in any case. */
1424 if (cur) {
1425 cur->bc_private.b.allocated = 0;
1426 *curp = cur;
1427 }
1428
1429 xfs_bmap_check_leaf_extents(*curp, ip, XFS_DATA_FORK);
1541done: 1430done:
1542 *logflagsp = rval; 1431 *logflagsp |= rval;
1543 return error; 1432 return error;
1544#undef LEFT 1433#undef LEFT
1545#undef RIGHT 1434#undef RIGHT
@@ -1691,30 +1580,42 @@ xfs_bmap_add_extent_hole_delay(
1691} 1580}
1692 1581
1693/* 1582/*
1694 * Called by xfs_bmap_add_extent to handle cases converting a hole 1583 * Convert a hole to a real allocation.
1695 * to a real allocation.
1696 */ 1584 */
1697STATIC int /* error */ 1585STATIC int /* error */
1698xfs_bmap_add_extent_hole_real( 1586xfs_bmap_add_extent_hole_real(
1587 struct xfs_trans *tp,
1699 xfs_inode_t *ip, /* incore inode pointer */ 1588 xfs_inode_t *ip, /* incore inode pointer */
1700 xfs_extnum_t *idx, /* extent number to update/insert */ 1589 xfs_extnum_t *idx, /* extent number to update/insert */
1701 xfs_btree_cur_t *cur, /* if null, not a btree */ 1590 xfs_btree_cur_t **curp, /* if null, not a btree */
1702 xfs_bmbt_irec_t *new, /* new data to add to file extents */ 1591 xfs_bmbt_irec_t *new, /* new data to add to file extents */
1592 xfs_fsblock_t *first, /* pointer to firstblock variable */
1593 xfs_bmap_free_t *flist, /* list of extents to be freed */
1703 int *logflagsp, /* inode logging flags */ 1594 int *logflagsp, /* inode logging flags */
1704 int whichfork) /* data or attr fork */ 1595 int whichfork) /* data or attr fork */
1705{ 1596{
1706 int error; /* error return value */ 1597 int error; /* error return value */
1707 int i; /* temp state */ 1598 int i; /* temp state */
1599 xfs_btree_cur_t *cur; /* if null, not a btree */
1708 xfs_ifork_t *ifp; /* inode fork pointer */ 1600 xfs_ifork_t *ifp; /* inode fork pointer */
1709 xfs_bmbt_irec_t left; /* left neighbor extent entry */ 1601 xfs_bmbt_irec_t left; /* left neighbor extent entry */
1710 xfs_bmbt_irec_t right; /* right neighbor extent entry */ 1602 xfs_bmbt_irec_t right; /* right neighbor extent entry */
1711 int rval=0; /* return value (logging flags) */ 1603 int rval=0; /* return value (logging flags) */
1712 int state; /* state bits, accessed thru macros */ 1604 int state; /* state bits, accessed thru macros */
1713 1605
1606 *logflagsp = 0;
1607
1714 ifp = XFS_IFORK_PTR(ip, whichfork); 1608 ifp = XFS_IFORK_PTR(ip, whichfork);
1715 ASSERT(*idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); 1609 cur = *curp;
1716 state = 0; 1610
1611 ASSERT(*idx >= 0);
1612 ASSERT(*idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec));
1613 ASSERT(!isnullstartblock(new->br_startblock));
1614 ASSERT(!cur || !(cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL));
1615
1616 XFS_STATS_INC(xs_add_exlist);
1717 1617
1618 state = 0;
1718 if (whichfork == XFS_ATTR_FORK) 1619 if (whichfork == XFS_ATTR_FORK)
1719 state |= BMAP_ATTRFORK; 1620 state |= BMAP_ATTRFORK;
1720 1621
@@ -1897,8 +1798,28 @@ xfs_bmap_add_extent_hole_real(
1897 } 1798 }
1898 break; 1799 break;
1899 } 1800 }
1801
1802 /* convert to a btree if necessary */
1803 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS &&
1804 XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) {
1805 int tmp_logflags; /* partial log flag return val */
1806
1807 ASSERT(cur == NULL);
1808 error = xfs_bmap_extents_to_btree(tp, ip, first,
1809 flist, &cur, 0, &tmp_logflags, whichfork);
1810 *logflagsp |= tmp_logflags;
1811 if (error)
1812 goto done;
1813 }
1814
1815 /* clear out the allocated field, done with it now in any case. */
1816 if (cur) {
1817 cur->bc_private.b.allocated = 0;
1818 *curp = cur;
1819 }
1820 xfs_bmap_check_leaf_extents(cur, ip, whichfork);
1900done: 1821done:
1901 *logflagsp = rval; 1822 *logflagsp |= rval;
1902 return error; 1823 return error;
1903} 1824}
1904 1825
@@ -4792,14 +4713,22 @@ xfs_bmapi_allocate(
4792 xfs_sb_version_hasextflgbit(&mp->m_sb)) 4713 xfs_sb_version_hasextflgbit(&mp->m_sb))
4793 bma->gotp->br_state = XFS_EXT_UNWRITTEN; 4714 bma->gotp->br_state = XFS_EXT_UNWRITTEN;
4794 4715
4795 error = xfs_bmap_add_extent(bma->tp, bma->ip, lastx, cur, bma->gotp, 4716 if (bma->wasdel) {
4796 firstblock, flist, logflags, whichfork); 4717 error = xfs_bmap_add_extent_delay_real(bma->tp, bma->ip, lastx,
4718 cur, bma->gotp, firstblock, flist, logflags);
4719 } else {
4720 error = xfs_bmap_add_extent_hole_real(bma->tp, bma->ip, lastx,
4721 cur, bma->gotp, firstblock, flist, logflags,
4722 whichfork);
4723 }
4724
4797 if (error) 4725 if (error)
4798 return error; 4726 return error;
4799 4727
4800 /* 4728 /*
4801 * Update our extent pointer, given that xfs_bmap_add_extent might 4729 * Update our extent pointer, given that xfs_bmap_add_extent_delay_real
4802 * have merged it into one of the neighbouring ones. 4730 * or xfs_bmap_add_extent_hole_real might have merged it into one of
4731 * the neighbouring ones.
4803 */ 4732 */
4804 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), bma->gotp); 4733 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), bma->gotp);
4805 4734
@@ -4854,14 +4783,15 @@ xfs_bmapi_convert_unwritten(
4854 mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) 4783 mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN)
4855 ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; 4784 ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN;
4856 4785
4857 error = xfs_bmap_add_extent(bma->tp, bma->ip, lastx, cur, mval, 4786 error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, lastx,
4858 firstblock, flist, logflags, whichfork); 4787 cur, mval, firstblock, flist, logflags);
4859 if (error) 4788 if (error)
4860 return error; 4789 return error;
4861 4790
4862 /* 4791 /*
4863 * Update our extent pointer, given that xfs_bmap_add_extent might 4792 * Update our extent pointer, given that
4864 * have merged it into one of the neighbouring ones. 4793 * xfs_bmap_add_extent_unwritten_real might have merged it into one
4794 * of the neighbouring ones.
4865 */ 4795 */
4866 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), bma->gotp); 4796 xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), bma->gotp);
4867 4797
@@ -5287,9 +5217,9 @@ xfs_bunmapi(
5287 del.br_blockcount = mod; 5217 del.br_blockcount = mod;
5288 } 5218 }
5289 del.br_state = XFS_EXT_UNWRITTEN; 5219 del.br_state = XFS_EXT_UNWRITTEN;
5290 error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &del, 5220 error = xfs_bmap_add_extent_unwritten_real(tp, ip,
5291 firstblock, flist, &logflags, 5221 &lastx, &cur, &del, firstblock, flist,
5292 XFS_DATA_FORK); 5222 &logflags);
5293 if (error) 5223 if (error)
5294 goto error0; 5224 goto error0;
5295 goto nodelete; 5225 goto nodelete;
@@ -5345,18 +5275,18 @@ xfs_bunmapi(
5345 } 5275 }
5346 prev.br_state = XFS_EXT_UNWRITTEN; 5276 prev.br_state = XFS_EXT_UNWRITTEN;
5347 lastx--; 5277 lastx--;
5348 error = xfs_bmap_add_extent(tp, ip, &lastx, 5278 error = xfs_bmap_add_extent_unwritten_real(tp,
5349 &cur, &prev, firstblock, flist, 5279 ip, &lastx, &cur, &prev,
5350 &logflags, XFS_DATA_FORK); 5280 firstblock, flist, &logflags);
5351 if (error) 5281 if (error)
5352 goto error0; 5282 goto error0;
5353 goto nodelete; 5283 goto nodelete;
5354 } else { 5284 } else {
5355 ASSERT(del.br_state == XFS_EXT_NORM); 5285 ASSERT(del.br_state == XFS_EXT_NORM);
5356 del.br_state = XFS_EXT_UNWRITTEN; 5286 del.br_state = XFS_EXT_UNWRITTEN;
5357 error = xfs_bmap_add_extent(tp, ip, &lastx, 5287 error = xfs_bmap_add_extent_unwritten_real(tp,
5358 &cur, &del, firstblock, flist, 5288 ip, &lastx, &cur, &del,
5359 &logflags, XFS_DATA_FORK); 5289 firstblock, flist, &logflags);
5360 if (error) 5290 if (error)
5361 goto error0; 5291 goto error0;
5362 goto nodelete; 5292 goto nodelete;