aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_bmap.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-09-18 16:40:54 -0400
committerAlex Elder <aelder@sgi.com>2011-10-11 22:15:05 -0400
commita5bd606ba65f24e5990edfc0e7b52702720ee6fa (patch)
treea3492cb106bfaa0e5bc4c3b14c7b513ec01fcbbd /fs/xfs/xfs_bmap.c
parent27a3f8f2de758205765f277b3428bbf3d15da973 (diff)
xfs: remove xfs_bmap_add_extent
There is no real need to the xfs_bmap_add_extent, as the callers know what kind of extents they need to it. Removing it means duplicating the extents to btree conversion logic in three places, but overall it's still much simpler code and quite a bit less code. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-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;