diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/xfs/xfs_alloc.c | 129 |
1 files changed, 68 insertions, 61 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index b5af10713dca..4bc3c649aee4 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
| @@ -463,6 +463,27 @@ xfs_alloc_read_agfl( | |||
| 463 | return 0; | 463 | return 0; |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | STATIC int | ||
| 467 | xfs_alloc_update_counters( | ||
| 468 | struct xfs_trans *tp, | ||
| 469 | struct xfs_perag *pag, | ||
| 470 | struct xfs_buf *agbp, | ||
| 471 | long len) | ||
| 472 | { | ||
| 473 | struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); | ||
| 474 | |||
| 475 | pag->pagf_freeblks += len; | ||
| 476 | be32_add_cpu(&agf->agf_freeblks, len); | ||
| 477 | |||
| 478 | xfs_trans_agblocks_delta(tp, len); | ||
| 479 | if (unlikely(be32_to_cpu(agf->agf_freeblks) > | ||
| 480 | be32_to_cpu(agf->agf_length))) | ||
| 481 | return EFSCORRUPTED; | ||
| 482 | |||
| 483 | xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); | ||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | |||
| 466 | /* | 487 | /* |
| 467 | * Allocation group level functions. | 488 | * Allocation group level functions. |
| 468 | */ | 489 | */ |
| @@ -504,49 +525,44 @@ xfs_alloc_ag_vextent( | |||
| 504 | ASSERT(0); | 525 | ASSERT(0); |
| 505 | /* NOTREACHED */ | 526 | /* NOTREACHED */ |
| 506 | } | 527 | } |
| 507 | if (error) | 528 | |
| 529 | if (error || args->agbno == NULLAGBLOCK) | ||
| 508 | return error; | 530 | return error; |
| 509 | /* | ||
| 510 | * If the allocation worked, need to change the agf structure | ||
| 511 | * (and log it), and the superblock. | ||
| 512 | */ | ||
| 513 | if (args->agbno != NULLAGBLOCK) { | ||
| 514 | xfs_agf_t *agf; /* allocation group freelist header */ | ||
| 515 | long slen = (long)args->len; | ||
| 516 | 531 | ||
| 517 | ASSERT(args->len >= args->minlen && args->len <= args->maxlen); | 532 | ASSERT(args->len >= args->minlen); |
| 518 | ASSERT(!(args->wasfromfl) || !args->isfl); | 533 | ASSERT(args->len <= args->maxlen); |
| 519 | ASSERT(args->agbno % args->alignment == 0); | 534 | ASSERT(!args->wasfromfl || !args->isfl); |
| 520 | if (!(args->wasfromfl)) { | 535 | ASSERT(args->agbno % args->alignment == 0); |
| 521 | 536 | ||
| 522 | agf = XFS_BUF_TO_AGF(args->agbp); | 537 | if (!args->wasfromfl) { |
| 523 | be32_add_cpu(&agf->agf_freeblks, -(args->len)); | 538 | error = xfs_alloc_update_counters(args->tp, args->pag, |
| 524 | xfs_trans_agblocks_delta(args->tp, | 539 | args->agbp, |
| 525 | -((long)(args->len))); | 540 | -((long)(args->len))); |
| 526 | args->pag->pagf_freeblks -= args->len; | 541 | if (error) |
| 527 | ASSERT(be32_to_cpu(agf->agf_freeblks) <= | 542 | return error; |
| 528 | be32_to_cpu(agf->agf_length)); | 543 | |
| 529 | xfs_alloc_log_agf(args->tp, args->agbp, | 544 | /* |
| 530 | XFS_AGF_FREEBLKS); | 545 | * Search the busylist for these blocks and mark the |
| 531 | /* | 546 | * transaction as synchronous if blocks are found. This |
| 532 | * Search the busylist for these blocks and mark the | 547 | * avoids the need to block due to a synchronous log |
| 533 | * transaction as synchronous if blocks are found. This | 548 | * force to ensure correct ordering as the synchronous |
| 534 | * avoids the need to block due to a synchronous log | 549 | * transaction will guarantee that for us. |
| 535 | * force to ensure correct ordering as the synchronous | 550 | */ |
| 536 | * transaction will guarantee that for us. | 551 | if (xfs_alloc_busy_search(args->mp, args->agno, |
| 537 | */ | 552 | args->agbno, args->len)) |
| 538 | if (xfs_alloc_busy_search(args->mp, args->agno, | 553 | xfs_trans_set_sync(args->tp); |
| 539 | args->agbno, args->len)) | ||
| 540 | xfs_trans_set_sync(args->tp); | ||
| 541 | } | ||
| 542 | if (!args->isfl) | ||
| 543 | xfs_trans_mod_sb(args->tp, | ||
| 544 | args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : | ||
| 545 | XFS_TRANS_SB_FDBLOCKS, -slen); | ||
| 546 | XFS_STATS_INC(xs_allocx); | ||
| 547 | XFS_STATS_ADD(xs_allocb, args->len); | ||
| 548 | } | 554 | } |
| 549 | return 0; | 555 | |
| 556 | if (!args->isfl) { | ||
| 557 | xfs_trans_mod_sb(args->tp, args->wasdel ? | ||
| 558 | XFS_TRANS_SB_RES_FDBLOCKS : | ||
| 559 | XFS_TRANS_SB_FDBLOCKS, | ||
| 560 | -((long)(args->len))); | ||
| 561 | } | ||
| 562 | |||
| 563 | XFS_STATS_INC(xs_allocx); | ||
| 564 | XFS_STATS_ADD(xs_allocb, args->len); | ||
| 565 | return error; | ||
| 550 | } | 566 | } |
| 551 | 567 | ||
| 552 | /* | 568 | /* |
| @@ -1385,6 +1401,7 @@ xfs_free_ag_extent( | |||
| 1385 | xfs_mount_t *mp; /* mount point struct for filesystem */ | 1401 | xfs_mount_t *mp; /* mount point struct for filesystem */ |
| 1386 | xfs_agblock_t nbno; /* new starting block of freespace */ | 1402 | xfs_agblock_t nbno; /* new starting block of freespace */ |
| 1387 | xfs_extlen_t nlen; /* new length of freespace */ | 1403 | xfs_extlen_t nlen; /* new length of freespace */ |
| 1404 | xfs_perag_t *pag; /* per allocation group data */ | ||
| 1388 | 1405 | ||
| 1389 | mp = tp->t_mountp; | 1406 | mp = tp->t_mountp; |
| 1390 | /* | 1407 | /* |
| @@ -1583,30 +1600,20 @@ xfs_free_ag_extent( | |||
| 1583 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); | 1600 | XFS_WANT_CORRUPTED_GOTO(i == 1, error0); |
| 1584 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); | 1601 | xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR); |
| 1585 | cnt_cur = NULL; | 1602 | cnt_cur = NULL; |
| 1603 | |||
| 1586 | /* | 1604 | /* |
| 1587 | * Update the freespace totals in the ag and superblock. | 1605 | * Update the freespace totals in the ag and superblock. |
| 1588 | */ | 1606 | */ |
| 1589 | { | 1607 | pag = xfs_perag_get(mp, agno); |
| 1590 | xfs_agf_t *agf; | 1608 | error = xfs_alloc_update_counters(tp, pag, agbp, len); |
| 1591 | xfs_perag_t *pag; /* per allocation group data */ | 1609 | xfs_perag_put(pag); |
| 1592 | 1610 | if (error) | |
| 1593 | pag = xfs_perag_get(mp, agno); | 1611 | goto error0; |
| 1594 | pag->pagf_freeblks += len; | 1612 | |
| 1595 | xfs_perag_put(pag); | 1613 | if (!isfl) |
| 1596 | 1614 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); | |
| 1597 | agf = XFS_BUF_TO_AGF(agbp); | 1615 | XFS_STATS_INC(xs_freex); |
| 1598 | be32_add_cpu(&agf->agf_freeblks, len); | 1616 | XFS_STATS_ADD(xs_freeb, len); |
| 1599 | xfs_trans_agblocks_delta(tp, len); | ||
| 1600 | XFS_WANT_CORRUPTED_GOTO( | ||
| 1601 | be32_to_cpu(agf->agf_freeblks) <= | ||
| 1602 | be32_to_cpu(agf->agf_length), | ||
| 1603 | error0); | ||
| 1604 | xfs_alloc_log_agf(tp, agbp, XFS_AGF_FREEBLKS); | ||
| 1605 | if (!isfl) | ||
| 1606 | xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); | ||
| 1607 | XFS_STATS_INC(xs_freex); | ||
| 1608 | XFS_STATS_ADD(xs_freeb, len); | ||
| 1609 | } | ||
| 1610 | 1617 | ||
| 1611 | trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); | 1618 | trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); |
| 1612 | 1619 | ||
