diff options
Diffstat (limited to 'fs/xfs/xfs_bmap.c')
-rw-r--r-- | fs/xfs/xfs_bmap.c | 2531 |
1 files changed, 1261 insertions, 1270 deletions
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 452a291383ab..c68baeb0974a 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 | ||
54 | STATIC void | ||
55 | xfs_bmap_check_leaf_extents(xfs_btree_cur_t *cur, xfs_inode_t *ip, int whichfork); | ||
56 | #endif | ||
57 | |||
58 | kmem_zone_t *xfs_bmap_free_item_zone; | 53 | kmem_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 | ||
60 | STATIC void | ||
61 | xfs_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,58 +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 | */ | ||
91 | STATIC int /* error */ | ||
92 | xfs_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 delayed allocation. | ||
106 | */ | ||
107 | STATIC int /* error */ | ||
108 | xfs_bmap_add_extent_hole_delay( | ||
109 | xfs_inode_t *ip, /* incore inode pointer */ | ||
110 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
111 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
112 | int *logflagsp); /* inode logging flags */ | ||
113 | |||
114 | /* | ||
115 | * Called by xfs_bmap_add_extent to handle cases converting a hole | ||
116 | * to a real allocation. | ||
117 | */ | ||
118 | STATIC int /* error */ | ||
119 | xfs_bmap_add_extent_hole_real( | ||
120 | xfs_inode_t *ip, /* incore inode pointer */ | ||
121 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
122 | xfs_btree_cur_t *cur, /* if null, not a btree */ | ||
123 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
124 | int *logflagsp, /* inode logging flags */ | ||
125 | int whichfork); /* data or attr fork */ | ||
126 | |||
127 | /* | ||
128 | * Called by xfs_bmap_add_extent to handle cases converting an unwritten | ||
129 | * allocation to a real allocation or vice versa. | ||
130 | */ | ||
131 | STATIC int /* error */ | ||
132 | xfs_bmap_add_extent_unwritten_real( | ||
133 | xfs_inode_t *ip, /* incore inode pointer */ | ||
134 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
135 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | ||
136 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
137 | int *logflagsp); /* inode logging flags */ | ||
138 | |||
139 | /* | ||
140 | * 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. |
141 | * 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. |
142 | */ | 95 | */ |
@@ -215,19 +168,6 @@ xfs_bmap_search_extents( | |||
215 | xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */ | 168 | xfs_bmbt_irec_t *prevp); /* out: previous extent entry found */ |
216 | 169 | ||
217 | /* | 170 | /* |
218 | * Check the last inode extent to determine whether this allocation will result | ||
219 | * in blocks being allocated at the end of the file. When we allocate new data | ||
220 | * blocks at the end of the file which do not start at the previous data block, | ||
221 | * we will try to align the new blocks at stripe unit boundaries. | ||
222 | */ | ||
223 | STATIC int /* error */ | ||
224 | xfs_bmap_isaeof( | ||
225 | xfs_inode_t *ip, /* incore inode pointer */ | ||
226 | xfs_fileoff_t off, /* file offset in fsblocks */ | ||
227 | int whichfork, /* data or attribute fork */ | ||
228 | char *aeof); /* return value */ | ||
229 | |||
230 | /* | ||
231 | * Compute the worst-case number of indirect blocks that will be used | 171 | * Compute the worst-case number of indirect blocks that will be used |
232 | * for ip's delayed extent of length "len". | 172 | * for ip's delayed extent of length "len". |
233 | */ | 173 | */ |
@@ -431,188 +371,13 @@ xfs_bmap_add_attrfork_local( | |||
431 | } | 371 | } |
432 | 372 | ||
433 | /* | 373 | /* |
434 | * Called by xfs_bmapi to update file extent records and the btree | 374 | * Convert a delayed allocation to a real allocation. |
435 | * after allocating space (or doing a delayed allocation). | ||
436 | */ | ||
437 | STATIC int /* error */ | ||
438 | xfs_bmap_add_extent( | ||
439 | struct xfs_trans *tp, /* transaction pointer */ | ||
440 | xfs_inode_t *ip, /* incore inode pointer */ | ||
441 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
442 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | ||
443 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
444 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | ||
445 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | ||
446 | int *logflagsp, /* inode logging flags */ | ||
447 | int whichfork) /* data or attr fork */ | ||
448 | { | ||
449 | xfs_btree_cur_t *cur; /* btree cursor or null */ | ||
450 | xfs_filblks_t da_new; /* new count del alloc blocks used */ | ||
451 | xfs_filblks_t da_old; /* old count del alloc blocks used */ | ||
452 | int error; /* error return value */ | ||
453 | xfs_ifork_t *ifp; /* inode fork ptr */ | ||
454 | int logflags; /* returned value */ | ||
455 | xfs_extnum_t nextents; /* number of extents in file now */ | ||
456 | |||
457 | XFS_STATS_INC(xs_add_exlist); | ||
458 | |||
459 | cur = *curp; | ||
460 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
461 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
462 | da_old = da_new = 0; | ||
463 | error = 0; | ||
464 | |||
465 | ASSERT(*idx >= 0); | ||
466 | ASSERT(*idx <= nextents); | ||
467 | |||
468 | /* | ||
469 | * This is the first extent added to a new/empty file. | ||
470 | * Special case this one, so other routines get to assume there are | ||
471 | * already extents in the list. | ||
472 | */ | ||
473 | if (nextents == 0) { | ||
474 | xfs_iext_insert(ip, *idx, 1, new, | ||
475 | whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0); | ||
476 | |||
477 | ASSERT(cur == NULL); | ||
478 | |||
479 | if (!isnullstartblock(new->br_startblock)) { | ||
480 | XFS_IFORK_NEXT_SET(ip, whichfork, 1); | ||
481 | logflags = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); | ||
482 | } else | ||
483 | logflags = 0; | ||
484 | } | ||
485 | /* | ||
486 | * Any kind of new delayed allocation goes here. | ||
487 | */ | ||
488 | else if (isnullstartblock(new->br_startblock)) { | ||
489 | if (cur) | ||
490 | ASSERT((cur->bc_private.b.flags & | ||
491 | XFS_BTCUR_BPRV_WASDEL) == 0); | ||
492 | error = xfs_bmap_add_extent_hole_delay(ip, idx, new, | ||
493 | &logflags); | ||
494 | } | ||
495 | /* | ||
496 | * Real allocation off the end of the file. | ||
497 | */ | ||
498 | else if (*idx == nextents) { | ||
499 | if (cur) | ||
500 | ASSERT((cur->bc_private.b.flags & | ||
501 | XFS_BTCUR_BPRV_WASDEL) == 0); | ||
502 | error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, | ||
503 | &logflags, whichfork); | ||
504 | } else { | ||
505 | xfs_bmbt_irec_t prev; /* old extent at offset idx */ | ||
506 | |||
507 | /* | ||
508 | * Get the record referred to by idx. | ||
509 | */ | ||
510 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &prev); | ||
511 | /* | ||
512 | * If it's a real allocation record, and the new allocation ends | ||
513 | * after the start of the referred to record, then we're filling | ||
514 | * in a delayed or unwritten allocation with a real one, or | ||
515 | * converting real back to unwritten. | ||
516 | */ | ||
517 | if (!isnullstartblock(new->br_startblock) && | ||
518 | new->br_startoff + new->br_blockcount > prev.br_startoff) { | ||
519 | if (prev.br_state != XFS_EXT_UNWRITTEN && | ||
520 | isnullstartblock(prev.br_startblock)) { | ||
521 | da_old = startblockval(prev.br_startblock); | ||
522 | if (cur) | ||
523 | ASSERT(cur->bc_private.b.flags & | ||
524 | XFS_BTCUR_BPRV_WASDEL); | ||
525 | error = xfs_bmap_add_extent_delay_real(tp, ip, | ||
526 | idx, &cur, new, &da_new, | ||
527 | first, flist, &logflags); | ||
528 | } else { | ||
529 | ASSERT(new->br_state == XFS_EXT_NORM || | ||
530 | new->br_state == XFS_EXT_UNWRITTEN); | ||
531 | |||
532 | error = xfs_bmap_add_extent_unwritten_real(ip, | ||
533 | idx, &cur, new, &logflags); | ||
534 | if (error) | ||
535 | goto done; | ||
536 | } | ||
537 | } | ||
538 | /* | ||
539 | * Otherwise we're filling in a hole with an allocation. | ||
540 | */ | ||
541 | else { | ||
542 | if (cur) | ||
543 | ASSERT((cur->bc_private.b.flags & | ||
544 | XFS_BTCUR_BPRV_WASDEL) == 0); | ||
545 | error = xfs_bmap_add_extent_hole_real(ip, idx, cur, | ||
546 | new, &logflags, whichfork); | ||
547 | } | ||
548 | } | ||
549 | |||
550 | if (error) | ||
551 | goto done; | ||
552 | ASSERT(*curp == cur || *curp == NULL); | ||
553 | |||
554 | /* | ||
555 | * Convert to a btree if necessary. | ||
556 | */ | ||
557 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && | ||
558 | XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max) { | ||
559 | int tmp_logflags; /* partial log flag return val */ | ||
560 | |||
561 | ASSERT(cur == NULL); | ||
562 | error = xfs_bmap_extents_to_btree(tp, ip, first, | ||
563 | flist, &cur, da_old > 0, &tmp_logflags, whichfork); | ||
564 | logflags |= tmp_logflags; | ||
565 | if (error) | ||
566 | goto done; | ||
567 | } | ||
568 | /* | ||
569 | * Adjust for changes in reserved delayed indirect blocks. | ||
570 | * Nothing to do for disk quotas here. | ||
571 | */ | ||
572 | if (da_old || da_new) { | ||
573 | xfs_filblks_t nblks; | ||
574 | |||
575 | nblks = da_new; | ||
576 | if (cur) | ||
577 | nblks += cur->bc_private.b.allocated; | ||
578 | ASSERT(nblks <= da_old); | ||
579 | if (nblks < da_old) | ||
580 | xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, | ||
581 | (int64_t)(da_old - nblks), 0); | ||
582 | } | ||
583 | /* | ||
584 | * Clear out the allocated field, done with it now in any case. | ||
585 | */ | ||
586 | if (cur) { | ||
587 | cur->bc_private.b.allocated = 0; | ||
588 | *curp = cur; | ||
589 | } | ||
590 | done: | ||
591 | #ifdef DEBUG | ||
592 | if (!error) | ||
593 | xfs_bmap_check_leaf_extents(*curp, ip, whichfork); | ||
594 | #endif | ||
595 | *logflagsp = logflags; | ||
596 | return error; | ||
597 | } | ||
598 | |||
599 | /* | ||
600 | * Called by xfs_bmap_add_extent to handle cases converting a delayed | ||
601 | * allocation to a real allocation. | ||
602 | */ | 375 | */ |
603 | STATIC int /* error */ | 376 | STATIC int /* error */ |
604 | xfs_bmap_add_extent_delay_real( | 377 | xfs_bmap_add_extent_delay_real( |
605 | struct xfs_trans *tp, /* transaction pointer */ | 378 | struct xfs_bmalloca *bma) |
606 | xfs_inode_t *ip, /* incore inode pointer */ | ||
607 | xfs_extnum_t *idx, /* extent number to update/insert */ | ||
608 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | ||
609 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
610 | xfs_filblks_t *dnew, /* new delayed-alloc indirect blocks */ | ||
611 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | ||
612 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | ||
613 | int *logflagsp) /* inode logging flags */ | ||
614 | { | 379 | { |
615 | xfs_btree_cur_t *cur; /* btree cursor */ | 380 | struct xfs_bmbt_irec *new = &bma->got; |
616 | int diff; /* temp value */ | 381 | int diff; /* temp value */ |
617 | xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ | 382 | xfs_bmbt_rec_host_t *ep; /* extent entry for idx */ |
618 | int error; /* error return value */ | 383 | int error; /* error return value */ |
@@ -623,10 +388,22 @@ xfs_bmap_add_extent_delay_real( | |||
623 | /* left is 0, right is 1, prev is 2 */ | 388 | /* left is 0, right is 1, prev is 2 */ |
624 | int rval=0; /* return value (logging flags) */ | 389 | int rval=0; /* return value (logging flags) */ |
625 | int state = 0;/* state bits, accessed thru macros */ | 390 | int state = 0;/* state bits, accessed thru macros */ |
626 | xfs_filblks_t temp=0; /* value for dnew calculations */ | 391 | xfs_filblks_t da_new; /* new count del alloc blocks used */ |
627 | xfs_filblks_t temp2=0;/* value for dnew calculations */ | 392 | xfs_filblks_t da_old; /* old count del alloc blocks used */ |
393 | xfs_filblks_t temp=0; /* value for da_new calculations */ | ||
394 | xfs_filblks_t temp2=0;/* value for da_new calculations */ | ||
628 | int tmp_rval; /* partial logging flags */ | 395 | int tmp_rval; /* partial logging flags */ |
629 | 396 | ||
397 | ifp = XFS_IFORK_PTR(bma->ip, XFS_DATA_FORK); | ||
398 | |||
399 | ASSERT(bma->idx >= 0); | ||
400 | ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); | ||
401 | ASSERT(!isnullstartblock(new->br_startblock)); | ||
402 | ASSERT(!bma->cur || | ||
403 | (bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); | ||
404 | |||
405 | XFS_STATS_INC(xs_add_exlist); | ||
406 | |||
630 | #define LEFT r[0] | 407 | #define LEFT r[0] |
631 | #define RIGHT r[1] | 408 | #define RIGHT r[1] |
632 | #define PREV r[2] | 409 | #define PREV r[2] |
@@ -634,14 +411,15 @@ xfs_bmap_add_extent_delay_real( | |||
634 | /* | 411 | /* |
635 | * Set up a bunch of variables to make the tests simpler. | 412 | * Set up a bunch of variables to make the tests simpler. |
636 | */ | 413 | */ |
637 | cur = *curp; | 414 | ep = xfs_iext_get_ext(ifp, bma->idx); |
638 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
639 | ep = xfs_iext_get_ext(ifp, *idx); | ||
640 | xfs_bmbt_get_all(ep, &PREV); | 415 | xfs_bmbt_get_all(ep, &PREV); |
641 | new_endoff = new->br_startoff + new->br_blockcount; | 416 | new_endoff = new->br_startoff + new->br_blockcount; |
642 | ASSERT(PREV.br_startoff <= new->br_startoff); | 417 | ASSERT(PREV.br_startoff <= new->br_startoff); |
643 | ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff); | 418 | ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff); |
644 | 419 | ||
420 | da_old = startblockval(PREV.br_startblock); | ||
421 | da_new = 0; | ||
422 | |||
645 | /* | 423 | /* |
646 | * Set flags determining what part of the previous delayed allocation | 424 | * Set flags determining what part of the previous delayed allocation |
647 | * extent is being replaced by a real allocation. | 425 | * extent is being replaced by a real allocation. |
@@ -655,9 +433,9 @@ xfs_bmap_add_extent_delay_real( | |||
655 | * Check and set flags if this segment has a left neighbor. | 433 | * Check and set flags if this segment has a left neighbor. |
656 | * Don't set contiguous if the combined extent would be too large. | 434 | * Don't set contiguous if the combined extent would be too large. |
657 | */ | 435 | */ |
658 | if (*idx > 0) { | 436 | if (bma->idx > 0) { |
659 | state |= BMAP_LEFT_VALID; | 437 | state |= BMAP_LEFT_VALID; |
660 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &LEFT); | 438 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &LEFT); |
661 | 439 | ||
662 | if (isnullstartblock(LEFT.br_startblock)) | 440 | if (isnullstartblock(LEFT.br_startblock)) |
663 | state |= BMAP_LEFT_DELAY; | 441 | state |= BMAP_LEFT_DELAY; |
@@ -675,9 +453,9 @@ xfs_bmap_add_extent_delay_real( | |||
675 | * Don't set contiguous if the combined extent would be too large. | 453 | * Don't set contiguous if the combined extent would be too large. |
676 | * Also check for all-three-contiguous being too large. | 454 | * Also check for all-three-contiguous being too large. |
677 | */ | 455 | */ |
678 | if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { | 456 | if (bma->idx < bma->ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1) { |
679 | state |= BMAP_RIGHT_VALID; | 457 | state |= BMAP_RIGHT_VALID; |
680 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx + 1), &RIGHT); | 458 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx + 1), &RIGHT); |
681 | 459 | ||
682 | if (isnullstartblock(RIGHT.br_startblock)) | 460 | if (isnullstartblock(RIGHT.br_startblock)) |
683 | state |= BMAP_RIGHT_DELAY; | 461 | state |= BMAP_RIGHT_DELAY; |
@@ -708,38 +486,41 @@ xfs_bmap_add_extent_delay_real( | |||
708 | * Filling in all of a previously delayed allocation extent. | 486 | * Filling in all of a previously delayed allocation extent. |
709 | * The left and right neighbors are both contiguous with new. | 487 | * The left and right neighbors are both contiguous with new. |
710 | */ | 488 | */ |
711 | --*idx; | 489 | bma->idx--; |
712 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 490 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
713 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), | 491 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), |
714 | LEFT.br_blockcount + PREV.br_blockcount + | 492 | LEFT.br_blockcount + PREV.br_blockcount + |
715 | RIGHT.br_blockcount); | 493 | RIGHT.br_blockcount); |
716 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 494 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
717 | 495 | ||
718 | xfs_iext_remove(ip, *idx + 1, 2, state); | 496 | xfs_iext_remove(bma->ip, bma->idx + 1, 2, state); |
719 | ip->i_d.di_nextents--; | 497 | bma->ip->i_d.di_nextents--; |
720 | if (cur == NULL) | 498 | if (bma->cur == NULL) |
721 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 499 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
722 | else { | 500 | else { |
723 | rval = XFS_ILOG_CORE; | 501 | rval = XFS_ILOG_CORE; |
724 | if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, | 502 | error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, |
725 | RIGHT.br_startblock, | 503 | RIGHT.br_startblock, |
726 | RIGHT.br_blockcount, &i))) | 504 | RIGHT.br_blockcount, &i); |
505 | if (error) | ||
727 | goto done; | 506 | goto done; |
728 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 507 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
729 | if ((error = xfs_btree_delete(cur, &i))) | 508 | error = xfs_btree_delete(bma->cur, &i); |
509 | if (error) | ||
730 | goto done; | 510 | goto done; |
731 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 511 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
732 | if ((error = xfs_btree_decrement(cur, 0, &i))) | 512 | error = xfs_btree_decrement(bma->cur, 0, &i); |
513 | if (error) | ||
733 | goto done; | 514 | goto done; |
734 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 515 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
735 | if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, | 516 | error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, |
736 | LEFT.br_startblock, | 517 | LEFT.br_startblock, |
737 | LEFT.br_blockcount + | 518 | LEFT.br_blockcount + |
738 | PREV.br_blockcount + | 519 | PREV.br_blockcount + |
739 | RIGHT.br_blockcount, LEFT.br_state))) | 520 | RIGHT.br_blockcount, LEFT.br_state); |
521 | if (error) | ||
740 | goto done; | 522 | goto done; |
741 | } | 523 | } |
742 | *dnew = 0; | ||
743 | break; | 524 | break; |
744 | 525 | ||
745 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: | 526 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_LEFT_CONTIG: |
@@ -747,30 +528,31 @@ xfs_bmap_add_extent_delay_real( | |||
747 | * Filling in all of a previously delayed allocation extent. | 528 | * Filling in all of a previously delayed allocation extent. |
748 | * The left neighbor is contiguous, the right is not. | 529 | * The left neighbor is contiguous, the right is not. |
749 | */ | 530 | */ |
750 | --*idx; | 531 | bma->idx--; |
751 | 532 | ||
752 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 533 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
753 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), | 534 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), |
754 | LEFT.br_blockcount + PREV.br_blockcount); | 535 | LEFT.br_blockcount + PREV.br_blockcount); |
755 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 536 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
756 | 537 | ||
757 | xfs_iext_remove(ip, *idx + 1, 1, state); | 538 | xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); |
758 | if (cur == NULL) | 539 | if (bma->cur == NULL) |
759 | rval = XFS_ILOG_DEXT; | 540 | rval = XFS_ILOG_DEXT; |
760 | else { | 541 | else { |
761 | rval = 0; | 542 | rval = 0; |
762 | if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff, | 543 | error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff, |
763 | LEFT.br_startblock, LEFT.br_blockcount, | 544 | LEFT.br_startblock, LEFT.br_blockcount, |
764 | &i))) | 545 | &i); |
546 | if (error) | ||
765 | goto done; | 547 | goto done; |
766 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 548 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
767 | if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, | 549 | error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, |
768 | LEFT.br_startblock, | 550 | LEFT.br_startblock, |
769 | LEFT.br_blockcount + | 551 | LEFT.br_blockcount + |
770 | PREV.br_blockcount, LEFT.br_state))) | 552 | PREV.br_blockcount, LEFT.br_state); |
553 | if (error) | ||
771 | goto done; | 554 | goto done; |
772 | } | 555 | } |
773 | *dnew = 0; | ||
774 | break; | 556 | break; |
775 | 557 | ||
776 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: | 558 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: |
@@ -778,30 +560,30 @@ xfs_bmap_add_extent_delay_real( | |||
778 | * Filling in all of a previously delayed allocation extent. | 560 | * Filling in all of a previously delayed allocation extent. |
779 | * The right neighbor is contiguous, the left is not. | 561 | * The right neighbor is contiguous, the left is not. |
780 | */ | 562 | */ |
781 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 563 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
782 | xfs_bmbt_set_startblock(ep, new->br_startblock); | 564 | xfs_bmbt_set_startblock(ep, new->br_startblock); |
783 | xfs_bmbt_set_blockcount(ep, | 565 | xfs_bmbt_set_blockcount(ep, |
784 | PREV.br_blockcount + RIGHT.br_blockcount); | 566 | PREV.br_blockcount + RIGHT.br_blockcount); |
785 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 567 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
786 | 568 | ||
787 | xfs_iext_remove(ip, *idx + 1, 1, state); | 569 | xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); |
788 | if (cur == NULL) | 570 | if (bma->cur == NULL) |
789 | rval = XFS_ILOG_DEXT; | 571 | rval = XFS_ILOG_DEXT; |
790 | else { | 572 | else { |
791 | rval = 0; | 573 | rval = 0; |
792 | if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, | 574 | error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, |
793 | RIGHT.br_startblock, | 575 | RIGHT.br_startblock, |
794 | RIGHT.br_blockcount, &i))) | 576 | RIGHT.br_blockcount, &i); |
577 | if (error) | ||
795 | goto done; | 578 | goto done; |
796 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 579 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
797 | if ((error = xfs_bmbt_update(cur, PREV.br_startoff, | 580 | error = xfs_bmbt_update(bma->cur, PREV.br_startoff, |
798 | new->br_startblock, | 581 | new->br_startblock, |
799 | PREV.br_blockcount + | 582 | PREV.br_blockcount + |
800 | RIGHT.br_blockcount, PREV.br_state))) | 583 | RIGHT.br_blockcount, PREV.br_state); |
584 | if (error) | ||
801 | goto done; | 585 | goto done; |
802 | } | 586 | } |
803 | |||
804 | *dnew = 0; | ||
805 | break; | 587 | break; |
806 | 588 | ||
807 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: | 589 | case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING: |
@@ -810,27 +592,27 @@ xfs_bmap_add_extent_delay_real( | |||
810 | * Neither the left nor right neighbors are contiguous with | 592 | * Neither the left nor right neighbors are contiguous with |
811 | * the new one. | 593 | * the new one. |
812 | */ | 594 | */ |
813 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 595 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
814 | xfs_bmbt_set_startblock(ep, new->br_startblock); | 596 | xfs_bmbt_set_startblock(ep, new->br_startblock); |
815 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 597 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
816 | 598 | ||
817 | ip->i_d.di_nextents++; | 599 | bma->ip->i_d.di_nextents++; |
818 | if (cur == NULL) | 600 | if (bma->cur == NULL) |
819 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 601 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
820 | else { | 602 | else { |
821 | rval = XFS_ILOG_CORE; | 603 | rval = XFS_ILOG_CORE; |
822 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 604 | error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, |
823 | new->br_startblock, new->br_blockcount, | 605 | new->br_startblock, new->br_blockcount, |
824 | &i))) | 606 | &i); |
607 | if (error) | ||
825 | goto done; | 608 | goto done; |
826 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 609 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
827 | cur->bc_rec.b.br_state = XFS_EXT_NORM; | 610 | bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; |
828 | if ((error = xfs_btree_insert(cur, &i))) | 611 | error = xfs_btree_insert(bma->cur, &i); |
612 | if (error) | ||
829 | goto done; | 613 | goto done; |
830 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 614 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
831 | } | 615 | } |
832 | |||
833 | *dnew = 0; | ||
834 | break; | 616 | break; |
835 | 617 | ||
836 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: | 618 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG: |
@@ -838,39 +620,40 @@ xfs_bmap_add_extent_delay_real( | |||
838 | * Filling in the first part of a previous delayed allocation. | 620 | * Filling in the first part of a previous delayed allocation. |
839 | * The left neighbor is contiguous. | 621 | * The left neighbor is contiguous. |
840 | */ | 622 | */ |
841 | trace_xfs_bmap_pre_update(ip, *idx - 1, state, _THIS_IP_); | 623 | trace_xfs_bmap_pre_update(bma->ip, bma->idx - 1, state, _THIS_IP_); |
842 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx - 1), | 624 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx - 1), |
843 | LEFT.br_blockcount + new->br_blockcount); | 625 | LEFT.br_blockcount + new->br_blockcount); |
844 | xfs_bmbt_set_startoff(ep, | 626 | xfs_bmbt_set_startoff(ep, |
845 | PREV.br_startoff + new->br_blockcount); | 627 | PREV.br_startoff + new->br_blockcount); |
846 | trace_xfs_bmap_post_update(ip, *idx - 1, state, _THIS_IP_); | 628 | trace_xfs_bmap_post_update(bma->ip, bma->idx - 1, state, _THIS_IP_); |
847 | 629 | ||
848 | temp = PREV.br_blockcount - new->br_blockcount; | 630 | temp = PREV.br_blockcount - new->br_blockcount; |
849 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 631 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
850 | xfs_bmbt_set_blockcount(ep, temp); | 632 | xfs_bmbt_set_blockcount(ep, temp); |
851 | if (cur == NULL) | 633 | if (bma->cur == NULL) |
852 | rval = XFS_ILOG_DEXT; | 634 | rval = XFS_ILOG_DEXT; |
853 | else { | 635 | else { |
854 | rval = 0; | 636 | rval = 0; |
855 | if ((error = xfs_bmbt_lookup_eq(cur, LEFT.br_startoff, | 637 | error = xfs_bmbt_lookup_eq(bma->cur, LEFT.br_startoff, |
856 | LEFT.br_startblock, LEFT.br_blockcount, | 638 | LEFT.br_startblock, LEFT.br_blockcount, |
857 | &i))) | 639 | &i); |
640 | if (error) | ||
858 | goto done; | 641 | goto done; |
859 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 642 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
860 | if ((error = xfs_bmbt_update(cur, LEFT.br_startoff, | 643 | error = xfs_bmbt_update(bma->cur, LEFT.br_startoff, |
861 | LEFT.br_startblock, | 644 | LEFT.br_startblock, |
862 | LEFT.br_blockcount + | 645 | LEFT.br_blockcount + |
863 | new->br_blockcount, | 646 | new->br_blockcount, |
864 | LEFT.br_state))) | 647 | LEFT.br_state); |
648 | if (error) | ||
865 | goto done; | 649 | goto done; |
866 | } | 650 | } |
867 | temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), | 651 | da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), |
868 | startblockval(PREV.br_startblock)); | 652 | startblockval(PREV.br_startblock)); |
869 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 653 | xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); |
870 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 654 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
871 | 655 | ||
872 | --*idx; | 656 | bma->idx--; |
873 | *dnew = temp; | ||
874 | break; | 657 | break; |
875 | 658 | ||
876 | case BMAP_LEFT_FILLING: | 659 | case BMAP_LEFT_FILLING: |
@@ -878,43 +661,43 @@ xfs_bmap_add_extent_delay_real( | |||
878 | * Filling in the first part of a previous delayed allocation. | 661 | * Filling in the first part of a previous delayed allocation. |
879 | * The left neighbor is not contiguous. | 662 | * The left neighbor is not contiguous. |
880 | */ | 663 | */ |
881 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 664 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
882 | xfs_bmbt_set_startoff(ep, new_endoff); | 665 | xfs_bmbt_set_startoff(ep, new_endoff); |
883 | temp = PREV.br_blockcount - new->br_blockcount; | 666 | temp = PREV.br_blockcount - new->br_blockcount; |
884 | xfs_bmbt_set_blockcount(ep, temp); | 667 | xfs_bmbt_set_blockcount(ep, temp); |
885 | xfs_iext_insert(ip, *idx, 1, new, state); | 668 | xfs_iext_insert(bma->ip, bma->idx, 1, new, state); |
886 | ip->i_d.di_nextents++; | 669 | bma->ip->i_d.di_nextents++; |
887 | if (cur == NULL) | 670 | if (bma->cur == NULL) |
888 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 671 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
889 | else { | 672 | else { |
890 | rval = XFS_ILOG_CORE; | 673 | rval = XFS_ILOG_CORE; |
891 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 674 | error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, |
892 | new->br_startblock, new->br_blockcount, | 675 | new->br_startblock, new->br_blockcount, |
893 | &i))) | 676 | &i); |
677 | if (error) | ||
894 | goto done; | 678 | goto done; |
895 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 679 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
896 | cur->bc_rec.b.br_state = XFS_EXT_NORM; | 680 | bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; |
897 | if ((error = xfs_btree_insert(cur, &i))) | 681 | error = xfs_btree_insert(bma->cur, &i); |
682 | if (error) | ||
898 | goto done; | 683 | goto done; |
899 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 684 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
900 | } | 685 | } |
901 | if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && | 686 | if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && |
902 | ip->i_d.di_nextents > ip->i_df.if_ext_max) { | 687 | bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) { |
903 | error = xfs_bmap_extents_to_btree(tp, ip, | 688 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, |
904 | first, flist, &cur, 1, &tmp_rval, | 689 | bma->firstblock, bma->flist, |
905 | XFS_DATA_FORK); | 690 | &bma->cur, 1, &tmp_rval, XFS_DATA_FORK); |
906 | rval |= tmp_rval; | 691 | rval |= tmp_rval; |
907 | if (error) | 692 | if (error) |
908 | goto done; | 693 | goto done; |
909 | } | 694 | } |
910 | temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), | 695 | da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), |
911 | startblockval(PREV.br_startblock) - | 696 | startblockval(PREV.br_startblock) - |
912 | (cur ? cur->bc_private.b.allocated : 0)); | 697 | (bma->cur ? bma->cur->bc_private.b.allocated : 0)); |
913 | ep = xfs_iext_get_ext(ifp, *idx + 1); | 698 | ep = xfs_iext_get_ext(ifp, bma->idx + 1); |
914 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 699 | xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); |
915 | trace_xfs_bmap_post_update(ip, *idx + 1, state, _THIS_IP_); | 700 | trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_); |
916 | |||
917 | *dnew = temp; | ||
918 | break; | 701 | break; |
919 | 702 | ||
920 | case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: | 703 | case BMAP_RIGHT_FILLING | BMAP_RIGHT_CONTIG: |
@@ -923,38 +706,39 @@ xfs_bmap_add_extent_delay_real( | |||
923 | * The right neighbor is contiguous with the new allocation. | 706 | * The right neighbor is contiguous with the new allocation. |
924 | */ | 707 | */ |
925 | temp = PREV.br_blockcount - new->br_blockcount; | 708 | temp = PREV.br_blockcount - new->br_blockcount; |
926 | trace_xfs_bmap_pre_update(ip, *idx + 1, state, _THIS_IP_); | 709 | trace_xfs_bmap_pre_update(bma->ip, bma->idx + 1, state, _THIS_IP_); |
927 | xfs_bmbt_set_blockcount(ep, temp); | 710 | xfs_bmbt_set_blockcount(ep, temp); |
928 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx + 1), | 711 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx + 1), |
929 | new->br_startoff, new->br_startblock, | 712 | new->br_startoff, new->br_startblock, |
930 | new->br_blockcount + RIGHT.br_blockcount, | 713 | new->br_blockcount + RIGHT.br_blockcount, |
931 | RIGHT.br_state); | 714 | RIGHT.br_state); |
932 | trace_xfs_bmap_post_update(ip, *idx + 1, state, _THIS_IP_); | 715 | trace_xfs_bmap_post_update(bma->ip, bma->idx + 1, state, _THIS_IP_); |
933 | if (cur == NULL) | 716 | if (bma->cur == NULL) |
934 | rval = XFS_ILOG_DEXT; | 717 | rval = XFS_ILOG_DEXT; |
935 | else { | 718 | else { |
936 | rval = 0; | 719 | rval = 0; |
937 | if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff, | 720 | error = xfs_bmbt_lookup_eq(bma->cur, RIGHT.br_startoff, |
938 | RIGHT.br_startblock, | 721 | RIGHT.br_startblock, |
939 | RIGHT.br_blockcount, &i))) | 722 | RIGHT.br_blockcount, &i); |
723 | if (error) | ||
940 | goto done; | 724 | goto done; |
941 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 725 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
942 | if ((error = xfs_bmbt_update(cur, new->br_startoff, | 726 | error = xfs_bmbt_update(bma->cur, new->br_startoff, |
943 | new->br_startblock, | 727 | new->br_startblock, |
944 | new->br_blockcount + | 728 | new->br_blockcount + |
945 | RIGHT.br_blockcount, | 729 | RIGHT.br_blockcount, |
946 | RIGHT.br_state))) | 730 | RIGHT.br_state); |
731 | if (error) | ||
947 | goto done; | 732 | goto done; |
948 | } | 733 | } |
949 | 734 | ||
950 | temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), | 735 | da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), |
951 | startblockval(PREV.br_startblock)); | 736 | startblockval(PREV.br_startblock)); |
952 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 737 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
953 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 738 | xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); |
954 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 739 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
955 | 740 | ||
956 | ++*idx; | 741 | bma->idx++; |
957 | *dnew = temp; | ||
958 | break; | 742 | break; |
959 | 743 | ||
960 | case BMAP_RIGHT_FILLING: | 744 | case BMAP_RIGHT_FILLING: |
@@ -963,42 +747,43 @@ xfs_bmap_add_extent_delay_real( | |||
963 | * The right neighbor is not contiguous. | 747 | * The right neighbor is not contiguous. |
964 | */ | 748 | */ |
965 | temp = PREV.br_blockcount - new->br_blockcount; | 749 | temp = PREV.br_blockcount - new->br_blockcount; |
966 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 750 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
967 | xfs_bmbt_set_blockcount(ep, temp); | 751 | xfs_bmbt_set_blockcount(ep, temp); |
968 | xfs_iext_insert(ip, *idx + 1, 1, new, state); | 752 | xfs_iext_insert(bma->ip, bma->idx + 1, 1, new, state); |
969 | ip->i_d.di_nextents++; | 753 | bma->ip->i_d.di_nextents++; |
970 | if (cur == NULL) | 754 | if (bma->cur == NULL) |
971 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 755 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
972 | else { | 756 | else { |
973 | rval = XFS_ILOG_CORE; | 757 | rval = XFS_ILOG_CORE; |
974 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 758 | error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, |
975 | new->br_startblock, new->br_blockcount, | 759 | new->br_startblock, new->br_blockcount, |
976 | &i))) | 760 | &i); |
761 | if (error) | ||
977 | goto done; | 762 | goto done; |
978 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 763 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
979 | cur->bc_rec.b.br_state = XFS_EXT_NORM; | 764 | bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; |
980 | if ((error = xfs_btree_insert(cur, &i))) | 765 | error = xfs_btree_insert(bma->cur, &i); |
766 | if (error) | ||
981 | goto done; | 767 | goto done; |
982 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 768 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
983 | } | 769 | } |
984 | if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && | 770 | if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && |
985 | ip->i_d.di_nextents > ip->i_df.if_ext_max) { | 771 | bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) { |
986 | error = xfs_bmap_extents_to_btree(tp, ip, | 772 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, |
987 | first, flist, &cur, 1, &tmp_rval, | 773 | bma->firstblock, bma->flist, &bma->cur, 1, |
988 | XFS_DATA_FORK); | 774 | &tmp_rval, XFS_DATA_FORK); |
989 | rval |= tmp_rval; | 775 | rval |= tmp_rval; |
990 | if (error) | 776 | if (error) |
991 | goto done; | 777 | goto done; |
992 | } | 778 | } |
993 | temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), | 779 | da_new = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(bma->ip, temp), |
994 | startblockval(PREV.br_startblock) - | 780 | startblockval(PREV.br_startblock) - |
995 | (cur ? cur->bc_private.b.allocated : 0)); | 781 | (bma->cur ? bma->cur->bc_private.b.allocated : 0)); |
996 | ep = xfs_iext_get_ext(ifp, *idx); | 782 | ep = xfs_iext_get_ext(ifp, bma->idx); |
997 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 783 | xfs_bmbt_set_startblock(ep, nullstartblock(da_new)); |
998 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 784 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
999 | 785 | ||
1000 | ++*idx; | 786 | bma->idx++; |
1001 | *dnew = temp; | ||
1002 | break; | 787 | break; |
1003 | 788 | ||
1004 | case 0: | 789 | case 0: |
@@ -1024,82 +809,65 @@ xfs_bmap_add_extent_delay_real( | |||
1024 | */ | 809 | */ |
1025 | temp = new->br_startoff - PREV.br_startoff; | 810 | temp = new->br_startoff - PREV.br_startoff; |
1026 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; | 811 | temp2 = PREV.br_startoff + PREV.br_blockcount - new_endoff; |
1027 | trace_xfs_bmap_pre_update(ip, *idx, 0, _THIS_IP_); | 812 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, 0, _THIS_IP_); |
1028 | xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ | 813 | xfs_bmbt_set_blockcount(ep, temp); /* truncate PREV */ |
1029 | LEFT = *new; | 814 | LEFT = *new; |
1030 | RIGHT.br_state = PREV.br_state; | 815 | RIGHT.br_state = PREV.br_state; |
1031 | RIGHT.br_startblock = nullstartblock( | 816 | RIGHT.br_startblock = nullstartblock( |
1032 | (int)xfs_bmap_worst_indlen(ip, temp2)); | 817 | (int)xfs_bmap_worst_indlen(bma->ip, temp2)); |
1033 | RIGHT.br_startoff = new_endoff; | 818 | RIGHT.br_startoff = new_endoff; |
1034 | RIGHT.br_blockcount = temp2; | 819 | RIGHT.br_blockcount = temp2; |
1035 | /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ | 820 | /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ |
1036 | xfs_iext_insert(ip, *idx + 1, 2, &LEFT, state); | 821 | xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state); |
1037 | ip->i_d.di_nextents++; | 822 | bma->ip->i_d.di_nextents++; |
1038 | if (cur == NULL) | 823 | if (bma->cur == NULL) |
1039 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; | 824 | rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; |
1040 | else { | 825 | else { |
1041 | rval = XFS_ILOG_CORE; | 826 | rval = XFS_ILOG_CORE; |
1042 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 827 | error = xfs_bmbt_lookup_eq(bma->cur, new->br_startoff, |
1043 | new->br_startblock, new->br_blockcount, | 828 | new->br_startblock, new->br_blockcount, |
1044 | &i))) | 829 | &i); |
830 | if (error) | ||
1045 | goto done; | 831 | goto done; |
1046 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 832 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1047 | cur->bc_rec.b.br_state = XFS_EXT_NORM; | 833 | bma->cur->bc_rec.b.br_state = XFS_EXT_NORM; |
1048 | if ((error = xfs_btree_insert(cur, &i))) | 834 | error = xfs_btree_insert(bma->cur, &i); |
835 | if (error) | ||
1049 | goto done; | 836 | goto done; |
1050 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 837 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1051 | } | 838 | } |
1052 | if (ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && | 839 | if (bma->ip->i_d.di_format == XFS_DINODE_FMT_EXTENTS && |
1053 | ip->i_d.di_nextents > ip->i_df.if_ext_max) { | 840 | bma->ip->i_d.di_nextents > bma->ip->i_df.if_ext_max) { |
1054 | error = xfs_bmap_extents_to_btree(tp, ip, | 841 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, |
1055 | first, flist, &cur, 1, &tmp_rval, | 842 | bma->firstblock, bma->flist, &bma->cur, |
1056 | XFS_DATA_FORK); | 843 | 1, &tmp_rval, XFS_DATA_FORK); |
1057 | rval |= tmp_rval; | 844 | rval |= tmp_rval; |
1058 | if (error) | 845 | if (error) |
1059 | goto done; | 846 | goto done; |
1060 | } | 847 | } |
1061 | temp = xfs_bmap_worst_indlen(ip, temp); | 848 | temp = xfs_bmap_worst_indlen(bma->ip, temp); |
1062 | temp2 = xfs_bmap_worst_indlen(ip, temp2); | 849 | temp2 = xfs_bmap_worst_indlen(bma->ip, temp2); |
1063 | diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - | 850 | diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - |
1064 | (cur ? cur->bc_private.b.allocated : 0)); | 851 | (bma->cur ? bma->cur->bc_private.b.allocated : 0)); |
1065 | if (diff > 0 && | 852 | if (diff > 0) { |
1066 | xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, | 853 | error = xfs_icsb_modify_counters(bma->ip->i_mount, |
1067 | -((int64_t)diff), 0)) { | 854 | XFS_SBS_FDBLOCKS, |
1068 | /* | 855 | -((int64_t)diff), 0); |
1069 | * Ick gross gag me with a spoon. | 856 | ASSERT(!error); |
1070 | */ | 857 | if (error) |
1071 | ASSERT(0); /* want to see if this ever happens! */ | 858 | goto done; |
1072 | while (diff > 0) { | ||
1073 | if (temp) { | ||
1074 | temp--; | ||
1075 | diff--; | ||
1076 | if (!diff || | ||
1077 | !xfs_icsb_modify_counters(ip->i_mount, | ||
1078 | XFS_SBS_FDBLOCKS, | ||
1079 | -((int64_t)diff), 0)) | ||
1080 | break; | ||
1081 | } | ||
1082 | if (temp2) { | ||
1083 | temp2--; | ||
1084 | diff--; | ||
1085 | if (!diff || | ||
1086 | !xfs_icsb_modify_counters(ip->i_mount, | ||
1087 | XFS_SBS_FDBLOCKS, | ||
1088 | -((int64_t)diff), 0)) | ||
1089 | break; | ||
1090 | } | ||
1091 | } | ||
1092 | } | 859 | } |
1093 | ep = xfs_iext_get_ext(ifp, *idx); | 860 | |
861 | ep = xfs_iext_get_ext(ifp, bma->idx); | ||
1094 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); | 862 | xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); |
1095 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 863 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1096 | trace_xfs_bmap_pre_update(ip, *idx + 2, state, _THIS_IP_); | 864 | trace_xfs_bmap_pre_update(bma->ip, bma->idx + 2, state, _THIS_IP_); |
1097 | xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, *idx + 2), | 865 | xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, bma->idx + 2), |
1098 | nullstartblock((int)temp2)); | 866 | nullstartblock((int)temp2)); |
1099 | trace_xfs_bmap_post_update(ip, *idx + 2, state, _THIS_IP_); | 867 | trace_xfs_bmap_post_update(bma->ip, bma->idx + 2, state, _THIS_IP_); |
1100 | 868 | ||
1101 | ++*idx; | 869 | bma->idx++; |
1102 | *dnew = temp + temp2; | 870 | da_new = temp + temp2; |
1103 | break; | 871 | break; |
1104 | 872 | ||
1105 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: | 873 | case BMAP_LEFT_FILLING | BMAP_LEFT_CONTIG | BMAP_RIGHT_CONTIG: |
@@ -1114,9 +882,40 @@ xfs_bmap_add_extent_delay_real( | |||
1114 | */ | 882 | */ |
1115 | ASSERT(0); | 883 | ASSERT(0); |
1116 | } | 884 | } |
1117 | *curp = cur; | 885 | |
886 | /* convert to a btree if necessary */ | ||
887 | if (XFS_IFORK_FORMAT(bma->ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS && | ||
888 | XFS_IFORK_NEXTENTS(bma->ip, XFS_DATA_FORK) > ifp->if_ext_max) { | ||
889 | int tmp_logflags; /* partial log flag return val */ | ||
890 | |||
891 | ASSERT(bma->cur == NULL); | ||
892 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, | ||
893 | bma->firstblock, bma->flist, &bma->cur, | ||
894 | da_old > 0, &tmp_logflags, XFS_DATA_FORK); | ||
895 | bma->logflags |= tmp_logflags; | ||
896 | if (error) | ||
897 | goto done; | ||
898 | } | ||
899 | |||
900 | /* adjust for changes in reserved delayed indirect blocks */ | ||
901 | if (da_old || da_new) { | ||
902 | temp = da_new; | ||
903 | if (bma->cur) | ||
904 | temp += bma->cur->bc_private.b.allocated; | ||
905 | ASSERT(temp <= da_old); | ||
906 | if (temp < da_old) | ||
907 | xfs_icsb_modify_counters(bma->ip->i_mount, | ||
908 | XFS_SBS_FDBLOCKS, | ||
909 | (int64_t)(da_old - temp), 0); | ||
910 | } | ||
911 | |||
912 | /* clear out the allocated field, done with it now in any case. */ | ||
913 | if (bma->cur) | ||
914 | bma->cur->bc_private.b.allocated = 0; | ||
915 | |||
916 | xfs_bmap_check_leaf_extents(bma->cur, bma->ip, XFS_DATA_FORK); | ||
1118 | done: | 917 | done: |
1119 | *logflagsp = rval; | 918 | bma->logflags |= rval; |
1120 | return error; | 919 | return error; |
1121 | #undef LEFT | 920 | #undef LEFT |
1122 | #undef RIGHT | 921 | #undef RIGHT |
@@ -1124,15 +923,17 @@ done: | |||
1124 | } | 923 | } |
1125 | 924 | ||
1126 | /* | 925 | /* |
1127 | * Called by xfs_bmap_add_extent to handle cases converting an unwritten | 926 | * Convert an unwritten allocation to a real allocation or vice versa. |
1128 | * allocation to a real allocation or vice versa. | ||
1129 | */ | 927 | */ |
1130 | STATIC int /* error */ | 928 | STATIC int /* error */ |
1131 | xfs_bmap_add_extent_unwritten_real( | 929 | xfs_bmap_add_extent_unwritten_real( |
930 | struct xfs_trans *tp, | ||
1132 | xfs_inode_t *ip, /* incore inode pointer */ | 931 | xfs_inode_t *ip, /* incore inode pointer */ |
1133 | xfs_extnum_t *idx, /* extent number to update/insert */ | 932 | xfs_extnum_t *idx, /* extent number to update/insert */ |
1134 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | 933 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ |
1135 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 934 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
935 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | ||
936 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | ||
1136 | int *logflagsp) /* inode logging flags */ | 937 | int *logflagsp) /* inode logging flags */ |
1137 | { | 938 | { |
1138 | xfs_btree_cur_t *cur; /* btree cursor */ | 939 | xfs_btree_cur_t *cur; /* btree cursor */ |
@@ -1148,15 +949,25 @@ xfs_bmap_add_extent_unwritten_real( | |||
1148 | int rval=0; /* return value (logging flags) */ | 949 | int rval=0; /* return value (logging flags) */ |
1149 | int state = 0;/* state bits, accessed thru macros */ | 950 | int state = 0;/* state bits, accessed thru macros */ |
1150 | 951 | ||
952 | *logflagsp = 0; | ||
953 | |||
954 | cur = *curp; | ||
955 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
956 | |||
957 | ASSERT(*idx >= 0); | ||
958 | ASSERT(*idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); | ||
959 | ASSERT(!isnullstartblock(new->br_startblock)); | ||
960 | |||
961 | XFS_STATS_INC(xs_add_exlist); | ||
962 | |||
1151 | #define LEFT r[0] | 963 | #define LEFT r[0] |
1152 | #define RIGHT r[1] | 964 | #define RIGHT r[1] |
1153 | #define PREV r[2] | 965 | #define PREV r[2] |
966 | |||
1154 | /* | 967 | /* |
1155 | * Set up a bunch of variables to make the tests simpler. | 968 | * Set up a bunch of variables to make the tests simpler. |
1156 | */ | 969 | */ |
1157 | error = 0; | 970 | error = 0; |
1158 | cur = *curp; | ||
1159 | ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
1160 | ep = xfs_iext_get_ext(ifp, *idx); | 971 | ep = xfs_iext_get_ext(ifp, *idx); |
1161 | xfs_bmbt_get_all(ep, &PREV); | 972 | xfs_bmbt_get_all(ep, &PREV); |
1162 | newext = new->br_state; | 973 | newext = new->br_state; |
@@ -1406,10 +1217,11 @@ xfs_bmap_add_extent_unwritten_real( | |||
1406 | goto done; | 1217 | goto done; |
1407 | if ((error = xfs_btree_decrement(cur, 0, &i))) | 1218 | if ((error = xfs_btree_decrement(cur, 0, &i))) |
1408 | goto done; | 1219 | goto done; |
1409 | if (xfs_bmbt_update(cur, LEFT.br_startoff, | 1220 | error = xfs_bmbt_update(cur, LEFT.br_startoff, |
1410 | LEFT.br_startblock, | 1221 | LEFT.br_startblock, |
1411 | LEFT.br_blockcount + new->br_blockcount, | 1222 | LEFT.br_blockcount + new->br_blockcount, |
1412 | LEFT.br_state)) | 1223 | LEFT.br_state); |
1224 | if (error) | ||
1413 | goto done; | 1225 | goto done; |
1414 | } | 1226 | } |
1415 | break; | 1227 | break; |
@@ -1607,9 +1419,29 @@ xfs_bmap_add_extent_unwritten_real( | |||
1607 | */ | 1419 | */ |
1608 | ASSERT(0); | 1420 | ASSERT(0); |
1609 | } | 1421 | } |
1610 | *curp = cur; | 1422 | |
1423 | /* convert to a btree if necessary */ | ||
1424 | if (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) == XFS_DINODE_FMT_EXTENTS && | ||
1425 | XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) > ifp->if_ext_max) { | ||
1426 | int tmp_logflags; /* partial log flag return val */ | ||
1427 | |||
1428 | ASSERT(cur == NULL); | ||
1429 | error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur, | ||
1430 | 0, &tmp_logflags, XFS_DATA_FORK); | ||
1431 | *logflagsp |= tmp_logflags; | ||
1432 | if (error) | ||
1433 | goto done; | ||
1434 | } | ||
1435 | |||
1436 | /* clear out the allocated field, done with it now in any case. */ | ||
1437 | if (cur) { | ||
1438 | cur->bc_private.b.allocated = 0; | ||
1439 | *curp = cur; | ||
1440 | } | ||
1441 | |||
1442 | xfs_bmap_check_leaf_extents(*curp, ip, XFS_DATA_FORK); | ||
1611 | done: | 1443 | done: |
1612 | *logflagsp = rval; | 1444 | *logflagsp |= rval; |
1613 | return error; | 1445 | return error; |
1614 | #undef LEFT | 1446 | #undef LEFT |
1615 | #undef RIGHT | 1447 | #undef RIGHT |
@@ -1617,16 +1449,13 @@ done: | |||
1617 | } | 1449 | } |
1618 | 1450 | ||
1619 | /* | 1451 | /* |
1620 | * Called by xfs_bmap_add_extent to handle cases converting a hole | 1452 | * Convert a hole to a delayed allocation. |
1621 | * to a delayed allocation. | ||
1622 | */ | 1453 | */ |
1623 | /*ARGSUSED*/ | 1454 | STATIC void |
1624 | STATIC int /* error */ | ||
1625 | xfs_bmap_add_extent_hole_delay( | 1455 | xfs_bmap_add_extent_hole_delay( |
1626 | xfs_inode_t *ip, /* incore inode pointer */ | 1456 | xfs_inode_t *ip, /* incore inode pointer */ |
1627 | xfs_extnum_t *idx, /* extent number to update/insert */ | 1457 | xfs_extnum_t *idx, /* extent number to update/insert */ |
1628 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 1458 | xfs_bmbt_irec_t *new) /* new data to add to file extents */ |
1629 | int *logflagsp) /* inode logging flags */ | ||
1630 | { | 1459 | { |
1631 | xfs_ifork_t *ifp; /* inode fork pointer */ | 1460 | xfs_ifork_t *ifp; /* inode fork pointer */ |
1632 | xfs_bmbt_irec_t left; /* left neighbor extent entry */ | 1461 | xfs_bmbt_irec_t left; /* left neighbor extent entry */ |
@@ -1761,23 +1590,17 @@ xfs_bmap_add_extent_hole_delay( | |||
1761 | * Nothing to do for disk quota accounting here. | 1590 | * Nothing to do for disk quota accounting here. |
1762 | */ | 1591 | */ |
1763 | } | 1592 | } |
1764 | *logflagsp = 0; | ||
1765 | return 0; | ||
1766 | } | 1593 | } |
1767 | 1594 | ||
1768 | /* | 1595 | /* |
1769 | * Called by xfs_bmap_add_extent to handle cases converting a hole | 1596 | * Convert a hole to a real allocation. |
1770 | * to a real allocation. | ||
1771 | */ | 1597 | */ |
1772 | STATIC int /* error */ | 1598 | STATIC int /* error */ |
1773 | xfs_bmap_add_extent_hole_real( | 1599 | xfs_bmap_add_extent_hole_real( |
1774 | xfs_inode_t *ip, /* incore inode pointer */ | 1600 | struct xfs_bmalloca *bma, |
1775 | xfs_extnum_t *idx, /* extent number to update/insert */ | 1601 | int whichfork) |
1776 | xfs_btree_cur_t *cur, /* if null, not a btree */ | ||
1777 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | ||
1778 | int *logflagsp, /* inode logging flags */ | ||
1779 | int whichfork) /* data or attr fork */ | ||
1780 | { | 1602 | { |
1603 | struct xfs_bmbt_irec *new = &bma->got; | ||
1781 | int error; /* error return value */ | 1604 | int error; /* error return value */ |
1782 | int i; /* temp state */ | 1605 | int i; /* temp state */ |
1783 | xfs_ifork_t *ifp; /* inode fork pointer */ | 1606 | xfs_ifork_t *ifp; /* inode fork pointer */ |
@@ -1786,19 +1609,26 @@ xfs_bmap_add_extent_hole_real( | |||
1786 | int rval=0; /* return value (logging flags) */ | 1609 | int rval=0; /* return value (logging flags) */ |
1787 | int state; /* state bits, accessed thru macros */ | 1610 | int state; /* state bits, accessed thru macros */ |
1788 | 1611 | ||
1789 | ifp = XFS_IFORK_PTR(ip, whichfork); | 1612 | ifp = XFS_IFORK_PTR(bma->ip, whichfork); |
1790 | ASSERT(*idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)); | 1613 | |
1791 | state = 0; | 1614 | ASSERT(bma->idx >= 0); |
1615 | ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); | ||
1616 | ASSERT(!isnullstartblock(new->br_startblock)); | ||
1617 | ASSERT(!bma->cur || | ||
1618 | !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); | ||
1619 | |||
1620 | XFS_STATS_INC(xs_add_exlist); | ||
1792 | 1621 | ||
1622 | state = 0; | ||
1793 | if (whichfork == XFS_ATTR_FORK) | 1623 | if (whichfork == XFS_ATTR_FORK) |
1794 | state |= BMAP_ATTRFORK; | 1624 | state |= BMAP_ATTRFORK; |
1795 | 1625 | ||
1796 | /* | 1626 | /* |
1797 | * Check and set flags if this segment has a left neighbor. | 1627 | * Check and set flags if this segment has a left neighbor. |
1798 | */ | 1628 | */ |
1799 | if (*idx > 0) { | 1629 | if (bma->idx > 0) { |
1800 | state |= BMAP_LEFT_VALID; | 1630 | state |= BMAP_LEFT_VALID; |
1801 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx - 1), &left); | 1631 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), &left); |
1802 | if (isnullstartblock(left.br_startblock)) | 1632 | if (isnullstartblock(left.br_startblock)) |
1803 | state |= BMAP_LEFT_DELAY; | 1633 | state |= BMAP_LEFT_DELAY; |
1804 | } | 1634 | } |
@@ -1807,9 +1637,9 @@ xfs_bmap_add_extent_hole_real( | |||
1807 | * Check and set flags if this segment has a current value. | 1637 | * Check and set flags if this segment has a current value. |
1808 | * Not true if we're inserting into the "hole" at eof. | 1638 | * Not true if we're inserting into the "hole" at eof. |
1809 | */ | 1639 | */ |
1810 | if (*idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { | 1640 | if (bma->idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { |
1811 | state |= BMAP_RIGHT_VALID; | 1641 | state |= BMAP_RIGHT_VALID; |
1812 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right); | 1642 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &right); |
1813 | if (isnullstartblock(right.br_startblock)) | 1643 | if (isnullstartblock(right.br_startblock)) |
1814 | state |= BMAP_RIGHT_DELAY; | 1644 | state |= BMAP_RIGHT_DELAY; |
1815 | } | 1645 | } |
@@ -1846,39 +1676,42 @@ xfs_bmap_add_extent_hole_real( | |||
1846 | * left and on the right. | 1676 | * left and on the right. |
1847 | * Merge all three into a single extent record. | 1677 | * Merge all three into a single extent record. |
1848 | */ | 1678 | */ |
1849 | --*idx; | 1679 | --bma->idx; |
1850 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 1680 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
1851 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), | 1681 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), |
1852 | left.br_blockcount + new->br_blockcount + | 1682 | left.br_blockcount + new->br_blockcount + |
1853 | right.br_blockcount); | 1683 | right.br_blockcount); |
1854 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 1684 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1855 | 1685 | ||
1856 | xfs_iext_remove(ip, *idx + 1, 1, state); | 1686 | xfs_iext_remove(bma->ip, bma->idx + 1, 1, state); |
1857 | 1687 | ||
1858 | XFS_IFORK_NEXT_SET(ip, whichfork, | 1688 | XFS_IFORK_NEXT_SET(bma->ip, whichfork, |
1859 | XFS_IFORK_NEXTENTS(ip, whichfork) - 1); | 1689 | XFS_IFORK_NEXTENTS(bma->ip, whichfork) - 1); |
1860 | if (cur == NULL) { | 1690 | if (bma->cur == NULL) { |
1861 | rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); | 1691 | rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); |
1862 | } else { | 1692 | } else { |
1863 | rval = XFS_ILOG_CORE; | 1693 | rval = XFS_ILOG_CORE; |
1864 | if ((error = xfs_bmbt_lookup_eq(cur, | 1694 | error = xfs_bmbt_lookup_eq(bma->cur, right.br_startoff, |
1865 | right.br_startoff, | 1695 | right.br_startblock, right.br_blockcount, |
1866 | right.br_startblock, | 1696 | &i); |
1867 | right.br_blockcount, &i))) | 1697 | if (error) |
1868 | goto done; | 1698 | goto done; |
1869 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1699 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1870 | if ((error = xfs_btree_delete(cur, &i))) | 1700 | error = xfs_btree_delete(bma->cur, &i); |
1701 | if (error) | ||
1871 | goto done; | 1702 | goto done; |
1872 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1703 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1873 | if ((error = xfs_btree_decrement(cur, 0, &i))) | 1704 | error = xfs_btree_decrement(bma->cur, 0, &i); |
1705 | if (error) | ||
1874 | goto done; | 1706 | goto done; |
1875 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1707 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1876 | if ((error = xfs_bmbt_update(cur, left.br_startoff, | 1708 | error = xfs_bmbt_update(bma->cur, left.br_startoff, |
1877 | left.br_startblock, | 1709 | left.br_startblock, |
1878 | left.br_blockcount + | 1710 | left.br_blockcount + |
1879 | new->br_blockcount + | 1711 | new->br_blockcount + |
1880 | right.br_blockcount, | 1712 | right.br_blockcount, |
1881 | left.br_state))) | 1713 | left.br_state); |
1714 | if (error) | ||
1882 | goto done; | 1715 | goto done; |
1883 | } | 1716 | } |
1884 | break; | 1717 | break; |
@@ -1889,27 +1722,28 @@ xfs_bmap_add_extent_hole_real( | |||
1889 | * on the left. | 1722 | * on the left. |
1890 | * Merge the new allocation with the left neighbor. | 1723 | * Merge the new allocation with the left neighbor. |
1891 | */ | 1724 | */ |
1892 | --*idx; | 1725 | --bma->idx; |
1893 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 1726 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
1894 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, *idx), | 1727 | xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, bma->idx), |
1895 | left.br_blockcount + new->br_blockcount); | 1728 | left.br_blockcount + new->br_blockcount); |
1896 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 1729 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1897 | 1730 | ||
1898 | if (cur == NULL) { | 1731 | if (bma->cur == NULL) { |
1899 | rval = xfs_ilog_fext(whichfork); | 1732 | rval = xfs_ilog_fext(whichfork); |
1900 | } else { | 1733 | } else { |
1901 | rval = 0; | 1734 | rval = 0; |
1902 | if ((error = xfs_bmbt_lookup_eq(cur, | 1735 | error = xfs_bmbt_lookup_eq(bma->cur, left.br_startoff, |
1903 | left.br_startoff, | 1736 | left.br_startblock, left.br_blockcount, |
1904 | left.br_startblock, | 1737 | &i); |
1905 | left.br_blockcount, &i))) | 1738 | if (error) |
1906 | goto done; | 1739 | goto done; |
1907 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1740 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1908 | if ((error = xfs_bmbt_update(cur, left.br_startoff, | 1741 | error = xfs_bmbt_update(bma->cur, left.br_startoff, |
1909 | left.br_startblock, | 1742 | left.br_startblock, |
1910 | left.br_blockcount + | 1743 | left.br_blockcount + |
1911 | new->br_blockcount, | 1744 | new->br_blockcount, |
1912 | left.br_state))) | 1745 | left.br_state); |
1746 | if (error) | ||
1913 | goto done; | 1747 | goto done; |
1914 | } | 1748 | } |
1915 | break; | 1749 | break; |
@@ -1920,28 +1754,30 @@ xfs_bmap_add_extent_hole_real( | |||
1920 | * on the right. | 1754 | * on the right. |
1921 | * Merge the new allocation with the right neighbor. | 1755 | * Merge the new allocation with the right neighbor. |
1922 | */ | 1756 | */ |
1923 | trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); | 1757 | trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); |
1924 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, *idx), | 1758 | xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, bma->idx), |
1925 | new->br_startoff, new->br_startblock, | 1759 | new->br_startoff, new->br_startblock, |
1926 | new->br_blockcount + right.br_blockcount, | 1760 | new->br_blockcount + right.br_blockcount, |
1927 | right.br_state); | 1761 | right.br_state); |
1928 | trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); | 1762 | trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); |
1929 | 1763 | ||
1930 | if (cur == NULL) { | 1764 | if (bma->cur == NULL) { |
1931 | rval = xfs_ilog_fext(whichfork); | 1765 | rval = xfs_ilog_fext(whichfork); |
1932 | } else { | 1766 | } else { |
1933 | rval = 0; | 1767 | rval = 0; |
1934 | if ((error = xfs_bmbt_lookup_eq(cur, | 1768 | error = xfs_bmbt_lookup_eq(bma->cur, |
1935 | right.br_startoff, | 1769 | right.br_startoff, |
1936 | right.br_startblock, | 1770 | right.br_startblock, |
1937 | right.br_blockcount, &i))) | 1771 | right.br_blockcount, &i); |
1772 | if (error) | ||
1938 | goto done; | 1773 | goto done; |
1939 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1774 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1940 | if ((error = xfs_bmbt_update(cur, new->br_startoff, | 1775 | error = xfs_bmbt_update(bma->cur, new->br_startoff, |
1941 | new->br_startblock, | 1776 | new->br_startblock, |
1942 | new->br_blockcount + | 1777 | new->br_blockcount + |
1943 | right.br_blockcount, | 1778 | right.br_blockcount, |
1944 | right.br_state))) | 1779 | right.br_state); |
1780 | if (error) | ||
1945 | goto done; | 1781 | goto done; |
1946 | } | 1782 | } |
1947 | break; | 1783 | break; |
@@ -1952,28 +1788,50 @@ xfs_bmap_add_extent_hole_real( | |||
1952 | * real allocation. | 1788 | * real allocation. |
1953 | * Insert a new entry. | 1789 | * Insert a new entry. |
1954 | */ | 1790 | */ |
1955 | xfs_iext_insert(ip, *idx, 1, new, state); | 1791 | xfs_iext_insert(bma->ip, bma->idx, 1, new, state); |
1956 | XFS_IFORK_NEXT_SET(ip, whichfork, | 1792 | XFS_IFORK_NEXT_SET(bma->ip, whichfork, |
1957 | XFS_IFORK_NEXTENTS(ip, whichfork) + 1); | 1793 | XFS_IFORK_NEXTENTS(bma->ip, whichfork) + 1); |
1958 | if (cur == NULL) { | 1794 | if (bma->cur == NULL) { |
1959 | rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); | 1795 | rval = XFS_ILOG_CORE | xfs_ilog_fext(whichfork); |
1960 | } else { | 1796 | } else { |
1961 | rval = XFS_ILOG_CORE; | 1797 | rval = XFS_ILOG_CORE; |
1962 | if ((error = xfs_bmbt_lookup_eq(cur, | 1798 | error = xfs_bmbt_lookup_eq(bma->cur, |
1963 | new->br_startoff, | 1799 | new->br_startoff, |
1964 | new->br_startblock, | 1800 | new->br_startblock, |
1965 | new->br_blockcount, &i))) | 1801 | new->br_blockcount, &i); |
1802 | if (error) | ||
1966 | goto done; | 1803 | goto done; |
1967 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); | 1804 | XFS_WANT_CORRUPTED_GOTO(i == 0, done); |
1968 | cur->bc_rec.b.br_state = new->br_state; | 1805 | bma->cur->bc_rec.b.br_state = new->br_state; |
1969 | if ((error = xfs_btree_insert(cur, &i))) | 1806 | error = xfs_btree_insert(bma->cur, &i); |
1807 | if (error) | ||
1970 | goto done; | 1808 | goto done; |
1971 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); | 1809 | XFS_WANT_CORRUPTED_GOTO(i == 1, done); |
1972 | } | 1810 | } |
1973 | break; | 1811 | break; |
1974 | } | 1812 | } |
1813 | |||
1814 | /* convert to a btree if necessary */ | ||
1815 | if (XFS_IFORK_FORMAT(bma->ip, whichfork) == XFS_DINODE_FMT_EXTENTS && | ||
1816 | XFS_IFORK_NEXTENTS(bma->ip, whichfork) > ifp->if_ext_max) { | ||
1817 | int tmp_logflags; /* partial log flag return val */ | ||
1818 | |||
1819 | ASSERT(bma->cur == NULL); | ||
1820 | error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, | ||
1821 | bma->firstblock, bma->flist, &bma->cur, | ||
1822 | 0, &tmp_logflags, whichfork); | ||
1823 | bma->logflags |= tmp_logflags; | ||
1824 | if (error) | ||
1825 | goto done; | ||
1826 | } | ||
1827 | |||
1828 | /* clear out the allocated field, done with it now in any case. */ | ||
1829 | if (bma->cur) | ||
1830 | bma->cur->bc_private.b.allocated = 0; | ||
1831 | |||
1832 | xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork); | ||
1975 | done: | 1833 | done: |
1976 | *logflagsp = rval; | 1834 | bma->logflags |= rval; |
1977 | return error; | 1835 | return error; |
1978 | } | 1836 | } |
1979 | 1837 | ||
@@ -2160,26 +2018,26 @@ xfs_bmap_adjacent( | |||
2160 | XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) | 2018 | XFS_FSB_TO_AGBNO(mp, x) < mp->m_sb.sb_agblocks) |
2161 | 2019 | ||
2162 | mp = ap->ip->i_mount; | 2020 | mp = ap->ip->i_mount; |
2163 | nullfb = ap->firstblock == NULLFSBLOCK; | 2021 | nullfb = *ap->firstblock == NULLFSBLOCK; |
2164 | rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; | 2022 | rt = XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata; |
2165 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); | 2023 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); |
2166 | /* | 2024 | /* |
2167 | * If allocating at eof, and there's a previous real block, | 2025 | * If allocating at eof, and there's a previous real block, |
2168 | * try to use its last block as our starting point. | 2026 | * try to use its last block as our starting point. |
2169 | */ | 2027 | */ |
2170 | if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF && | 2028 | if (ap->eof && ap->prev.br_startoff != NULLFILEOFF && |
2171 | !isnullstartblock(ap->prevp->br_startblock) && | 2029 | !isnullstartblock(ap->prev.br_startblock) && |
2172 | ISVALID(ap->prevp->br_startblock + ap->prevp->br_blockcount, | 2030 | ISVALID(ap->prev.br_startblock + ap->prev.br_blockcount, |
2173 | ap->prevp->br_startblock)) { | 2031 | ap->prev.br_startblock)) { |
2174 | ap->rval = ap->prevp->br_startblock + ap->prevp->br_blockcount; | 2032 | ap->blkno = ap->prev.br_startblock + ap->prev.br_blockcount; |
2175 | /* | 2033 | /* |
2176 | * Adjust for the gap between prevp and us. | 2034 | * Adjust for the gap between prevp and us. |
2177 | */ | 2035 | */ |
2178 | adjust = ap->off - | 2036 | adjust = ap->offset - |
2179 | (ap->prevp->br_startoff + ap->prevp->br_blockcount); | 2037 | (ap->prev.br_startoff + ap->prev.br_blockcount); |
2180 | if (adjust && | 2038 | if (adjust && |
2181 | ISVALID(ap->rval + adjust, ap->prevp->br_startblock)) | 2039 | ISVALID(ap->blkno + adjust, ap->prev.br_startblock)) |
2182 | ap->rval += adjust; | 2040 | ap->blkno += adjust; |
2183 | } | 2041 | } |
2184 | /* | 2042 | /* |
2185 | * If not at eof, then compare the two neighbor blocks. | 2043 | * If not at eof, then compare the two neighbor blocks. |
@@ -2196,17 +2054,17 @@ xfs_bmap_adjacent( | |||
2196 | * If there's a previous (left) block, select a requested | 2054 | * If there's a previous (left) block, select a requested |
2197 | * start block based on it. | 2055 | * start block based on it. |
2198 | */ | 2056 | */ |
2199 | if (ap->prevp->br_startoff != NULLFILEOFF && | 2057 | if (ap->prev.br_startoff != NULLFILEOFF && |
2200 | !isnullstartblock(ap->prevp->br_startblock) && | 2058 | !isnullstartblock(ap->prev.br_startblock) && |
2201 | (prevbno = ap->prevp->br_startblock + | 2059 | (prevbno = ap->prev.br_startblock + |
2202 | ap->prevp->br_blockcount) && | 2060 | ap->prev.br_blockcount) && |
2203 | ISVALID(prevbno, ap->prevp->br_startblock)) { | 2061 | ISVALID(prevbno, ap->prev.br_startblock)) { |
2204 | /* | 2062 | /* |
2205 | * Calculate gap to end of previous block. | 2063 | * Calculate gap to end of previous block. |
2206 | */ | 2064 | */ |
2207 | adjust = prevdiff = ap->off - | 2065 | adjust = prevdiff = ap->offset - |
2208 | (ap->prevp->br_startoff + | 2066 | (ap->prev.br_startoff + |
2209 | ap->prevp->br_blockcount); | 2067 | ap->prev.br_blockcount); |
2210 | /* | 2068 | /* |
2211 | * Figure the startblock based on the previous block's | 2069 | * Figure the startblock based on the previous block's |
2212 | * end and the gap size. | 2070 | * end and the gap size. |
@@ -2215,9 +2073,9 @@ xfs_bmap_adjacent( | |||
2215 | * allocating, or using it gives us an invalid block | 2073 | * allocating, or using it gives us an invalid block |
2216 | * number, then just use the end of the previous block. | 2074 | * number, then just use the end of the previous block. |
2217 | */ | 2075 | */ |
2218 | if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->alen && | 2076 | if (prevdiff <= XFS_ALLOC_GAP_UNITS * ap->length && |
2219 | ISVALID(prevbno + prevdiff, | 2077 | ISVALID(prevbno + prevdiff, |
2220 | ap->prevp->br_startblock)) | 2078 | ap->prev.br_startblock)) |
2221 | prevbno += adjust; | 2079 | prevbno += adjust; |
2222 | else | 2080 | else |
2223 | prevdiff += adjust; | 2081 | prevdiff += adjust; |
@@ -2238,16 +2096,16 @@ xfs_bmap_adjacent( | |||
2238 | * If there's a following (right) block, select a requested | 2096 | * If there's a following (right) block, select a requested |
2239 | * start block based on it. | 2097 | * start block based on it. |
2240 | */ | 2098 | */ |
2241 | if (!isnullstartblock(ap->gotp->br_startblock)) { | 2099 | if (!isnullstartblock(ap->got.br_startblock)) { |
2242 | /* | 2100 | /* |
2243 | * Calculate gap to start of next block. | 2101 | * Calculate gap to start of next block. |
2244 | */ | 2102 | */ |
2245 | adjust = gotdiff = ap->gotp->br_startoff - ap->off; | 2103 | adjust = gotdiff = ap->got.br_startoff - ap->offset; |
2246 | /* | 2104 | /* |
2247 | * Figure the startblock based on the next block's | 2105 | * Figure the startblock based on the next block's |
2248 | * start and the gap size. | 2106 | * start and the gap size. |
2249 | */ | 2107 | */ |
2250 | gotbno = ap->gotp->br_startblock; | 2108 | gotbno = ap->got.br_startblock; |
2251 | /* | 2109 | /* |
2252 | * Heuristic! | 2110 | * Heuristic! |
2253 | * If the gap is large relative to the piece we're | 2111 | * If the gap is large relative to the piece we're |
@@ -2255,12 +2113,12 @@ xfs_bmap_adjacent( | |||
2255 | * number, then just use the start of the next block | 2113 | * number, then just use the start of the next block |
2256 | * offset by our length. | 2114 | * offset by our length. |
2257 | */ | 2115 | */ |
2258 | if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->alen && | 2116 | if (gotdiff <= XFS_ALLOC_GAP_UNITS * ap->length && |
2259 | ISVALID(gotbno - gotdiff, gotbno)) | 2117 | ISVALID(gotbno - gotdiff, gotbno)) |
2260 | gotbno -= adjust; | 2118 | gotbno -= adjust; |
2261 | else if (ISVALID(gotbno - ap->alen, gotbno)) { | 2119 | else if (ISVALID(gotbno - ap->length, gotbno)) { |
2262 | gotbno -= ap->alen; | 2120 | gotbno -= ap->length; |
2263 | gotdiff += adjust - ap->alen; | 2121 | gotdiff += adjust - ap->length; |
2264 | } else | 2122 | } else |
2265 | gotdiff += adjust; | 2123 | gotdiff += adjust; |
2266 | /* | 2124 | /* |
@@ -2278,14 +2136,14 @@ xfs_bmap_adjacent( | |||
2278 | gotbno = NULLFSBLOCK; | 2136 | gotbno = NULLFSBLOCK; |
2279 | /* | 2137 | /* |
2280 | * If both valid, pick the better one, else the only good | 2138 | * If both valid, pick the better one, else the only good |
2281 | * one, else ap->rval is already set (to 0 or the inode block). | 2139 | * one, else ap->blkno is already set (to 0 or the inode block). |
2282 | */ | 2140 | */ |
2283 | if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK) | 2141 | if (prevbno != NULLFSBLOCK && gotbno != NULLFSBLOCK) |
2284 | ap->rval = prevdiff <= gotdiff ? prevbno : gotbno; | 2142 | ap->blkno = prevdiff <= gotdiff ? prevbno : gotbno; |
2285 | else if (prevbno != NULLFSBLOCK) | 2143 | else if (prevbno != NULLFSBLOCK) |
2286 | ap->rval = prevbno; | 2144 | ap->blkno = prevbno; |
2287 | else if (gotbno != NULLFSBLOCK) | 2145 | else if (gotbno != NULLFSBLOCK) |
2288 | ap->rval = gotbno; | 2146 | ap->blkno = gotbno; |
2289 | } | 2147 | } |
2290 | #undef ISVALID | 2148 | #undef ISVALID |
2291 | } | 2149 | } |
@@ -2305,24 +2163,24 @@ xfs_bmap_rtalloc( | |||
2305 | mp = ap->ip->i_mount; | 2163 | mp = ap->ip->i_mount; |
2306 | align = xfs_get_extsz_hint(ap->ip); | 2164 | align = xfs_get_extsz_hint(ap->ip); |
2307 | prod = align / mp->m_sb.sb_rextsize; | 2165 | prod = align / mp->m_sb.sb_rextsize; |
2308 | error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, | 2166 | error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, |
2309 | align, 1, ap->eof, 0, | 2167 | align, 1, ap->eof, 0, |
2310 | ap->conv, &ap->off, &ap->alen); | 2168 | ap->conv, &ap->offset, &ap->length); |
2311 | if (error) | 2169 | if (error) |
2312 | return error; | 2170 | return error; |
2313 | ASSERT(ap->alen); | 2171 | ASSERT(ap->length); |
2314 | ASSERT(ap->alen % mp->m_sb.sb_rextsize == 0); | 2172 | ASSERT(ap->length % mp->m_sb.sb_rextsize == 0); |
2315 | 2173 | ||
2316 | /* | 2174 | /* |
2317 | * If the offset & length are not perfectly aligned | 2175 | * If the offset & length are not perfectly aligned |
2318 | * then kill prod, it will just get us in trouble. | 2176 | * then kill prod, it will just get us in trouble. |
2319 | */ | 2177 | */ |
2320 | if (do_mod(ap->off, align) || ap->alen % align) | 2178 | if (do_mod(ap->offset, align) || ap->length % align) |
2321 | prod = 1; | 2179 | prod = 1; |
2322 | /* | 2180 | /* |
2323 | * Set ralen to be the actual requested length in rtextents. | 2181 | * Set ralen to be the actual requested length in rtextents. |
2324 | */ | 2182 | */ |
2325 | ralen = ap->alen / mp->m_sb.sb_rextsize; | 2183 | ralen = ap->length / mp->m_sb.sb_rextsize; |
2326 | /* | 2184 | /* |
2327 | * If the old value was close enough to MAXEXTLEN that | 2185 | * If the old value was close enough to MAXEXTLEN that |
2328 | * we rounded up to it, cut it back so it's valid again. | 2186 | * we rounded up to it, cut it back so it's valid again. |
@@ -2337,21 +2195,21 @@ xfs_bmap_rtalloc( | |||
2337 | * Lock out other modifications to the RT bitmap inode. | 2195 | * Lock out other modifications to the RT bitmap inode. |
2338 | */ | 2196 | */ |
2339 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); | 2197 | xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); |
2340 | xfs_trans_ijoin_ref(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); | 2198 | xfs_trans_ijoin(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL); |
2341 | 2199 | ||
2342 | /* | 2200 | /* |
2343 | * If it's an allocation to an empty file at offset 0, | 2201 | * If it's an allocation to an empty file at offset 0, |
2344 | * pick an extent that will space things out in the rt area. | 2202 | * pick an extent that will space things out in the rt area. |
2345 | */ | 2203 | */ |
2346 | if (ap->eof && ap->off == 0) { | 2204 | if (ap->eof && ap->offset == 0) { |
2347 | xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */ | 2205 | xfs_rtblock_t uninitialized_var(rtx); /* realtime extent no */ |
2348 | 2206 | ||
2349 | error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); | 2207 | error = xfs_rtpick_extent(mp, ap->tp, ralen, &rtx); |
2350 | if (error) | 2208 | if (error) |
2351 | return error; | 2209 | return error; |
2352 | ap->rval = rtx * mp->m_sb.sb_rextsize; | 2210 | ap->blkno = rtx * mp->m_sb.sb_rextsize; |
2353 | } else { | 2211 | } else { |
2354 | ap->rval = 0; | 2212 | ap->blkno = 0; |
2355 | } | 2213 | } |
2356 | 2214 | ||
2357 | xfs_bmap_adjacent(ap); | 2215 | xfs_bmap_adjacent(ap); |
@@ -2359,23 +2217,23 @@ xfs_bmap_rtalloc( | |||
2359 | /* | 2217 | /* |
2360 | * Realtime allocation, done through xfs_rtallocate_extent. | 2218 | * Realtime allocation, done through xfs_rtallocate_extent. |
2361 | */ | 2219 | */ |
2362 | atype = ap->rval == 0 ? XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO; | 2220 | atype = ap->blkno == 0 ? XFS_ALLOCTYPE_ANY_AG : XFS_ALLOCTYPE_NEAR_BNO; |
2363 | do_div(ap->rval, mp->m_sb.sb_rextsize); | 2221 | do_div(ap->blkno, mp->m_sb.sb_rextsize); |
2364 | rtb = ap->rval; | 2222 | rtb = ap->blkno; |
2365 | ap->alen = ralen; | 2223 | ap->length = ralen; |
2366 | if ((error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, ap->alen, | 2224 | if ((error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1, ap->length, |
2367 | &ralen, atype, ap->wasdel, prod, &rtb))) | 2225 | &ralen, atype, ap->wasdel, prod, &rtb))) |
2368 | return error; | 2226 | return error; |
2369 | if (rtb == NULLFSBLOCK && prod > 1 && | 2227 | if (rtb == NULLFSBLOCK && prod > 1 && |
2370 | (error = xfs_rtallocate_extent(ap->tp, ap->rval, 1, | 2228 | (error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1, |
2371 | ap->alen, &ralen, atype, | 2229 | ap->length, &ralen, atype, |
2372 | ap->wasdel, 1, &rtb))) | 2230 | ap->wasdel, 1, &rtb))) |
2373 | return error; | 2231 | return error; |
2374 | ap->rval = rtb; | 2232 | ap->blkno = rtb; |
2375 | if (ap->rval != NULLFSBLOCK) { | 2233 | if (ap->blkno != NULLFSBLOCK) { |
2376 | ap->rval *= mp->m_sb.sb_rextsize; | 2234 | ap->blkno *= mp->m_sb.sb_rextsize; |
2377 | ralen *= mp->m_sb.sb_rextsize; | 2235 | ralen *= mp->m_sb.sb_rextsize; |
2378 | ap->alen = ralen; | 2236 | ap->length = ralen; |
2379 | ap->ip->i_d.di_nblocks += ralen; | 2237 | ap->ip->i_d.di_nblocks += ralen; |
2380 | xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); | 2238 | xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); |
2381 | if (ap->wasdel) | 2239 | if (ap->wasdel) |
@@ -2388,7 +2246,7 @@ xfs_bmap_rtalloc( | |||
2388 | ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : | 2246 | ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT : |
2389 | XFS_TRANS_DQ_RTBCOUNT, (long) ralen); | 2247 | XFS_TRANS_DQ_RTBCOUNT, (long) ralen); |
2390 | } else { | 2248 | } else { |
2391 | ap->alen = 0; | 2249 | ap->length = 0; |
2392 | } | 2250 | } |
2393 | return 0; | 2251 | return 0; |
2394 | } | 2252 | } |
@@ -2503,7 +2361,7 @@ xfs_bmap_btalloc_nullfb( | |||
2503 | * AG as the stream may have moved. | 2361 | * AG as the stream may have moved. |
2504 | */ | 2362 | */ |
2505 | if (xfs_inode_is_filestream(ap->ip)) | 2363 | if (xfs_inode_is_filestream(ap->ip)) |
2506 | ap->rval = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); | 2364 | ap->blkno = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0); |
2507 | 2365 | ||
2508 | return 0; | 2366 | return 0; |
2509 | } | 2367 | } |
@@ -2528,52 +2386,52 @@ xfs_bmap_btalloc( | |||
2528 | mp = ap->ip->i_mount; | 2386 | mp = ap->ip->i_mount; |
2529 | align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; | 2387 | align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; |
2530 | if (unlikely(align)) { | 2388 | if (unlikely(align)) { |
2531 | error = xfs_bmap_extsize_align(mp, ap->gotp, ap->prevp, | 2389 | error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, |
2532 | align, 0, ap->eof, 0, ap->conv, | 2390 | align, 0, ap->eof, 0, ap->conv, |
2533 | &ap->off, &ap->alen); | 2391 | &ap->offset, &ap->length); |
2534 | ASSERT(!error); | 2392 | ASSERT(!error); |
2535 | ASSERT(ap->alen); | 2393 | ASSERT(ap->length); |
2536 | } | 2394 | } |
2537 | nullfb = ap->firstblock == NULLFSBLOCK; | 2395 | nullfb = *ap->firstblock == NULLFSBLOCK; |
2538 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); | 2396 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock); |
2539 | if (nullfb) { | 2397 | if (nullfb) { |
2540 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) { | 2398 | if (ap->userdata && xfs_inode_is_filestream(ap->ip)) { |
2541 | ag = xfs_filestream_lookup_ag(ap->ip); | 2399 | ag = xfs_filestream_lookup_ag(ap->ip); |
2542 | ag = (ag != NULLAGNUMBER) ? ag : 0; | 2400 | ag = (ag != NULLAGNUMBER) ? ag : 0; |
2543 | ap->rval = XFS_AGB_TO_FSB(mp, ag, 0); | 2401 | ap->blkno = XFS_AGB_TO_FSB(mp, ag, 0); |
2544 | } else { | 2402 | } else { |
2545 | ap->rval = XFS_INO_TO_FSB(mp, ap->ip->i_ino); | 2403 | ap->blkno = XFS_INO_TO_FSB(mp, ap->ip->i_ino); |
2546 | } | 2404 | } |
2547 | } else | 2405 | } else |
2548 | ap->rval = ap->firstblock; | 2406 | ap->blkno = *ap->firstblock; |
2549 | 2407 | ||
2550 | xfs_bmap_adjacent(ap); | 2408 | xfs_bmap_adjacent(ap); |
2551 | 2409 | ||
2552 | /* | 2410 | /* |
2553 | * If allowed, use ap->rval; otherwise must use firstblock since | 2411 | * If allowed, use ap->blkno; otherwise must use firstblock since |
2554 | * it's in the right allocation group. | 2412 | * it's in the right allocation group. |
2555 | */ | 2413 | */ |
2556 | if (nullfb || XFS_FSB_TO_AGNO(mp, ap->rval) == fb_agno) | 2414 | if (nullfb || XFS_FSB_TO_AGNO(mp, ap->blkno) == fb_agno) |
2557 | ; | 2415 | ; |
2558 | else | 2416 | else |
2559 | ap->rval = ap->firstblock; | 2417 | ap->blkno = *ap->firstblock; |
2560 | /* | 2418 | /* |
2561 | * Normal allocation, done through xfs_alloc_vextent. | 2419 | * Normal allocation, done through xfs_alloc_vextent. |
2562 | */ | 2420 | */ |
2563 | tryagain = isaligned = 0; | 2421 | tryagain = isaligned = 0; |
2564 | args.tp = ap->tp; | 2422 | args.tp = ap->tp; |
2565 | args.mp = mp; | 2423 | args.mp = mp; |
2566 | args.fsbno = ap->rval; | 2424 | args.fsbno = ap->blkno; |
2567 | 2425 | ||
2568 | /* Trim the allocation back to the maximum an AG can fit. */ | 2426 | /* Trim the allocation back to the maximum an AG can fit. */ |
2569 | args.maxlen = MIN(ap->alen, XFS_ALLOC_AG_MAX_USABLE(mp)); | 2427 | args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp)); |
2570 | args.firstblock = ap->firstblock; | 2428 | args.firstblock = *ap->firstblock; |
2571 | blen = 0; | 2429 | blen = 0; |
2572 | if (nullfb) { | 2430 | if (nullfb) { |
2573 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); | 2431 | error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); |
2574 | if (error) | 2432 | if (error) |
2575 | return error; | 2433 | return error; |
2576 | } else if (ap->low) { | 2434 | } else if (ap->flist->xbf_low) { |
2577 | if (xfs_inode_is_filestream(ap->ip)) | 2435 | if (xfs_inode_is_filestream(ap->ip)) |
2578 | args.type = XFS_ALLOCTYPE_FIRST_AG; | 2436 | args.type = XFS_ALLOCTYPE_FIRST_AG; |
2579 | else | 2437 | else |
@@ -2587,14 +2445,14 @@ xfs_bmap_btalloc( | |||
2587 | /* apply extent size hints if obtained earlier */ | 2445 | /* apply extent size hints if obtained earlier */ |
2588 | if (unlikely(align)) { | 2446 | if (unlikely(align)) { |
2589 | args.prod = align; | 2447 | args.prod = align; |
2590 | if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) | 2448 | if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod))) |
2591 | args.mod = (xfs_extlen_t)(args.prod - args.mod); | 2449 | args.mod = (xfs_extlen_t)(args.prod - args.mod); |
2592 | } else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) { | 2450 | } else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) { |
2593 | args.prod = 1; | 2451 | args.prod = 1; |
2594 | args.mod = 0; | 2452 | args.mod = 0; |
2595 | } else { | 2453 | } else { |
2596 | args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog; | 2454 | args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog; |
2597 | if ((args.mod = (xfs_extlen_t)(do_mod(ap->off, args.prod)))) | 2455 | if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod)))) |
2598 | args.mod = (xfs_extlen_t)(args.prod - args.mod); | 2456 | args.mod = (xfs_extlen_t)(args.prod - args.mod); |
2599 | } | 2457 | } |
2600 | /* | 2458 | /* |
@@ -2606,8 +2464,8 @@ xfs_bmap_btalloc( | |||
2606 | * is >= the stripe unit and the allocation offset is | 2464 | * is >= the stripe unit and the allocation offset is |
2607 | * at the end of file. | 2465 | * at the end of file. |
2608 | */ | 2466 | */ |
2609 | if (!ap->low && ap->aeof) { | 2467 | if (!ap->flist->xbf_low && ap->aeof) { |
2610 | if (!ap->off) { | 2468 | if (!ap->offset) { |
2611 | args.alignment = mp->m_dalign; | 2469 | args.alignment = mp->m_dalign; |
2612 | atype = args.type; | 2470 | atype = args.type; |
2613 | isaligned = 1; | 2471 | isaligned = 1; |
@@ -2660,7 +2518,7 @@ xfs_bmap_btalloc( | |||
2660 | * turned on. | 2518 | * turned on. |
2661 | */ | 2519 | */ |
2662 | args.type = atype; | 2520 | args.type = atype; |
2663 | args.fsbno = ap->rval; | 2521 | args.fsbno = ap->blkno; |
2664 | args.alignment = mp->m_dalign; | 2522 | args.alignment = mp->m_dalign; |
2665 | args.minlen = nextminlen; | 2523 | args.minlen = nextminlen; |
2666 | args.minalignslop = 0; | 2524 | args.minalignslop = 0; |
@@ -2674,7 +2532,7 @@ xfs_bmap_btalloc( | |||
2674 | * try again. | 2532 | * try again. |
2675 | */ | 2533 | */ |
2676 | args.type = atype; | 2534 | args.type = atype; |
2677 | args.fsbno = ap->rval; | 2535 | args.fsbno = ap->blkno; |
2678 | args.alignment = 0; | 2536 | args.alignment = 0; |
2679 | if ((error = xfs_alloc_vextent(&args))) | 2537 | if ((error = xfs_alloc_vextent(&args))) |
2680 | return error; | 2538 | return error; |
@@ -2683,7 +2541,7 @@ xfs_bmap_btalloc( | |||
2683 | args.minlen > ap->minlen) { | 2541 | args.minlen > ap->minlen) { |
2684 | args.minlen = ap->minlen; | 2542 | args.minlen = ap->minlen; |
2685 | args.type = XFS_ALLOCTYPE_START_BNO; | 2543 | args.type = XFS_ALLOCTYPE_START_BNO; |
2686 | args.fsbno = ap->rval; | 2544 | args.fsbno = ap->blkno; |
2687 | if ((error = xfs_alloc_vextent(&args))) | 2545 | if ((error = xfs_alloc_vextent(&args))) |
2688 | return error; | 2546 | return error; |
2689 | } | 2547 | } |
@@ -2694,13 +2552,26 @@ xfs_bmap_btalloc( | |||
2694 | args.minleft = 0; | 2552 | args.minleft = 0; |
2695 | if ((error = xfs_alloc_vextent(&args))) | 2553 | if ((error = xfs_alloc_vextent(&args))) |
2696 | return error; | 2554 | return error; |
2697 | ap->low = 1; | 2555 | ap->flist->xbf_low = 1; |
2698 | } | 2556 | } |
2699 | if (args.fsbno != NULLFSBLOCK) { | 2557 | if (args.fsbno != NULLFSBLOCK) { |
2700 | ap->firstblock = ap->rval = args.fsbno; | 2558 | /* |
2559 | * check the allocation happened at the same or higher AG than | ||
2560 | * the first block that was allocated. | ||
2561 | */ | ||
2562 | ASSERT(*ap->firstblock == NULLFSBLOCK || | ||
2563 | XFS_FSB_TO_AGNO(mp, *ap->firstblock) == | ||
2564 | XFS_FSB_TO_AGNO(mp, args.fsbno) || | ||
2565 | (ap->flist->xbf_low && | ||
2566 | XFS_FSB_TO_AGNO(mp, *ap->firstblock) < | ||
2567 | XFS_FSB_TO_AGNO(mp, args.fsbno))); | ||
2568 | |||
2569 | ap->blkno = args.fsbno; | ||
2570 | if (*ap->firstblock == NULLFSBLOCK) | ||
2571 | *ap->firstblock = args.fsbno; | ||
2701 | ASSERT(nullfb || fb_agno == args.agno || | 2572 | ASSERT(nullfb || fb_agno == args.agno || |
2702 | (ap->low && fb_agno < args.agno)); | 2573 | (ap->flist->xbf_low && fb_agno < args.agno)); |
2703 | ap->alen = args.len; | 2574 | ap->length = args.len; |
2704 | ap->ip->i_d.di_nblocks += args.len; | 2575 | ap->ip->i_d.di_nblocks += args.len; |
2705 | xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); | 2576 | xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); |
2706 | if (ap->wasdel) | 2577 | if (ap->wasdel) |
@@ -2714,8 +2585,8 @@ xfs_bmap_btalloc( | |||
2714 | XFS_TRANS_DQ_BCOUNT, | 2585 | XFS_TRANS_DQ_BCOUNT, |
2715 | (long) args.len); | 2586 | (long) args.len); |
2716 | } else { | 2587 | } else { |
2717 | ap->rval = NULLFSBLOCK; | 2588 | ap->blkno = NULLFSBLOCK; |
2718 | ap->alen = 0; | 2589 | ap->length = 0; |
2719 | } | 2590 | } |
2720 | return 0; | 2591 | return 0; |
2721 | } | 2592 | } |
@@ -3589,7 +3460,7 @@ xfs_bmap_add_attrfork( | |||
3589 | } | 3460 | } |
3590 | ASSERT(ip->i_d.di_anextents == 0); | 3461 | ASSERT(ip->i_d.di_anextents == 0); |
3591 | 3462 | ||
3592 | xfs_trans_ijoin_ref(tp, ip, XFS_ILOCK_EXCL); | 3463 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); |
3593 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | 3464 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); |
3594 | 3465 | ||
3595 | switch (ip->i_d.di_format) { | 3466 | switch (ip->i_d.di_format) { |
@@ -3782,19 +3653,11 @@ xfs_bmap_compute_maxlevels( | |||
3782 | * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi | 3653 | * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi |
3783 | * caller. Frees all the extents that need freeing, which must be done | 3654 | * caller. Frees all the extents that need freeing, which must be done |
3784 | * last due to locking considerations. We never free any extents in | 3655 | * last due to locking considerations. We never free any extents in |
3785 | * the first transaction. This is to allow the caller to make the first | 3656 | * the first transaction. |
3786 | * transaction a synchronous one so that the pointers to the data being | ||
3787 | * broken in this transaction will be permanent before the data is actually | ||
3788 | * freed. This is necessary to prevent blocks from being reallocated | ||
3789 | * and written to before the free and reallocation are actually permanent. | ||
3790 | * We do not just make the first transaction synchronous here, because | ||
3791 | * there are more efficient ways to gain the same protection in some cases | ||
3792 | * (see the file truncation code). | ||
3793 | * | 3657 | * |
3794 | * Return 1 if the given transaction was committed and a new one | 3658 | * Return 1 if the given transaction was committed and a new one |
3795 | * started, and 0 otherwise in the committed parameter. | 3659 | * started, and 0 otherwise in the committed parameter. |
3796 | */ | 3660 | */ |
3797 | /*ARGSUSED*/ | ||
3798 | int /* error */ | 3661 | int /* error */ |
3799 | xfs_bmap_finish( | 3662 | xfs_bmap_finish( |
3800 | xfs_trans_t **tp, /* transaction pointer addr */ | 3663 | xfs_trans_t **tp, /* transaction pointer addr */ |
@@ -3994,42 +3857,122 @@ xfs_bmap_last_before( | |||
3994 | return 0; | 3857 | return 0; |
3995 | } | 3858 | } |
3996 | 3859 | ||
3860 | STATIC int | ||
3861 | xfs_bmap_last_extent( | ||
3862 | struct xfs_trans *tp, | ||
3863 | struct xfs_inode *ip, | ||
3864 | int whichfork, | ||
3865 | struct xfs_bmbt_irec *rec, | ||
3866 | int *is_empty) | ||
3867 | { | ||
3868 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); | ||
3869 | int error; | ||
3870 | int nextents; | ||
3871 | |||
3872 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | ||
3873 | error = xfs_iread_extents(tp, ip, whichfork); | ||
3874 | if (error) | ||
3875 | return error; | ||
3876 | } | ||
3877 | |||
3878 | nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); | ||
3879 | if (nextents == 0) { | ||
3880 | *is_empty = 1; | ||
3881 | return 0; | ||
3882 | } | ||
3883 | |||
3884 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, nextents - 1), rec); | ||
3885 | *is_empty = 0; | ||
3886 | return 0; | ||
3887 | } | ||
3888 | |||
3889 | /* | ||
3890 | * Check the last inode extent to determine whether this allocation will result | ||
3891 | * in blocks being allocated at the end of the file. When we allocate new data | ||
3892 | * blocks at the end of the file which do not start at the previous data block, | ||
3893 | * we will try to align the new blocks at stripe unit boundaries. | ||
3894 | * | ||
3895 | * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be | ||
3896 | * at, or past the EOF. | ||
3897 | */ | ||
3898 | STATIC int | ||
3899 | xfs_bmap_isaeof( | ||
3900 | struct xfs_bmalloca *bma, | ||
3901 | int whichfork) | ||
3902 | { | ||
3903 | struct xfs_bmbt_irec rec; | ||
3904 | int is_empty; | ||
3905 | int error; | ||
3906 | |||
3907 | bma->aeof = 0; | ||
3908 | error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec, | ||
3909 | &is_empty); | ||
3910 | if (error || is_empty) | ||
3911 | return error; | ||
3912 | |||
3913 | /* | ||
3914 | * Check if we are allocation or past the last extent, or at least into | ||
3915 | * the last delayed allocated extent. | ||
3916 | */ | ||
3917 | bma->aeof = bma->offset >= rec.br_startoff + rec.br_blockcount || | ||
3918 | (bma->offset >= rec.br_startoff && | ||
3919 | isnullstartblock(rec.br_startblock)); | ||
3920 | return 0; | ||
3921 | } | ||
3922 | |||
3923 | /* | ||
3924 | * Check if the endoff is outside the last extent. If so the caller will grow | ||
3925 | * the allocation to a stripe unit boundary. All offsets are considered outside | ||
3926 | * the end of file for an empty fork, so 1 is returned in *eof in that case. | ||
3927 | */ | ||
3928 | int | ||
3929 | xfs_bmap_eof( | ||
3930 | struct xfs_inode *ip, | ||
3931 | xfs_fileoff_t endoff, | ||
3932 | int whichfork, | ||
3933 | int *eof) | ||
3934 | { | ||
3935 | struct xfs_bmbt_irec rec; | ||
3936 | int error; | ||
3937 | |||
3938 | error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, eof); | ||
3939 | if (error || *eof) | ||
3940 | return error; | ||
3941 | |||
3942 | *eof = endoff >= rec.br_startoff + rec.br_blockcount; | ||
3943 | return 0; | ||
3944 | } | ||
3945 | |||
3997 | /* | 3946 | /* |
3998 | * Returns the file-relative block number of the first block past eof in | 3947 | * Returns the file-relative block number of the first block past eof in |
3999 | * the file. This is not based on i_size, it is based on the extent records. | 3948 | * the file. This is not based on i_size, it is based on the extent records. |
4000 | * Returns 0 for local files, as they do not have extent records. | 3949 | * Returns 0 for local files, as they do not have extent records. |
4001 | */ | 3950 | */ |
4002 | int /* error */ | 3951 | int |
4003 | xfs_bmap_last_offset( | 3952 | xfs_bmap_last_offset( |
4004 | xfs_trans_t *tp, /* transaction pointer */ | 3953 | struct xfs_trans *tp, |
4005 | xfs_inode_t *ip, /* incore inode */ | 3954 | struct xfs_inode *ip, |
4006 | xfs_fileoff_t *last_block, /* last block */ | 3955 | xfs_fileoff_t *last_block, |
4007 | int whichfork) /* data or attr fork */ | 3956 | int whichfork) |
4008 | { | 3957 | { |
4009 | xfs_bmbt_rec_host_t *ep; /* pointer to last extent */ | 3958 | struct xfs_bmbt_irec rec; |
4010 | int error; /* error return value */ | 3959 | int is_empty; |
4011 | xfs_ifork_t *ifp; /* inode fork pointer */ | 3960 | int error; |
4012 | xfs_extnum_t nextents; /* number of extent entries */ | 3961 | |
3962 | *last_block = 0; | ||
3963 | |||
3964 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) | ||
3965 | return 0; | ||
4013 | 3966 | ||
4014 | if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && | 3967 | if (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && |
4015 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | 3968 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) |
4016 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL) | ||
4017 | return XFS_ERROR(EIO); | 3969 | return XFS_ERROR(EIO); |
4018 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { | 3970 | |
4019 | *last_block = 0; | 3971 | error = xfs_bmap_last_extent(NULL, ip, whichfork, &rec, &is_empty); |
4020 | return 0; | 3972 | if (error || is_empty) |
4021 | } | ||
4022 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
4023 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | ||
4024 | (error = xfs_iread_extents(tp, ip, whichfork))) | ||
4025 | return error; | 3973 | return error; |
4026 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | 3974 | |
4027 | if (!nextents) { | 3975 | *last_block = rec.br_startoff + rec.br_blockcount; |
4028 | *last_block = 0; | ||
4029 | return 0; | ||
4030 | } | ||
4031 | ep = xfs_iext_get_ext(ifp, nextents - 1); | ||
4032 | *last_block = xfs_bmbt_get_startoff(ep) + xfs_bmbt_get_blockcount(ep); | ||
4033 | return 0; | 3976 | return 0; |
4034 | } | 3977 | } |
4035 | 3978 | ||
@@ -4159,7 +4102,6 @@ xfs_bmap_read_extents( | |||
4159 | xfs_extnum_t num_recs; | 4102 | xfs_extnum_t num_recs; |
4160 | xfs_extnum_t start; | 4103 | xfs_extnum_t start; |
4161 | 4104 | ||
4162 | |||
4163 | num_recs = xfs_btree_get_numrecs(block); | 4105 | num_recs = xfs_btree_get_numrecs(block); |
4164 | if (unlikely(i + num_recs > room)) { | 4106 | if (unlikely(i + num_recs > room)) { |
4165 | ASSERT(i + num_recs <= room); | 4107 | ASSERT(i + num_recs <= room); |
@@ -4282,9 +4224,8 @@ xfs_bmap_validate_ret( | |||
4282 | ASSERT(i == 0 || | 4224 | ASSERT(i == 0 || |
4283 | mval[i - 1].br_startoff + mval[i - 1].br_blockcount == | 4225 | mval[i - 1].br_startoff + mval[i - 1].br_blockcount == |
4284 | mval[i].br_startoff); | 4226 | mval[i].br_startoff); |
4285 | if ((flags & XFS_BMAPI_WRITE) && !(flags & XFS_BMAPI_DELAY)) | 4227 | ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK && |
4286 | ASSERT(mval[i].br_startblock != DELAYSTARTBLOCK && | 4228 | mval[i].br_startblock != HOLESTARTBLOCK); |
4287 | mval[i].br_startblock != HOLESTARTBLOCK); | ||
4288 | ASSERT(mval[i].br_state == XFS_EXT_NORM || | 4229 | ASSERT(mval[i].br_state == XFS_EXT_NORM || |
4289 | mval[i].br_state == XFS_EXT_UNWRITTEN); | 4230 | mval[i].br_state == XFS_EXT_UNWRITTEN); |
4290 | } | 4231 | } |
@@ -4293,66 +4234,609 @@ xfs_bmap_validate_ret( | |||
4293 | 4234 | ||
4294 | 4235 | ||
4295 | /* | 4236 | /* |
4296 | * Map file blocks to filesystem blocks. | 4237 | * Trim the returned map to the required bounds |
4297 | * File range is given by the bno/len pair. | 4238 | */ |
4298 | * Adds blocks to file if a write ("flags & XFS_BMAPI_WRITE" set) | 4239 | STATIC void |
4299 | * into a hole or past eof. | 4240 | xfs_bmapi_trim_map( |
4300 | * Only allocates blocks from a single allocation group, | 4241 | struct xfs_bmbt_irec *mval, |
4301 | * to avoid locking problems. | 4242 | struct xfs_bmbt_irec *got, |
4243 | xfs_fileoff_t *bno, | ||
4244 | xfs_filblks_t len, | ||
4245 | xfs_fileoff_t obno, | ||
4246 | xfs_fileoff_t end, | ||
4247 | int n, | ||
4248 | int flags) | ||
4249 | { | ||
4250 | if ((flags & XFS_BMAPI_ENTIRE) || | ||
4251 | got->br_startoff + got->br_blockcount <= obno) { | ||
4252 | *mval = *got; | ||
4253 | if (isnullstartblock(got->br_startblock)) | ||
4254 | mval->br_startblock = DELAYSTARTBLOCK; | ||
4255 | return; | ||
4256 | } | ||
4257 | |||
4258 | if (obno > *bno) | ||
4259 | *bno = obno; | ||
4260 | ASSERT((*bno >= obno) || (n == 0)); | ||
4261 | ASSERT(*bno < end); | ||
4262 | mval->br_startoff = *bno; | ||
4263 | if (isnullstartblock(got->br_startblock)) | ||
4264 | mval->br_startblock = DELAYSTARTBLOCK; | ||
4265 | else | ||
4266 | mval->br_startblock = got->br_startblock + | ||
4267 | (*bno - got->br_startoff); | ||
4268 | /* | ||
4269 | * Return the minimum of what we got and what we asked for for | ||
4270 | * the length. We can use the len variable here because it is | ||
4271 | * modified below and we could have been there before coming | ||
4272 | * here if the first part of the allocation didn't overlap what | ||
4273 | * was asked for. | ||
4274 | */ | ||
4275 | mval->br_blockcount = XFS_FILBLKS_MIN(end - *bno, | ||
4276 | got->br_blockcount - (*bno - got->br_startoff)); | ||
4277 | mval->br_state = got->br_state; | ||
4278 | ASSERT(mval->br_blockcount <= len); | ||
4279 | return; | ||
4280 | } | ||
4281 | |||
4282 | /* | ||
4283 | * Update and validate the extent map to return | ||
4284 | */ | ||
4285 | STATIC void | ||
4286 | xfs_bmapi_update_map( | ||
4287 | struct xfs_bmbt_irec **map, | ||
4288 | xfs_fileoff_t *bno, | ||
4289 | xfs_filblks_t *len, | ||
4290 | xfs_fileoff_t obno, | ||
4291 | xfs_fileoff_t end, | ||
4292 | int *n, | ||
4293 | int flags) | ||
4294 | { | ||
4295 | xfs_bmbt_irec_t *mval = *map; | ||
4296 | |||
4297 | ASSERT((flags & XFS_BMAPI_ENTIRE) || | ||
4298 | ((mval->br_startoff + mval->br_blockcount) <= end)); | ||
4299 | ASSERT((flags & XFS_BMAPI_ENTIRE) || (mval->br_blockcount <= *len) || | ||
4300 | (mval->br_startoff < obno)); | ||
4301 | |||
4302 | *bno = mval->br_startoff + mval->br_blockcount; | ||
4303 | *len = end - *bno; | ||
4304 | if (*n > 0 && mval->br_startoff == mval[-1].br_startoff) { | ||
4305 | /* update previous map with new information */ | ||
4306 | ASSERT(mval->br_startblock == mval[-1].br_startblock); | ||
4307 | ASSERT(mval->br_blockcount > mval[-1].br_blockcount); | ||
4308 | ASSERT(mval->br_state == mval[-1].br_state); | ||
4309 | mval[-1].br_blockcount = mval->br_blockcount; | ||
4310 | mval[-1].br_state = mval->br_state; | ||
4311 | } else if (*n > 0 && mval->br_startblock != DELAYSTARTBLOCK && | ||
4312 | mval[-1].br_startblock != DELAYSTARTBLOCK && | ||
4313 | mval[-1].br_startblock != HOLESTARTBLOCK && | ||
4314 | mval->br_startblock == mval[-1].br_startblock + | ||
4315 | mval[-1].br_blockcount && | ||
4316 | ((flags & XFS_BMAPI_IGSTATE) || | ||
4317 | mval[-1].br_state == mval->br_state)) { | ||
4318 | ASSERT(mval->br_startoff == | ||
4319 | mval[-1].br_startoff + mval[-1].br_blockcount); | ||
4320 | mval[-1].br_blockcount += mval->br_blockcount; | ||
4321 | } else if (*n > 0 && | ||
4322 | mval->br_startblock == DELAYSTARTBLOCK && | ||
4323 | mval[-1].br_startblock == DELAYSTARTBLOCK && | ||
4324 | mval->br_startoff == | ||
4325 | mval[-1].br_startoff + mval[-1].br_blockcount) { | ||
4326 | mval[-1].br_blockcount += mval->br_blockcount; | ||
4327 | mval[-1].br_state = mval->br_state; | ||
4328 | } else if (!((*n == 0) && | ||
4329 | ((mval->br_startoff + mval->br_blockcount) <= | ||
4330 | obno))) { | ||
4331 | mval++; | ||
4332 | (*n)++; | ||
4333 | } | ||
4334 | *map = mval; | ||
4335 | } | ||
4336 | |||
4337 | /* | ||
4338 | * Map file blocks to filesystem blocks without allocation. | ||
4339 | */ | ||
4340 | int | ||
4341 | xfs_bmapi_read( | ||
4342 | struct xfs_inode *ip, | ||
4343 | xfs_fileoff_t bno, | ||
4344 | xfs_filblks_t len, | ||
4345 | struct xfs_bmbt_irec *mval, | ||
4346 | int *nmap, | ||
4347 | int flags) | ||
4348 | { | ||
4349 | struct xfs_mount *mp = ip->i_mount; | ||
4350 | struct xfs_ifork *ifp; | ||
4351 | struct xfs_bmbt_irec got; | ||
4352 | struct xfs_bmbt_irec prev; | ||
4353 | xfs_fileoff_t obno; | ||
4354 | xfs_fileoff_t end; | ||
4355 | xfs_extnum_t lastx; | ||
4356 | int error; | ||
4357 | int eof; | ||
4358 | int n = 0; | ||
4359 | int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | ||
4360 | XFS_ATTR_FORK : XFS_DATA_FORK; | ||
4361 | |||
4362 | ASSERT(*nmap >= 1); | ||
4363 | ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE| | ||
4364 | XFS_BMAPI_IGSTATE))); | ||
4365 | |||
4366 | if (unlikely(XFS_TEST_ERROR( | ||
4367 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | ||
4368 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), | ||
4369 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { | ||
4370 | XFS_ERROR_REPORT("xfs_bmapi_read", XFS_ERRLEVEL_LOW, mp); | ||
4371 | return XFS_ERROR(EFSCORRUPTED); | ||
4372 | } | ||
4373 | |||
4374 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
4375 | return XFS_ERROR(EIO); | ||
4376 | |||
4377 | XFS_STATS_INC(xs_blk_mapr); | ||
4378 | |||
4379 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
4380 | ASSERT(ifp->if_ext_max == | ||
4381 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); | ||
4382 | |||
4383 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | ||
4384 | error = xfs_iread_extents(NULL, ip, whichfork); | ||
4385 | if (error) | ||
4386 | return error; | ||
4387 | } | ||
4388 | |||
4389 | xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); | ||
4390 | end = bno + len; | ||
4391 | obno = bno; | ||
4392 | |||
4393 | while (bno < end && n < *nmap) { | ||
4394 | /* Reading past eof, act as though there's a hole up to end. */ | ||
4395 | if (eof) | ||
4396 | got.br_startoff = end; | ||
4397 | if (got.br_startoff > bno) { | ||
4398 | /* Reading in a hole. */ | ||
4399 | mval->br_startoff = bno; | ||
4400 | mval->br_startblock = HOLESTARTBLOCK; | ||
4401 | mval->br_blockcount = | ||
4402 | XFS_FILBLKS_MIN(len, got.br_startoff - bno); | ||
4403 | mval->br_state = XFS_EXT_NORM; | ||
4404 | bno += mval->br_blockcount; | ||
4405 | len -= mval->br_blockcount; | ||
4406 | mval++; | ||
4407 | n++; | ||
4408 | continue; | ||
4409 | } | ||
4410 | |||
4411 | /* set up the extent map to return. */ | ||
4412 | xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); | ||
4413 | xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); | ||
4414 | |||
4415 | /* If we're done, stop now. */ | ||
4416 | if (bno >= end || n >= *nmap) | ||
4417 | break; | ||
4418 | |||
4419 | /* Else go on to the next record. */ | ||
4420 | if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) | ||
4421 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got); | ||
4422 | else | ||
4423 | eof = 1; | ||
4424 | } | ||
4425 | *nmap = n; | ||
4426 | return 0; | ||
4427 | } | ||
4428 | |||
4429 | STATIC int | ||
4430 | xfs_bmapi_reserve_delalloc( | ||
4431 | struct xfs_inode *ip, | ||
4432 | xfs_fileoff_t aoff, | ||
4433 | xfs_filblks_t len, | ||
4434 | struct xfs_bmbt_irec *got, | ||
4435 | struct xfs_bmbt_irec *prev, | ||
4436 | xfs_extnum_t *lastx, | ||
4437 | int eof) | ||
4438 | { | ||
4439 | struct xfs_mount *mp = ip->i_mount; | ||
4440 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
4441 | xfs_extlen_t alen; | ||
4442 | xfs_extlen_t indlen; | ||
4443 | char rt = XFS_IS_REALTIME_INODE(ip); | ||
4444 | xfs_extlen_t extsz; | ||
4445 | int error; | ||
4446 | |||
4447 | alen = XFS_FILBLKS_MIN(len, MAXEXTLEN); | ||
4448 | if (!eof) | ||
4449 | alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff); | ||
4450 | |||
4451 | /* Figure out the extent size, adjust alen */ | ||
4452 | extsz = xfs_get_extsz_hint(ip); | ||
4453 | if (extsz) { | ||
4454 | /* | ||
4455 | * Make sure we don't exceed a single extent length when we | ||
4456 | * align the extent by reducing length we are going to | ||
4457 | * allocate by the maximum amount extent size aligment may | ||
4458 | * require. | ||
4459 | */ | ||
4460 | alen = XFS_FILBLKS_MIN(len, MAXEXTLEN - (2 * extsz - 1)); | ||
4461 | error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof, | ||
4462 | 1, 0, &aoff, &alen); | ||
4463 | ASSERT(!error); | ||
4464 | } | ||
4465 | |||
4466 | if (rt) | ||
4467 | extsz = alen / mp->m_sb.sb_rextsize; | ||
4468 | |||
4469 | /* | ||
4470 | * Make a transaction-less quota reservation for delayed allocation | ||
4471 | * blocks. This number gets adjusted later. We return if we haven't | ||
4472 | * allocated blocks already inside this loop. | ||
4473 | */ | ||
4474 | error = xfs_trans_reserve_quota_nblks(NULL, ip, (long)alen, 0, | ||
4475 | rt ? XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); | ||
4476 | if (error) | ||
4477 | return error; | ||
4478 | |||
4479 | /* | ||
4480 | * Split changing sb for alen and indlen since they could be coming | ||
4481 | * from different places. | ||
4482 | */ | ||
4483 | indlen = (xfs_extlen_t)xfs_bmap_worst_indlen(ip, alen); | ||
4484 | ASSERT(indlen > 0); | ||
4485 | |||
4486 | if (rt) { | ||
4487 | error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, | ||
4488 | -((int64_t)extsz), 0); | ||
4489 | } else { | ||
4490 | error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | ||
4491 | -((int64_t)alen), 0); | ||
4492 | } | ||
4493 | |||
4494 | if (error) | ||
4495 | goto out_unreserve_quota; | ||
4496 | |||
4497 | error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | ||
4498 | -((int64_t)indlen), 0); | ||
4499 | if (error) | ||
4500 | goto out_unreserve_blocks; | ||
4501 | |||
4502 | |||
4503 | ip->i_delayed_blks += alen; | ||
4504 | |||
4505 | got->br_startoff = aoff; | ||
4506 | got->br_startblock = nullstartblock(indlen); | ||
4507 | got->br_blockcount = alen; | ||
4508 | got->br_state = XFS_EXT_NORM; | ||
4509 | xfs_bmap_add_extent_hole_delay(ip, lastx, got); | ||
4510 | |||
4511 | /* | ||
4512 | * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay | ||
4513 | * might have merged it into one of the neighbouring ones. | ||
4514 | */ | ||
4515 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *lastx), got); | ||
4516 | |||
4517 | ASSERT(got->br_startoff <= aoff); | ||
4518 | ASSERT(got->br_startoff + got->br_blockcount >= aoff + alen); | ||
4519 | ASSERT(isnullstartblock(got->br_startblock)); | ||
4520 | ASSERT(got->br_state == XFS_EXT_NORM); | ||
4521 | return 0; | ||
4522 | |||
4523 | out_unreserve_blocks: | ||
4524 | if (rt) | ||
4525 | xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0); | ||
4526 | else | ||
4527 | xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0); | ||
4528 | out_unreserve_quota: | ||
4529 | if (XFS_IS_QUOTA_ON(mp)) | ||
4530 | xfs_trans_unreserve_quota_nblks(NULL, ip, alen, 0, rt ? | ||
4531 | XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS); | ||
4532 | return error; | ||
4533 | } | ||
4534 | |||
4535 | /* | ||
4536 | * Map file blocks to filesystem blocks, adding delayed allocations as needed. | ||
4537 | */ | ||
4538 | int | ||
4539 | xfs_bmapi_delay( | ||
4540 | struct xfs_inode *ip, /* incore inode */ | ||
4541 | xfs_fileoff_t bno, /* starting file offs. mapped */ | ||
4542 | xfs_filblks_t len, /* length to map in file */ | ||
4543 | struct xfs_bmbt_irec *mval, /* output: map values */ | ||
4544 | int *nmap, /* i/o: mval size/count */ | ||
4545 | int flags) /* XFS_BMAPI_... */ | ||
4546 | { | ||
4547 | struct xfs_mount *mp = ip->i_mount; | ||
4548 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); | ||
4549 | struct xfs_bmbt_irec got; /* current file extent record */ | ||
4550 | struct xfs_bmbt_irec prev; /* previous file extent record */ | ||
4551 | xfs_fileoff_t obno; /* old block number (offset) */ | ||
4552 | xfs_fileoff_t end; /* end of mapped file region */ | ||
4553 | xfs_extnum_t lastx; /* last useful extent number */ | ||
4554 | int eof; /* we've hit the end of extents */ | ||
4555 | int n = 0; /* current extent index */ | ||
4556 | int error = 0; | ||
4557 | |||
4558 | ASSERT(*nmap >= 1); | ||
4559 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); | ||
4560 | ASSERT(!(flags & ~XFS_BMAPI_ENTIRE)); | ||
4561 | |||
4562 | if (unlikely(XFS_TEST_ERROR( | ||
4563 | (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS && | ||
4564 | XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE), | ||
4565 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { | ||
4566 | XFS_ERROR_REPORT("xfs_bmapi_delay", XFS_ERRLEVEL_LOW, mp); | ||
4567 | return XFS_ERROR(EFSCORRUPTED); | ||
4568 | } | ||
4569 | |||
4570 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
4571 | return XFS_ERROR(EIO); | ||
4572 | |||
4573 | XFS_STATS_INC(xs_blk_mapw); | ||
4574 | |||
4575 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { | ||
4576 | error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK); | ||
4577 | if (error) | ||
4578 | return error; | ||
4579 | } | ||
4580 | |||
4581 | xfs_bmap_search_extents(ip, bno, XFS_DATA_FORK, &eof, &lastx, &got, &prev); | ||
4582 | end = bno + len; | ||
4583 | obno = bno; | ||
4584 | |||
4585 | while (bno < end && n < *nmap) { | ||
4586 | if (eof || got.br_startoff > bno) { | ||
4587 | error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got, | ||
4588 | &prev, &lastx, eof); | ||
4589 | if (error) { | ||
4590 | if (n == 0) { | ||
4591 | *nmap = 0; | ||
4592 | return error; | ||
4593 | } | ||
4594 | break; | ||
4595 | } | ||
4596 | } | ||
4597 | |||
4598 | /* set up the extent map to return. */ | ||
4599 | xfs_bmapi_trim_map(mval, &got, &bno, len, obno, end, n, flags); | ||
4600 | xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); | ||
4601 | |||
4602 | /* If we're done, stop now. */ | ||
4603 | if (bno >= end || n >= *nmap) | ||
4604 | break; | ||
4605 | |||
4606 | /* Else go on to the next record. */ | ||
4607 | prev = got; | ||
4608 | if (++lastx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) | ||
4609 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, lastx), &got); | ||
4610 | else | ||
4611 | eof = 1; | ||
4612 | } | ||
4613 | |||
4614 | *nmap = n; | ||
4615 | return 0; | ||
4616 | } | ||
4617 | |||
4618 | |||
4619 | STATIC int | ||
4620 | xfs_bmapi_allocate( | ||
4621 | struct xfs_bmalloca *bma, | ||
4622 | int flags) | ||
4623 | { | ||
4624 | struct xfs_mount *mp = bma->ip->i_mount; | ||
4625 | int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | ||
4626 | XFS_ATTR_FORK : XFS_DATA_FORK; | ||
4627 | struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); | ||
4628 | int tmp_logflags = 0; | ||
4629 | int error; | ||
4630 | int rt; | ||
4631 | |||
4632 | rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(bma->ip); | ||
4633 | |||
4634 | /* | ||
4635 | * For the wasdelay case, we could also just allocate the stuff asked | ||
4636 | * for in this bmap call but that wouldn't be as good. | ||
4637 | */ | ||
4638 | if (bma->wasdel) { | ||
4639 | bma->length = (xfs_extlen_t)bma->got.br_blockcount; | ||
4640 | bma->offset = bma->got.br_startoff; | ||
4641 | if (bma->idx != NULLEXTNUM && bma->idx) { | ||
4642 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx - 1), | ||
4643 | &bma->prev); | ||
4644 | } | ||
4645 | } else { | ||
4646 | bma->length = XFS_FILBLKS_MIN(bma->length, MAXEXTLEN); | ||
4647 | if (!bma->eof) | ||
4648 | bma->length = XFS_FILBLKS_MIN(bma->length, | ||
4649 | bma->got.br_startoff - bma->offset); | ||
4650 | } | ||
4651 | |||
4652 | /* | ||
4653 | * Indicate if this is the first user data in the file, or just any | ||
4654 | * user data. | ||
4655 | */ | ||
4656 | if (!(flags & XFS_BMAPI_METADATA)) { | ||
4657 | bma->userdata = (bma->offset == 0) ? | ||
4658 | XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA; | ||
4659 | } | ||
4660 | |||
4661 | bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1; | ||
4662 | |||
4663 | /* | ||
4664 | * Only want to do the alignment at the eof if it is userdata and | ||
4665 | * allocation length is larger than a stripe unit. | ||
4666 | */ | ||
4667 | if (mp->m_dalign && bma->length >= mp->m_dalign && | ||
4668 | !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) { | ||
4669 | error = xfs_bmap_isaeof(bma, whichfork); | ||
4670 | if (error) | ||
4671 | return error; | ||
4672 | } | ||
4673 | |||
4674 | error = xfs_bmap_alloc(bma); | ||
4675 | if (error) | ||
4676 | return error; | ||
4677 | |||
4678 | if (bma->flist->xbf_low) | ||
4679 | bma->minleft = 0; | ||
4680 | if (bma->cur) | ||
4681 | bma->cur->bc_private.b.firstblock = *bma->firstblock; | ||
4682 | if (bma->blkno == NULLFSBLOCK) | ||
4683 | return 0; | ||
4684 | if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) { | ||
4685 | bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork); | ||
4686 | bma->cur->bc_private.b.firstblock = *bma->firstblock; | ||
4687 | bma->cur->bc_private.b.flist = bma->flist; | ||
4688 | } | ||
4689 | /* | ||
4690 | * Bump the number of extents we've allocated | ||
4691 | * in this call. | ||
4692 | */ | ||
4693 | bma->nallocs++; | ||
4694 | |||
4695 | if (bma->cur) | ||
4696 | bma->cur->bc_private.b.flags = | ||
4697 | bma->wasdel ? XFS_BTCUR_BPRV_WASDEL : 0; | ||
4698 | |||
4699 | bma->got.br_startoff = bma->offset; | ||
4700 | bma->got.br_startblock = bma->blkno; | ||
4701 | bma->got.br_blockcount = bma->length; | ||
4702 | bma->got.br_state = XFS_EXT_NORM; | ||
4703 | |||
4704 | /* | ||
4705 | * A wasdelay extent has been initialized, so shouldn't be flagged | ||
4706 | * as unwritten. | ||
4707 | */ | ||
4708 | if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) && | ||
4709 | xfs_sb_version_hasextflgbit(&mp->m_sb)) | ||
4710 | bma->got.br_state = XFS_EXT_UNWRITTEN; | ||
4711 | |||
4712 | if (bma->wasdel) | ||
4713 | error = xfs_bmap_add_extent_delay_real(bma); | ||
4714 | else | ||
4715 | error = xfs_bmap_add_extent_hole_real(bma, whichfork); | ||
4716 | |||
4717 | bma->logflags |= tmp_logflags; | ||
4718 | if (error) | ||
4719 | return error; | ||
4720 | |||
4721 | /* | ||
4722 | * Update our extent pointer, given that xfs_bmap_add_extent_delay_real | ||
4723 | * or xfs_bmap_add_extent_hole_real might have merged it into one of | ||
4724 | * the neighbouring ones. | ||
4725 | */ | ||
4726 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got); | ||
4727 | |||
4728 | ASSERT(bma->got.br_startoff <= bma->offset); | ||
4729 | ASSERT(bma->got.br_startoff + bma->got.br_blockcount >= | ||
4730 | bma->offset + bma->length); | ||
4731 | ASSERT(bma->got.br_state == XFS_EXT_NORM || | ||
4732 | bma->got.br_state == XFS_EXT_UNWRITTEN); | ||
4733 | return 0; | ||
4734 | } | ||
4735 | |||
4736 | STATIC int | ||
4737 | xfs_bmapi_convert_unwritten( | ||
4738 | struct xfs_bmalloca *bma, | ||
4739 | struct xfs_bmbt_irec *mval, | ||
4740 | xfs_filblks_t len, | ||
4741 | int flags) | ||
4742 | { | ||
4743 | int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | ||
4744 | XFS_ATTR_FORK : XFS_DATA_FORK; | ||
4745 | struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); | ||
4746 | int tmp_logflags = 0; | ||
4747 | int error; | ||
4748 | |||
4749 | /* check if we need to do unwritten->real conversion */ | ||
4750 | if (mval->br_state == XFS_EXT_UNWRITTEN && | ||
4751 | (flags & XFS_BMAPI_PREALLOC)) | ||
4752 | return 0; | ||
4753 | |||
4754 | /* check if we need to do real->unwritten conversion */ | ||
4755 | if (mval->br_state == XFS_EXT_NORM && | ||
4756 | (flags & (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) != | ||
4757 | (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) | ||
4758 | return 0; | ||
4759 | |||
4760 | /* | ||
4761 | * Modify (by adding) the state flag, if writing. | ||
4762 | */ | ||
4763 | ASSERT(mval->br_blockcount <= len); | ||
4764 | if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) { | ||
4765 | bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp, | ||
4766 | bma->ip, whichfork); | ||
4767 | bma->cur->bc_private.b.firstblock = *bma->firstblock; | ||
4768 | bma->cur->bc_private.b.flist = bma->flist; | ||
4769 | } | ||
4770 | mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) | ||
4771 | ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; | ||
4772 | |||
4773 | error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx, | ||
4774 | &bma->cur, mval, bma->firstblock, bma->flist, | ||
4775 | &tmp_logflags); | ||
4776 | bma->logflags |= tmp_logflags; | ||
4777 | if (error) | ||
4778 | return error; | ||
4779 | |||
4780 | /* | ||
4781 | * Update our extent pointer, given that | ||
4782 | * xfs_bmap_add_extent_unwritten_real might have merged it into one | ||
4783 | * of the neighbouring ones. | ||
4784 | */ | ||
4785 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma->idx), &bma->got); | ||
4786 | |||
4787 | /* | ||
4788 | * We may have combined previously unwritten space with written space, | ||
4789 | * so generate another request. | ||
4790 | */ | ||
4791 | if (mval->br_blockcount < len) | ||
4792 | return EAGAIN; | ||
4793 | return 0; | ||
4794 | } | ||
4795 | |||
4796 | /* | ||
4797 | * Map file blocks to filesystem blocks, and allocate blocks or convert the | ||
4798 | * extent state if necessary. Details behaviour is controlled by the flags | ||
4799 | * parameter. Only allocates blocks from a single allocation group, to avoid | ||
4800 | * locking problems. | ||
4801 | * | ||
4302 | * The returned value in "firstblock" from the first call in a transaction | 4802 | * The returned value in "firstblock" from the first call in a transaction |
4303 | * must be remembered and presented to subsequent calls in "firstblock". | 4803 | * must be remembered and presented to subsequent calls in "firstblock". |
4304 | * An upper bound for the number of blocks to be allocated is supplied to | 4804 | * An upper bound for the number of blocks to be allocated is supplied to |
4305 | * the first call in "total"; if no allocation group has that many free | 4805 | * the first call in "total"; if no allocation group has that many free |
4306 | * blocks then the call will fail (return NULLFSBLOCK in "firstblock"). | 4806 | * blocks then the call will fail (return NULLFSBLOCK in "firstblock"). |
4307 | */ | 4807 | */ |
4308 | int /* error */ | 4808 | int |
4309 | xfs_bmapi( | 4809 | xfs_bmapi_write( |
4310 | xfs_trans_t *tp, /* transaction pointer */ | 4810 | struct xfs_trans *tp, /* transaction pointer */ |
4311 | xfs_inode_t *ip, /* incore inode */ | 4811 | struct xfs_inode *ip, /* incore inode */ |
4312 | xfs_fileoff_t bno, /* starting file offs. mapped */ | 4812 | xfs_fileoff_t bno, /* starting file offs. mapped */ |
4313 | xfs_filblks_t len, /* length to map in file */ | 4813 | xfs_filblks_t len, /* length to map in file */ |
4314 | int flags, /* XFS_BMAPI_... */ | 4814 | int flags, /* XFS_BMAPI_... */ |
4315 | xfs_fsblock_t *firstblock, /* first allocated block | 4815 | xfs_fsblock_t *firstblock, /* first allocated block |
4316 | controls a.g. for allocs */ | 4816 | controls a.g. for allocs */ |
4317 | xfs_extlen_t total, /* total blocks needed */ | 4817 | xfs_extlen_t total, /* total blocks needed */ |
4318 | xfs_bmbt_irec_t *mval, /* output: map values */ | 4818 | struct xfs_bmbt_irec *mval, /* output: map values */ |
4319 | int *nmap, /* i/o: mval size/count */ | 4819 | int *nmap, /* i/o: mval size/count */ |
4320 | xfs_bmap_free_t *flist) /* i/o: list extents to free */ | 4820 | struct xfs_bmap_free *flist) /* i/o: list extents to free */ |
4321 | { | 4821 | { |
4322 | xfs_fsblock_t abno; /* allocated block number */ | 4822 | struct xfs_mount *mp = ip->i_mount; |
4323 | xfs_extlen_t alen; /* allocated extent length */ | 4823 | struct xfs_ifork *ifp; |
4324 | xfs_fileoff_t aoff; /* allocated file offset */ | 4824 | struct xfs_bmalloca bma = { 0 }; /* args for xfs_bmap_alloc */ |
4325 | xfs_bmalloca_t bma = { 0 }; /* args for xfs_bmap_alloc */ | 4825 | xfs_fileoff_t end; /* end of mapped file region */ |
4326 | xfs_btree_cur_t *cur; /* bmap btree cursor */ | 4826 | int eof; /* after the end of extents */ |
4327 | xfs_fileoff_t end; /* end of mapped file region */ | 4827 | int error; /* error return */ |
4328 | int eof; /* we've hit the end of extents */ | 4828 | int n; /* current extent index */ |
4329 | xfs_bmbt_rec_host_t *ep; /* extent record pointer */ | 4829 | xfs_fileoff_t obno; /* old block number (offset) */ |
4330 | int error; /* error return */ | 4830 | int whichfork; /* data or attr fork */ |
4331 | xfs_bmbt_irec_t got; /* current file extent record */ | 4831 | char inhole; /* current location is hole in file */ |
4332 | xfs_ifork_t *ifp; /* inode fork pointer */ | 4832 | char wasdelay; /* old extent was delayed */ |
4333 | xfs_extlen_t indlen; /* indirect blocks length */ | 4833 | |
4334 | xfs_extnum_t lastx; /* last useful extent number */ | ||
4335 | int logflags; /* flags for transaction logging */ | ||
4336 | xfs_extlen_t minleft; /* min blocks left after allocation */ | ||
4337 | xfs_extlen_t minlen; /* min allocation size */ | ||
4338 | xfs_mount_t *mp; /* xfs mount structure */ | ||
4339 | int n; /* current extent index */ | ||
4340 | int nallocs; /* number of extents alloc'd */ | ||
4341 | xfs_extnum_t nextents; /* number of extents in file */ | ||
4342 | xfs_fileoff_t obno; /* old block number (offset) */ | ||
4343 | xfs_bmbt_irec_t prev; /* previous file extent record */ | ||
4344 | int tmp_logflags; /* temp flags holder */ | ||
4345 | int whichfork; /* data or attr fork */ | ||
4346 | char inhole; /* current location is hole in file */ | ||
4347 | char wasdelay; /* old extent was delayed */ | ||
4348 | char wr; /* this is a write request */ | ||
4349 | char rt; /* this is a realtime file */ | ||
4350 | #ifdef DEBUG | 4834 | #ifdef DEBUG |
4351 | xfs_fileoff_t orig_bno; /* original block number value */ | 4835 | xfs_fileoff_t orig_bno; /* original block number value */ |
4352 | int orig_flags; /* original flags arg value */ | 4836 | int orig_flags; /* original flags arg value */ |
4353 | xfs_filblks_t orig_len; /* original value of len arg */ | 4837 | xfs_filblks_t orig_len; /* original value of len arg */ |
4354 | xfs_bmbt_irec_t *orig_mval; /* original value of mval */ | 4838 | struct xfs_bmbt_irec *orig_mval; /* original value of mval */ |
4355 | int orig_nmap; /* original value of *nmap */ | 4839 | int orig_nmap; /* original value of *nmap */ |
4356 | 4840 | ||
4357 | orig_bno = bno; | 4841 | orig_bno = bno; |
4358 | orig_len = len; | 4842 | orig_len = len; |
@@ -4360,488 +4844,133 @@ xfs_bmapi( | |||
4360 | orig_mval = mval; | 4844 | orig_mval = mval; |
4361 | orig_nmap = *nmap; | 4845 | orig_nmap = *nmap; |
4362 | #endif | 4846 | #endif |
4847 | |||
4363 | ASSERT(*nmap >= 1); | 4848 | ASSERT(*nmap >= 1); |
4364 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP || !(flags & XFS_BMAPI_WRITE)); | 4849 | ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); |
4850 | ASSERT(!(flags & XFS_BMAPI_IGSTATE)); | ||
4851 | ASSERT(tp != NULL); | ||
4852 | |||
4365 | whichfork = (flags & XFS_BMAPI_ATTRFORK) ? | 4853 | whichfork = (flags & XFS_BMAPI_ATTRFORK) ? |
4366 | XFS_ATTR_FORK : XFS_DATA_FORK; | 4854 | XFS_ATTR_FORK : XFS_DATA_FORK; |
4367 | mp = ip->i_mount; | 4855 | |
4368 | if (unlikely(XFS_TEST_ERROR( | 4856 | if (unlikely(XFS_TEST_ERROR( |
4369 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && | 4857 | (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && |
4370 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && | 4858 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && |
4371 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL), | 4859 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL), |
4372 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { | 4860 | mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { |
4373 | XFS_ERROR_REPORT("xfs_bmapi", XFS_ERRLEVEL_LOW, mp); | 4861 | XFS_ERROR_REPORT("xfs_bmapi_write", XFS_ERRLEVEL_LOW, mp); |
4374 | return XFS_ERROR(EFSCORRUPTED); | 4862 | return XFS_ERROR(EFSCORRUPTED); |
4375 | } | 4863 | } |
4864 | |||
4376 | if (XFS_FORCED_SHUTDOWN(mp)) | 4865 | if (XFS_FORCED_SHUTDOWN(mp)) |
4377 | return XFS_ERROR(EIO); | 4866 | return XFS_ERROR(EIO); |
4378 | rt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); | 4867 | |
4379 | ifp = XFS_IFORK_PTR(ip, whichfork); | 4868 | ifp = XFS_IFORK_PTR(ip, whichfork); |
4380 | ASSERT(ifp->if_ext_max == | 4869 | ASSERT(ifp->if_ext_max == |
4381 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); | 4870 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); |
4382 | if ((wr = (flags & XFS_BMAPI_WRITE)) != 0) | 4871 | |
4383 | XFS_STATS_INC(xs_blk_mapw); | 4872 | XFS_STATS_INC(xs_blk_mapw); |
4384 | else | 4873 | |
4385 | XFS_STATS_INC(xs_blk_mapr); | ||
4386 | /* | ||
4387 | * IGSTATE flag is used to combine extents which | ||
4388 | * differ only due to the state of the extents. | ||
4389 | * This technique is used from xfs_getbmap() | ||
4390 | * when the caller does not wish to see the | ||
4391 | * separation (which is the default). | ||
4392 | * | ||
4393 | * This technique is also used when writing a | ||
4394 | * buffer which has been partially written, | ||
4395 | * (usually by being flushed during a chunkread), | ||
4396 | * to ensure one write takes place. This also | ||
4397 | * prevents a change in the xfs inode extents at | ||
4398 | * this time, intentionally. This change occurs | ||
4399 | * on completion of the write operation, in | ||
4400 | * xfs_strat_comp(), where the xfs_bmapi() call | ||
4401 | * is transactioned, and the extents combined. | ||
4402 | */ | ||
4403 | if ((flags & XFS_BMAPI_IGSTATE) && wr) /* if writing unwritten space */ | ||
4404 | wr = 0; /* no allocations are allowed */ | ||
4405 | ASSERT(wr || !(flags & XFS_BMAPI_DELAY)); | ||
4406 | logflags = 0; | ||
4407 | nallocs = 0; | ||
4408 | cur = NULL; | ||
4409 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { | 4874 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { |
4410 | ASSERT(wr && tp); | 4875 | error = xfs_bmap_local_to_extents(tp, ip, firstblock, total, |
4411 | if ((error = xfs_bmap_local_to_extents(tp, ip, | 4876 | &bma.logflags, whichfork); |
4412 | firstblock, total, &logflags, whichfork))) | 4877 | if (error) |
4413 | goto error0; | 4878 | goto error0; |
4414 | } | 4879 | } |
4415 | if (wr && *firstblock == NULLFSBLOCK) { | 4880 | |
4881 | if (*firstblock == NULLFSBLOCK) { | ||
4416 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE) | 4882 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE) |
4417 | minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1; | 4883 | bma.minleft = be16_to_cpu(ifp->if_broot->bb_level) + 1; |
4418 | else | 4884 | else |
4419 | minleft = 1; | 4885 | bma.minleft = 1; |
4420 | } else | 4886 | } else { |
4421 | minleft = 0; | 4887 | bma.minleft = 0; |
4422 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | 4888 | } |
4423 | (error = xfs_iread_extents(tp, ip, whichfork))) | 4889 | |
4424 | goto error0; | 4890 | if (!(ifp->if_flags & XFS_IFEXTENTS)) { |
4425 | ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, | 4891 | error = xfs_iread_extents(tp, ip, whichfork); |
4426 | &prev); | 4892 | if (error) |
4427 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | 4893 | goto error0; |
4894 | } | ||
4895 | |||
4896 | xfs_bmap_search_extents(ip, bno, whichfork, &eof, &bma.idx, &bma.got, | ||
4897 | &bma.prev); | ||
4428 | n = 0; | 4898 | n = 0; |
4429 | end = bno + len; | 4899 | end = bno + len; |
4430 | obno = bno; | 4900 | obno = bno; |
4431 | bma.ip = NULL; | 4901 | |
4902 | bma.tp = tp; | ||
4903 | bma.ip = ip; | ||
4904 | bma.total = total; | ||
4905 | bma.userdata = 0; | ||
4906 | bma.flist = flist; | ||
4907 | bma.firstblock = firstblock; | ||
4432 | 4908 | ||
4433 | while (bno < end && n < *nmap) { | 4909 | while (bno < end && n < *nmap) { |
4434 | /* | 4910 | inhole = eof || bma.got.br_startoff > bno; |
4435 | * Reading past eof, act as though there's a hole | 4911 | wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); |
4436 | * up to end. | 4912 | |
4437 | */ | ||
4438 | if (eof && !wr) | ||
4439 | got.br_startoff = end; | ||
4440 | inhole = eof || got.br_startoff > bno; | ||
4441 | wasdelay = wr && !inhole && !(flags & XFS_BMAPI_DELAY) && | ||
4442 | isnullstartblock(got.br_startblock); | ||
4443 | /* | 4913 | /* |
4444 | * First, deal with the hole before the allocated space | 4914 | * First, deal with the hole before the allocated space |
4445 | * that we found, if any. | 4915 | * that we found, if any. |
4446 | */ | 4916 | */ |
4447 | if (wr && (inhole || wasdelay)) { | 4917 | if (inhole || wasdelay) { |
4448 | /* | 4918 | bma.eof = eof; |
4449 | * For the wasdelay case, we could also just | 4919 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); |
4450 | * allocate the stuff asked for in this bmap call | 4920 | bma.wasdel = wasdelay; |
4451 | * but that wouldn't be as good. | 4921 | bma.length = len; |
4452 | */ | 4922 | bma.offset = bno; |
4453 | if (wasdelay) { | 4923 | |
4454 | alen = (xfs_extlen_t)got.br_blockcount; | 4924 | error = xfs_bmapi_allocate(&bma, flags); |
4455 | aoff = got.br_startoff; | ||
4456 | if (lastx != NULLEXTNUM && lastx) { | ||
4457 | ep = xfs_iext_get_ext(ifp, lastx - 1); | ||
4458 | xfs_bmbt_get_all(ep, &prev); | ||
4459 | } | ||
4460 | } else { | ||
4461 | alen = (xfs_extlen_t) | ||
4462 | XFS_FILBLKS_MIN(len, MAXEXTLEN); | ||
4463 | if (!eof) | ||
4464 | alen = (xfs_extlen_t) | ||
4465 | XFS_FILBLKS_MIN(alen, | ||
4466 | got.br_startoff - bno); | ||
4467 | aoff = bno; | ||
4468 | } | ||
4469 | minlen = (flags & XFS_BMAPI_CONTIG) ? alen : 1; | ||
4470 | if (flags & XFS_BMAPI_DELAY) { | ||
4471 | xfs_extlen_t extsz; | ||
4472 | |||
4473 | /* Figure out the extent size, adjust alen */ | ||
4474 | extsz = xfs_get_extsz_hint(ip); | ||
4475 | if (extsz) { | ||
4476 | /* | ||
4477 | * make sure we don't exceed a single | ||
4478 | * extent length when we align the | ||
4479 | * extent by reducing length we are | ||
4480 | * going to allocate by the maximum | ||
4481 | * amount extent size aligment may | ||
4482 | * require. | ||
4483 | */ | ||
4484 | alen = XFS_FILBLKS_MIN(len, | ||
4485 | MAXEXTLEN - (2 * extsz - 1)); | ||
4486 | error = xfs_bmap_extsize_align(mp, | ||
4487 | &got, &prev, extsz, | ||
4488 | rt, eof, | ||
4489 | flags&XFS_BMAPI_DELAY, | ||
4490 | flags&XFS_BMAPI_CONVERT, | ||
4491 | &aoff, &alen); | ||
4492 | ASSERT(!error); | ||
4493 | } | ||
4494 | |||
4495 | if (rt) | ||
4496 | extsz = alen / mp->m_sb.sb_rextsize; | ||
4497 | |||
4498 | /* | ||
4499 | * Make a transaction-less quota reservation for | ||
4500 | * delayed allocation blocks. This number gets | ||
4501 | * adjusted later. We return if we haven't | ||
4502 | * allocated blocks already inside this loop. | ||
4503 | */ | ||
4504 | error = xfs_trans_reserve_quota_nblks( | ||
4505 | NULL, ip, (long)alen, 0, | ||
4506 | rt ? XFS_QMOPT_RES_RTBLKS : | ||
4507 | XFS_QMOPT_RES_REGBLKS); | ||
4508 | if (error) { | ||
4509 | if (n == 0) { | ||
4510 | *nmap = 0; | ||
4511 | ASSERT(cur == NULL); | ||
4512 | return error; | ||
4513 | } | ||
4514 | break; | ||
4515 | } | ||
4516 | |||
4517 | /* | ||
4518 | * Split changing sb for alen and indlen since | ||
4519 | * they could be coming from different places. | ||
4520 | */ | ||
4521 | indlen = (xfs_extlen_t) | ||
4522 | xfs_bmap_worst_indlen(ip, alen); | ||
4523 | ASSERT(indlen > 0); | ||
4524 | |||
4525 | if (rt) { | ||
4526 | error = xfs_mod_incore_sb(mp, | ||
4527 | XFS_SBS_FREXTENTS, | ||
4528 | -((int64_t)extsz), 0); | ||
4529 | } else { | ||
4530 | error = xfs_icsb_modify_counters(mp, | ||
4531 | XFS_SBS_FDBLOCKS, | ||
4532 | -((int64_t)alen), 0); | ||
4533 | } | ||
4534 | if (!error) { | ||
4535 | error = xfs_icsb_modify_counters(mp, | ||
4536 | XFS_SBS_FDBLOCKS, | ||
4537 | -((int64_t)indlen), 0); | ||
4538 | if (error && rt) | ||
4539 | xfs_mod_incore_sb(mp, | ||
4540 | XFS_SBS_FREXTENTS, | ||
4541 | (int64_t)extsz, 0); | ||
4542 | else if (error) | ||
4543 | xfs_icsb_modify_counters(mp, | ||
4544 | XFS_SBS_FDBLOCKS, | ||
4545 | (int64_t)alen, 0); | ||
4546 | } | ||
4547 | |||
4548 | if (error) { | ||
4549 | if (XFS_IS_QUOTA_ON(mp)) | ||
4550 | /* unreserve the blocks now */ | ||
4551 | (void) | ||
4552 | xfs_trans_unreserve_quota_nblks( | ||
4553 | NULL, ip, | ||
4554 | (long)alen, 0, rt ? | ||
4555 | XFS_QMOPT_RES_RTBLKS : | ||
4556 | XFS_QMOPT_RES_REGBLKS); | ||
4557 | break; | ||
4558 | } | ||
4559 | |||
4560 | ip->i_delayed_blks += alen; | ||
4561 | abno = nullstartblock(indlen); | ||
4562 | } else { | ||
4563 | /* | ||
4564 | * If first time, allocate and fill in | ||
4565 | * once-only bma fields. | ||
4566 | */ | ||
4567 | if (bma.ip == NULL) { | ||
4568 | bma.tp = tp; | ||
4569 | bma.ip = ip; | ||
4570 | bma.prevp = &prev; | ||
4571 | bma.gotp = &got; | ||
4572 | bma.total = total; | ||
4573 | bma.userdata = 0; | ||
4574 | } | ||
4575 | /* Indicate if this is the first user data | ||
4576 | * in the file, or just any user data. | ||
4577 | */ | ||
4578 | if (!(flags & XFS_BMAPI_METADATA)) { | ||
4579 | bma.userdata = (aoff == 0) ? | ||
4580 | XFS_ALLOC_INITIAL_USER_DATA : | ||
4581 | XFS_ALLOC_USERDATA; | ||
4582 | } | ||
4583 | /* | ||
4584 | * Fill in changeable bma fields. | ||
4585 | */ | ||
4586 | bma.eof = eof; | ||
4587 | bma.firstblock = *firstblock; | ||
4588 | bma.alen = alen; | ||
4589 | bma.off = aoff; | ||
4590 | bma.conv = !!(flags & XFS_BMAPI_CONVERT); | ||
4591 | bma.wasdel = wasdelay; | ||
4592 | bma.minlen = minlen; | ||
4593 | bma.low = flist->xbf_low; | ||
4594 | bma.minleft = minleft; | ||
4595 | /* | ||
4596 | * Only want to do the alignment at the | ||
4597 | * eof if it is userdata and allocation length | ||
4598 | * is larger than a stripe unit. | ||
4599 | */ | ||
4600 | if (mp->m_dalign && alen >= mp->m_dalign && | ||
4601 | (!(flags & XFS_BMAPI_METADATA)) && | ||
4602 | (whichfork == XFS_DATA_FORK)) { | ||
4603 | if ((error = xfs_bmap_isaeof(ip, aoff, | ||
4604 | whichfork, &bma.aeof))) | ||
4605 | goto error0; | ||
4606 | } else | ||
4607 | bma.aeof = 0; | ||
4608 | /* | ||
4609 | * Call allocator. | ||
4610 | */ | ||
4611 | if ((error = xfs_bmap_alloc(&bma))) | ||
4612 | goto error0; | ||
4613 | /* | ||
4614 | * Copy out result fields. | ||
4615 | */ | ||
4616 | abno = bma.rval; | ||
4617 | if ((flist->xbf_low = bma.low)) | ||
4618 | minleft = 0; | ||
4619 | alen = bma.alen; | ||
4620 | aoff = bma.off; | ||
4621 | ASSERT(*firstblock == NULLFSBLOCK || | ||
4622 | XFS_FSB_TO_AGNO(mp, *firstblock) == | ||
4623 | XFS_FSB_TO_AGNO(mp, bma.firstblock) || | ||
4624 | (flist->xbf_low && | ||
4625 | XFS_FSB_TO_AGNO(mp, *firstblock) < | ||
4626 | XFS_FSB_TO_AGNO(mp, bma.firstblock))); | ||
4627 | *firstblock = bma.firstblock; | ||
4628 | if (cur) | ||
4629 | cur->bc_private.b.firstblock = | ||
4630 | *firstblock; | ||
4631 | if (abno == NULLFSBLOCK) | ||
4632 | break; | ||
4633 | if ((ifp->if_flags & XFS_IFBROOT) && !cur) { | ||
4634 | cur = xfs_bmbt_init_cursor(mp, tp, | ||
4635 | ip, whichfork); | ||
4636 | cur->bc_private.b.firstblock = | ||
4637 | *firstblock; | ||
4638 | cur->bc_private.b.flist = flist; | ||
4639 | } | ||
4640 | /* | ||
4641 | * Bump the number of extents we've allocated | ||
4642 | * in this call. | ||
4643 | */ | ||
4644 | nallocs++; | ||
4645 | } | ||
4646 | if (cur) | ||
4647 | cur->bc_private.b.flags = | ||
4648 | wasdelay ? XFS_BTCUR_BPRV_WASDEL : 0; | ||
4649 | got.br_startoff = aoff; | ||
4650 | got.br_startblock = abno; | ||
4651 | got.br_blockcount = alen; | ||
4652 | got.br_state = XFS_EXT_NORM; /* assume normal */ | ||
4653 | /* | ||
4654 | * Determine state of extent, and the filesystem. | ||
4655 | * A wasdelay extent has been initialized, so | ||
4656 | * shouldn't be flagged as unwritten. | ||
4657 | */ | ||
4658 | if (wr && xfs_sb_version_hasextflgbit(&mp->m_sb)) { | ||
4659 | if (!wasdelay && (flags & XFS_BMAPI_PREALLOC)) | ||
4660 | got.br_state = XFS_EXT_UNWRITTEN; | ||
4661 | } | ||
4662 | error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &got, | ||
4663 | firstblock, flist, &tmp_logflags, | ||
4664 | whichfork); | ||
4665 | logflags |= tmp_logflags; | ||
4666 | if (error) | 4925 | if (error) |
4667 | goto error0; | 4926 | goto error0; |
4668 | ep = xfs_iext_get_ext(ifp, lastx); | 4927 | if (bma.blkno == NULLFSBLOCK) |
4669 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | 4928 | break; |
4670 | xfs_bmbt_get_all(ep, &got); | ||
4671 | ASSERT(got.br_startoff <= aoff); | ||
4672 | ASSERT(got.br_startoff + got.br_blockcount >= | ||
4673 | aoff + alen); | ||
4674 | #ifdef DEBUG | ||
4675 | if (flags & XFS_BMAPI_DELAY) { | ||
4676 | ASSERT(isnullstartblock(got.br_startblock)); | ||
4677 | ASSERT(startblockval(got.br_startblock) > 0); | ||
4678 | } | ||
4679 | ASSERT(got.br_state == XFS_EXT_NORM || | ||
4680 | got.br_state == XFS_EXT_UNWRITTEN); | ||
4681 | #endif | ||
4682 | /* | ||
4683 | * Fall down into the found allocated space case. | ||
4684 | */ | ||
4685 | } else if (inhole) { | ||
4686 | /* | ||
4687 | * Reading in a hole. | ||
4688 | */ | ||
4689 | mval->br_startoff = bno; | ||
4690 | mval->br_startblock = HOLESTARTBLOCK; | ||
4691 | mval->br_blockcount = | ||
4692 | XFS_FILBLKS_MIN(len, got.br_startoff - bno); | ||
4693 | mval->br_state = XFS_EXT_NORM; | ||
4694 | bno += mval->br_blockcount; | ||
4695 | len -= mval->br_blockcount; | ||
4696 | mval++; | ||
4697 | n++; | ||
4698 | continue; | ||
4699 | } | ||
4700 | /* | ||
4701 | * Then deal with the allocated space we found. | ||
4702 | */ | ||
4703 | ASSERT(ep != NULL); | ||
4704 | if (!(flags & XFS_BMAPI_ENTIRE) && | ||
4705 | (got.br_startoff + got.br_blockcount > obno)) { | ||
4706 | if (obno > bno) | ||
4707 | bno = obno; | ||
4708 | ASSERT((bno >= obno) || (n == 0)); | ||
4709 | ASSERT(bno < end); | ||
4710 | mval->br_startoff = bno; | ||
4711 | if (isnullstartblock(got.br_startblock)) { | ||
4712 | ASSERT(!wr || (flags & XFS_BMAPI_DELAY)); | ||
4713 | mval->br_startblock = DELAYSTARTBLOCK; | ||
4714 | } else | ||
4715 | mval->br_startblock = | ||
4716 | got.br_startblock + | ||
4717 | (bno - got.br_startoff); | ||
4718 | /* | ||
4719 | * Return the minimum of what we got and what we | ||
4720 | * asked for for the length. We can use the len | ||
4721 | * variable here because it is modified below | ||
4722 | * and we could have been there before coming | ||
4723 | * here if the first part of the allocation | ||
4724 | * didn't overlap what was asked for. | ||
4725 | */ | ||
4726 | mval->br_blockcount = | ||
4727 | XFS_FILBLKS_MIN(end - bno, got.br_blockcount - | ||
4728 | (bno - got.br_startoff)); | ||
4729 | mval->br_state = got.br_state; | ||
4730 | ASSERT(mval->br_blockcount <= len); | ||
4731 | } else { | ||
4732 | *mval = got; | ||
4733 | if (isnullstartblock(mval->br_startblock)) { | ||
4734 | ASSERT(!wr || (flags & XFS_BMAPI_DELAY)); | ||
4735 | mval->br_startblock = DELAYSTARTBLOCK; | ||
4736 | } | ||
4737 | } | 4929 | } |
4738 | 4930 | ||
4739 | /* | 4931 | /* Deal with the allocated space we found. */ |
4740 | * Check if writing previously allocated but | 4932 | xfs_bmapi_trim_map(mval, &bma.got, &bno, len, obno, |
4741 | * unwritten extents. | 4933 | end, n, flags); |
4742 | */ | 4934 | |
4743 | if (wr && | 4935 | /* Execute unwritten extent conversion if necessary */ |
4744 | ((mval->br_state == XFS_EXT_UNWRITTEN && | 4936 | error = xfs_bmapi_convert_unwritten(&bma, mval, len, flags); |
4745 | ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_DELAY)) == 0)) || | 4937 | if (error == EAGAIN) |
4746 | (mval->br_state == XFS_EXT_NORM && | 4938 | continue; |
4747 | ((flags & (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT)) == | 4939 | if (error) |
4748 | (XFS_BMAPI_PREALLOC|XFS_BMAPI_CONVERT))))) { | 4940 | goto error0; |
4749 | /* | 4941 | |
4750 | * Modify (by adding) the state flag, if writing. | 4942 | /* update the extent map to return */ |
4751 | */ | 4943 | xfs_bmapi_update_map(&mval, &bno, &len, obno, end, &n, flags); |
4752 | ASSERT(mval->br_blockcount <= len); | ||
4753 | if ((ifp->if_flags & XFS_IFBROOT) && !cur) { | ||
4754 | cur = xfs_bmbt_init_cursor(mp, | ||
4755 | tp, ip, whichfork); | ||
4756 | cur->bc_private.b.firstblock = | ||
4757 | *firstblock; | ||
4758 | cur->bc_private.b.flist = flist; | ||
4759 | } | ||
4760 | mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) | ||
4761 | ? XFS_EXT_NORM | ||
4762 | : XFS_EXT_UNWRITTEN; | ||
4763 | error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, mval, | ||
4764 | firstblock, flist, &tmp_logflags, | ||
4765 | whichfork); | ||
4766 | logflags |= tmp_logflags; | ||
4767 | if (error) | ||
4768 | goto error0; | ||
4769 | ep = xfs_iext_get_ext(ifp, lastx); | ||
4770 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
4771 | xfs_bmbt_get_all(ep, &got); | ||
4772 | /* | ||
4773 | * We may have combined previously unwritten | ||
4774 | * space with written space, so generate | ||
4775 | * another request. | ||
4776 | */ | ||
4777 | if (mval->br_blockcount < len) | ||
4778 | continue; | ||
4779 | } | ||
4780 | 4944 | ||
4781 | ASSERT((flags & XFS_BMAPI_ENTIRE) || | ||
4782 | ((mval->br_startoff + mval->br_blockcount) <= end)); | ||
4783 | ASSERT((flags & XFS_BMAPI_ENTIRE) || | ||
4784 | (mval->br_blockcount <= len) || | ||
4785 | (mval->br_startoff < obno)); | ||
4786 | bno = mval->br_startoff + mval->br_blockcount; | ||
4787 | len = end - bno; | ||
4788 | if (n > 0 && mval->br_startoff == mval[-1].br_startoff) { | ||
4789 | ASSERT(mval->br_startblock == mval[-1].br_startblock); | ||
4790 | ASSERT(mval->br_blockcount > mval[-1].br_blockcount); | ||
4791 | ASSERT(mval->br_state == mval[-1].br_state); | ||
4792 | mval[-1].br_blockcount = mval->br_blockcount; | ||
4793 | mval[-1].br_state = mval->br_state; | ||
4794 | } else if (n > 0 && mval->br_startblock != DELAYSTARTBLOCK && | ||
4795 | mval[-1].br_startblock != DELAYSTARTBLOCK && | ||
4796 | mval[-1].br_startblock != HOLESTARTBLOCK && | ||
4797 | mval->br_startblock == | ||
4798 | mval[-1].br_startblock + mval[-1].br_blockcount && | ||
4799 | ((flags & XFS_BMAPI_IGSTATE) || | ||
4800 | mval[-1].br_state == mval->br_state)) { | ||
4801 | ASSERT(mval->br_startoff == | ||
4802 | mval[-1].br_startoff + mval[-1].br_blockcount); | ||
4803 | mval[-1].br_blockcount += mval->br_blockcount; | ||
4804 | } else if (n > 0 && | ||
4805 | mval->br_startblock == DELAYSTARTBLOCK && | ||
4806 | mval[-1].br_startblock == DELAYSTARTBLOCK && | ||
4807 | mval->br_startoff == | ||
4808 | mval[-1].br_startoff + mval[-1].br_blockcount) { | ||
4809 | mval[-1].br_blockcount += mval->br_blockcount; | ||
4810 | mval[-1].br_state = mval->br_state; | ||
4811 | } else if (!((n == 0) && | ||
4812 | ((mval->br_startoff + mval->br_blockcount) <= | ||
4813 | obno))) { | ||
4814 | mval++; | ||
4815 | n++; | ||
4816 | } | ||
4817 | /* | 4945 | /* |
4818 | * If we're done, stop now. Stop when we've allocated | 4946 | * If we're done, stop now. Stop when we've allocated |
4819 | * XFS_BMAP_MAX_NMAP extents no matter what. Otherwise | 4947 | * XFS_BMAP_MAX_NMAP extents no matter what. Otherwise |
4820 | * the transaction may get too big. | 4948 | * the transaction may get too big. |
4821 | */ | 4949 | */ |
4822 | if (bno >= end || n >= *nmap || nallocs >= *nmap) | 4950 | if (bno >= end || n >= *nmap || bma.nallocs >= *nmap) |
4823 | break; | 4951 | break; |
4824 | /* | 4952 | |
4825 | * Else go on to the next record. | 4953 | /* Else go on to the next record. */ |
4826 | */ | 4954 | bma.prev = bma.got; |
4827 | prev = got; | 4955 | if (++bma.idx < ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) { |
4828 | if (++lastx < nextents) { | 4956 | xfs_bmbt_get_all(xfs_iext_get_ext(ifp, bma.idx), |
4829 | ep = xfs_iext_get_ext(ifp, lastx); | 4957 | &bma.got); |
4830 | xfs_bmbt_get_all(ep, &got); | 4958 | } else |
4831 | } else { | ||
4832 | eof = 1; | 4959 | eof = 1; |
4833 | } | ||
4834 | } | 4960 | } |
4835 | *nmap = n; | 4961 | *nmap = n; |
4962 | |||
4836 | /* | 4963 | /* |
4837 | * Transform from btree to extents, give it cur. | 4964 | * Transform from btree to extents, give it cur. |
4838 | */ | 4965 | */ |
4839 | if (tp && XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && | 4966 | if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && |
4840 | XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) { | 4967 | XFS_IFORK_NEXTENTS(ip, whichfork) <= ifp->if_ext_max) { |
4841 | ASSERT(wr && cur); | 4968 | int tmp_logflags = 0; |
4842 | error = xfs_bmap_btree_to_extents(tp, ip, cur, | 4969 | |
4970 | ASSERT(bma.cur); | ||
4971 | error = xfs_bmap_btree_to_extents(tp, ip, bma.cur, | ||
4843 | &tmp_logflags, whichfork); | 4972 | &tmp_logflags, whichfork); |
4844 | logflags |= tmp_logflags; | 4973 | bma.logflags |= tmp_logflags; |
4845 | if (error) | 4974 | if (error) |
4846 | goto error0; | 4975 | goto error0; |
4847 | } | 4976 | } |
@@ -4855,34 +4984,33 @@ error0: | |||
4855 | * Log everything. Do this after conversion, there's no point in | 4984 | * Log everything. Do this after conversion, there's no point in |
4856 | * logging the extent records if we've converted to btree format. | 4985 | * logging the extent records if we've converted to btree format. |
4857 | */ | 4986 | */ |
4858 | if ((logflags & xfs_ilog_fext(whichfork)) && | 4987 | if ((bma.logflags & xfs_ilog_fext(whichfork)) && |
4859 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) | 4988 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS) |
4860 | logflags &= ~xfs_ilog_fext(whichfork); | 4989 | bma.logflags &= ~xfs_ilog_fext(whichfork); |
4861 | else if ((logflags & xfs_ilog_fbroot(whichfork)) && | 4990 | else if ((bma.logflags & xfs_ilog_fbroot(whichfork)) && |
4862 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) | 4991 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE) |
4863 | logflags &= ~xfs_ilog_fbroot(whichfork); | 4992 | bma.logflags &= ~xfs_ilog_fbroot(whichfork); |
4864 | /* | 4993 | /* |
4865 | * Log whatever the flags say, even if error. Otherwise we might miss | 4994 | * Log whatever the flags say, even if error. Otherwise we might miss |
4866 | * detecting a case where the data is changed, there's an error, | 4995 | * detecting a case where the data is changed, there's an error, |
4867 | * and it's not logged so we don't shutdown when we should. | 4996 | * and it's not logged so we don't shutdown when we should. |
4868 | */ | 4997 | */ |
4869 | if (logflags) { | 4998 | if (bma.logflags) |
4870 | ASSERT(tp && wr); | 4999 | xfs_trans_log_inode(tp, ip, bma.logflags); |
4871 | xfs_trans_log_inode(tp, ip, logflags); | 5000 | |
4872 | } | 5001 | if (bma.cur) { |
4873 | if (cur) { | ||
4874 | if (!error) { | 5002 | if (!error) { |
4875 | ASSERT(*firstblock == NULLFSBLOCK || | 5003 | ASSERT(*firstblock == NULLFSBLOCK || |
4876 | XFS_FSB_TO_AGNO(mp, *firstblock) == | 5004 | XFS_FSB_TO_AGNO(mp, *firstblock) == |
4877 | XFS_FSB_TO_AGNO(mp, | 5005 | XFS_FSB_TO_AGNO(mp, |
4878 | cur->bc_private.b.firstblock) || | 5006 | bma.cur->bc_private.b.firstblock) || |
4879 | (flist->xbf_low && | 5007 | (flist->xbf_low && |
4880 | XFS_FSB_TO_AGNO(mp, *firstblock) < | 5008 | XFS_FSB_TO_AGNO(mp, *firstblock) < |
4881 | XFS_FSB_TO_AGNO(mp, | 5009 | XFS_FSB_TO_AGNO(mp, |
4882 | cur->bc_private.b.firstblock))); | 5010 | bma.cur->bc_private.b.firstblock))); |
4883 | *firstblock = cur->bc_private.b.firstblock; | 5011 | *firstblock = bma.cur->bc_private.b.firstblock; |
4884 | } | 5012 | } |
4885 | xfs_btree_del_cursor(cur, | 5013 | xfs_btree_del_cursor(bma.cur, |
4886 | error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); | 5014 | error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); |
4887 | } | 5015 | } |
4888 | if (!error) | 5016 | if (!error) |
@@ -4892,58 +5020,6 @@ error0: | |||
4892 | } | 5020 | } |
4893 | 5021 | ||
4894 | /* | 5022 | /* |
4895 | * Map file blocks to filesystem blocks, simple version. | ||
4896 | * One block (extent) only, read-only. | ||
4897 | * For flags, only the XFS_BMAPI_ATTRFORK flag is examined. | ||
4898 | * For the other flag values, the effect is as if XFS_BMAPI_METADATA | ||
4899 | * was set and all the others were clear. | ||
4900 | */ | ||
4901 | int /* error */ | ||
4902 | xfs_bmapi_single( | ||
4903 | xfs_trans_t *tp, /* transaction pointer */ | ||
4904 | xfs_inode_t *ip, /* incore inode */ | ||
4905 | int whichfork, /* data or attr fork */ | ||
4906 | xfs_fsblock_t *fsb, /* output: mapped block */ | ||
4907 | xfs_fileoff_t bno) /* starting file offs. mapped */ | ||
4908 | { | ||
4909 | int eof; /* we've hit the end of extents */ | ||
4910 | int error; /* error return */ | ||
4911 | xfs_bmbt_irec_t got; /* current file extent record */ | ||
4912 | xfs_ifork_t *ifp; /* inode fork pointer */ | ||
4913 | xfs_extnum_t lastx; /* last useful extent number */ | ||
4914 | xfs_bmbt_irec_t prev; /* previous file extent record */ | ||
4915 | |||
4916 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
4917 | if (unlikely( | ||
4918 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE && | ||
4919 | XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS)) { | ||
4920 | XFS_ERROR_REPORT("xfs_bmapi_single", XFS_ERRLEVEL_LOW, | ||
4921 | ip->i_mount); | ||
4922 | return XFS_ERROR(EFSCORRUPTED); | ||
4923 | } | ||
4924 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
4925 | return XFS_ERROR(EIO); | ||
4926 | XFS_STATS_INC(xs_blk_mapr); | ||
4927 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | ||
4928 | (error = xfs_iread_extents(tp, ip, whichfork))) | ||
4929 | return error; | ||
4930 | (void)xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, | ||
4931 | &prev); | ||
4932 | /* | ||
4933 | * Reading past eof, act as though there's a hole | ||
4934 | * up to end. | ||
4935 | */ | ||
4936 | if (eof || got.br_startoff > bno) { | ||
4937 | *fsb = NULLFSBLOCK; | ||
4938 | return 0; | ||
4939 | } | ||
4940 | ASSERT(!isnullstartblock(got.br_startblock)); | ||
4941 | ASSERT(bno < got.br_startoff + got.br_blockcount); | ||
4942 | *fsb = got.br_startblock + (bno - got.br_startoff); | ||
4943 | return 0; | ||
4944 | } | ||
4945 | |||
4946 | /* | ||
4947 | * Unmap (remove) blocks from a file. | 5023 | * Unmap (remove) blocks from a file. |
4948 | * If nexts is nonzero then the number of extents to remove is limited to | 5024 | * If nexts is nonzero then the number of extents to remove is limited to |
4949 | * that value. If not all extents in the block range can be removed then | 5025 | * that value. If not all extents in the block range can be removed then |
@@ -5114,9 +5190,9 @@ xfs_bunmapi( | |||
5114 | del.br_blockcount = mod; | 5190 | del.br_blockcount = mod; |
5115 | } | 5191 | } |
5116 | del.br_state = XFS_EXT_UNWRITTEN; | 5192 | del.br_state = XFS_EXT_UNWRITTEN; |
5117 | error = xfs_bmap_add_extent(tp, ip, &lastx, &cur, &del, | 5193 | error = xfs_bmap_add_extent_unwritten_real(tp, ip, |
5118 | firstblock, flist, &logflags, | 5194 | &lastx, &cur, &del, firstblock, flist, |
5119 | XFS_DATA_FORK); | 5195 | &logflags); |
5120 | if (error) | 5196 | if (error) |
5121 | goto error0; | 5197 | goto error0; |
5122 | goto nodelete; | 5198 | goto nodelete; |
@@ -5172,18 +5248,18 @@ xfs_bunmapi( | |||
5172 | } | 5248 | } |
5173 | prev.br_state = XFS_EXT_UNWRITTEN; | 5249 | prev.br_state = XFS_EXT_UNWRITTEN; |
5174 | lastx--; | 5250 | lastx--; |
5175 | error = xfs_bmap_add_extent(tp, ip, &lastx, | 5251 | error = xfs_bmap_add_extent_unwritten_real(tp, |
5176 | &cur, &prev, firstblock, flist, | 5252 | ip, &lastx, &cur, &prev, |
5177 | &logflags, XFS_DATA_FORK); | 5253 | firstblock, flist, &logflags); |
5178 | if (error) | 5254 | if (error) |
5179 | goto error0; | 5255 | goto error0; |
5180 | goto nodelete; | 5256 | goto nodelete; |
5181 | } else { | 5257 | } else { |
5182 | ASSERT(del.br_state == XFS_EXT_NORM); | 5258 | ASSERT(del.br_state == XFS_EXT_NORM); |
5183 | del.br_state = XFS_EXT_UNWRITTEN; | 5259 | del.br_state = XFS_EXT_UNWRITTEN; |
5184 | error = xfs_bmap_add_extent(tp, ip, &lastx, | 5260 | error = xfs_bmap_add_extent_unwritten_real(tp, |
5185 | &cur, &del, firstblock, flist, | 5261 | ip, &lastx, &cur, &del, |
5186 | &logflags, XFS_DATA_FORK); | 5262 | firstblock, flist, &logflags); |
5187 | if (error) | 5263 | if (error) |
5188 | goto error0; | 5264 | goto error0; |
5189 | goto nodelete; | 5265 | goto nodelete; |
@@ -5505,10 +5581,9 @@ xfs_getbmap( | |||
5505 | 5581 | ||
5506 | do { | 5582 | do { |
5507 | nmap = (nexleft > subnex) ? subnex : nexleft; | 5583 | nmap = (nexleft > subnex) ? subnex : nexleft; |
5508 | error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), | 5584 | error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), |
5509 | XFS_BB_TO_FSB(mp, bmv->bmv_length), | 5585 | XFS_BB_TO_FSB(mp, bmv->bmv_length), |
5510 | bmapi_flags, NULL, 0, map, &nmap, | 5586 | map, &nmap, bmapi_flags); |
5511 | NULL); | ||
5512 | if (error) | 5587 | if (error) |
5513 | goto out_free_map; | 5588 | goto out_free_map; |
5514 | ASSERT(nmap <= subnex); | 5589 | ASSERT(nmap <= subnex); |
@@ -5582,89 +5657,6 @@ xfs_getbmap( | |||
5582 | return error; | 5657 | return error; |
5583 | } | 5658 | } |
5584 | 5659 | ||
5585 | /* | ||
5586 | * Check the last inode extent to determine whether this allocation will result | ||
5587 | * in blocks being allocated at the end of the file. When we allocate new data | ||
5588 | * blocks at the end of the file which do not start at the previous data block, | ||
5589 | * we will try to align the new blocks at stripe unit boundaries. | ||
5590 | */ | ||
5591 | STATIC int /* error */ | ||
5592 | xfs_bmap_isaeof( | ||
5593 | xfs_inode_t *ip, /* incore inode pointer */ | ||
5594 | xfs_fileoff_t off, /* file offset in fsblocks */ | ||
5595 | int whichfork, /* data or attribute fork */ | ||
5596 | char *aeof) /* return value */ | ||
5597 | { | ||
5598 | int error; /* error return value */ | ||
5599 | xfs_ifork_t *ifp; /* inode fork pointer */ | ||
5600 | xfs_bmbt_rec_host_t *lastrec; /* extent record pointer */ | ||
5601 | xfs_extnum_t nextents; /* number of file extents */ | ||
5602 | xfs_bmbt_irec_t s; /* expanded extent record */ | ||
5603 | |||
5604 | ASSERT(whichfork == XFS_DATA_FORK); | ||
5605 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
5606 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | ||
5607 | (error = xfs_iread_extents(NULL, ip, whichfork))) | ||
5608 | return error; | ||
5609 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
5610 | if (nextents == 0) { | ||
5611 | *aeof = 1; | ||
5612 | return 0; | ||
5613 | } | ||
5614 | /* | ||
5615 | * Go to the last extent | ||
5616 | */ | ||
5617 | lastrec = xfs_iext_get_ext(ifp, nextents - 1); | ||
5618 | xfs_bmbt_get_all(lastrec, &s); | ||
5619 | /* | ||
5620 | * Check we are allocating in the last extent (for delayed allocations) | ||
5621 | * or past the last extent for non-delayed allocations. | ||
5622 | */ | ||
5623 | *aeof = (off >= s.br_startoff && | ||
5624 | off < s.br_startoff + s.br_blockcount && | ||
5625 | isnullstartblock(s.br_startblock)) || | ||
5626 | off >= s.br_startoff + s.br_blockcount; | ||
5627 | return 0; | ||
5628 | } | ||
5629 | |||
5630 | /* | ||
5631 | * Check if the endoff is outside the last extent. If so the caller will grow | ||
5632 | * the allocation to a stripe unit boundary. | ||
5633 | */ | ||
5634 | int /* error */ | ||
5635 | xfs_bmap_eof( | ||
5636 | xfs_inode_t *ip, /* incore inode pointer */ | ||
5637 | xfs_fileoff_t endoff, /* file offset in fsblocks */ | ||
5638 | int whichfork, /* data or attribute fork */ | ||
5639 | int *eof) /* result value */ | ||
5640 | { | ||
5641 | xfs_fsblock_t blockcount; /* extent block count */ | ||
5642 | int error; /* error return value */ | ||
5643 | xfs_ifork_t *ifp; /* inode fork pointer */ | ||
5644 | xfs_bmbt_rec_host_t *lastrec; /* extent record pointer */ | ||
5645 | xfs_extnum_t nextents; /* number of file extents */ | ||
5646 | xfs_fileoff_t startoff; /* extent starting file offset */ | ||
5647 | |||
5648 | ASSERT(whichfork == XFS_DATA_FORK); | ||
5649 | ifp = XFS_IFORK_PTR(ip, whichfork); | ||
5650 | if (!(ifp->if_flags & XFS_IFEXTENTS) && | ||
5651 | (error = xfs_iread_extents(NULL, ip, whichfork))) | ||
5652 | return error; | ||
5653 | nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); | ||
5654 | if (nextents == 0) { | ||
5655 | *eof = 1; | ||
5656 | return 0; | ||
5657 | } | ||
5658 | /* | ||
5659 | * Go to the last extent | ||
5660 | */ | ||
5661 | lastrec = xfs_iext_get_ext(ifp, nextents - 1); | ||
5662 | startoff = xfs_bmbt_get_startoff(lastrec); | ||
5663 | blockcount = xfs_bmbt_get_blockcount(lastrec); | ||
5664 | *eof = endoff >= startoff + blockcount; | ||
5665 | return 0; | ||
5666 | } | ||
5667 | |||
5668 | #ifdef DEBUG | 5660 | #ifdef DEBUG |
5669 | STATIC struct xfs_buf * | 5661 | STATIC struct xfs_buf * |
5670 | xfs_bmap_get_bp( | 5662 | xfs_bmap_get_bp( |
@@ -6099,9 +6091,8 @@ xfs_bmap_punch_delalloc_range( | |||
6099 | * trying to remove a real extent (which requires a | 6091 | * trying to remove a real extent (which requires a |
6100 | * transaction) or a hole, which is probably a bad idea... | 6092 | * transaction) or a hole, which is probably a bad idea... |
6101 | */ | 6093 | */ |
6102 | error = xfs_bmapi(NULL, ip, start_fsb, 1, | 6094 | error = xfs_bmapi_read(ip, start_fsb, 1, &imap, &nimaps, |
6103 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | 6095 | XFS_BMAPI_ENTIRE); |
6104 | &nimaps, NULL); | ||
6105 | 6096 | ||
6106 | if (error) { | 6097 | if (error) { |
6107 | /* something screwed, just bail */ | 6098 | /* something screwed, just bail */ |