diff options
author | Christoph Hellwig <hch@lst.de> | 2011-07-13 07:43:49 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2011-07-13 07:43:49 -0400 |
commit | 77936d0280616d84d1eb0eb38a6f857d2827a434 (patch) | |
tree | 3076e827144b7312d84e9ed52c5d2f92b1a10fb6 /fs | |
parent | a230a1df40864ef68ff6fbd09302f16d2a216ea5 (diff) |
xfs: factor out xfs_da_grow_inode_int
xfs_da_grow_inode and xfs_dir2_grow_inode are mostly duplicate code. Factor
the meat of those two functions into a new common helper.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Alex Elder <aelder@sgi.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_da_btree.c | 126 | ||||
-rw-r--r-- | fs/xfs/xfs_da_btree.h | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2.c | 125 |
3 files changed, 86 insertions, 167 deletions
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index a58a6410c58d..73b048f7eb71 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -1543,79 +1543,62 @@ const struct xfs_nameops xfs_default_nameops = { | |||
1543 | .compname = xfs_da_compname | 1543 | .compname = xfs_da_compname |
1544 | }; | 1544 | }; |
1545 | 1545 | ||
1546 | /* | ||
1547 | * Add a block to the btree ahead of the file. | ||
1548 | * Return the new block number to the caller. | ||
1549 | */ | ||
1550 | int | 1546 | int |
1551 | xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | 1547 | xfs_da_grow_inode_int( |
1548 | struct xfs_da_args *args, | ||
1549 | xfs_fileoff_t *bno, | ||
1550 | int count) | ||
1552 | { | 1551 | { |
1553 | xfs_fileoff_t bno, b; | 1552 | struct xfs_trans *tp = args->trans; |
1554 | xfs_bmbt_irec_t map; | 1553 | struct xfs_inode *dp = args->dp; |
1555 | xfs_bmbt_irec_t *mapp; | 1554 | int w = args->whichfork; |
1556 | xfs_inode_t *dp; | 1555 | xfs_drfsbno_t nblks = dp->i_d.di_nblocks; |
1557 | int nmap, error, w, count, c, got, i, mapi; | 1556 | struct xfs_bmbt_irec map, *mapp; |
1558 | xfs_trans_t *tp; | 1557 | int nmap, error, got, i, mapi; |
1559 | xfs_mount_t *mp; | ||
1560 | xfs_drfsbno_t nblks; | ||
1561 | 1558 | ||
1562 | dp = args->dp; | ||
1563 | mp = dp->i_mount; | ||
1564 | w = args->whichfork; | ||
1565 | tp = args->trans; | ||
1566 | nblks = dp->i_d.di_nblocks; | ||
1567 | |||
1568 | /* | ||
1569 | * For new directories adjust the file offset and block count. | ||
1570 | */ | ||
1571 | if (w == XFS_DATA_FORK) { | ||
1572 | bno = mp->m_dirleafblk; | ||
1573 | count = mp->m_dirblkfsbs; | ||
1574 | } else { | ||
1575 | bno = 0; | ||
1576 | count = 1; | ||
1577 | } | ||
1578 | /* | 1559 | /* |
1579 | * Find a spot in the file space to put the new block. | 1560 | * Find a spot in the file space to put the new block. |
1580 | */ | 1561 | */ |
1581 | if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) | 1562 | error = xfs_bmap_first_unused(tp, dp, count, bno, w); |
1563 | if (error) | ||
1582 | return error; | 1564 | return error; |
1583 | if (w == XFS_DATA_FORK) | 1565 | |
1584 | ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk); | ||
1585 | /* | 1566 | /* |
1586 | * Try mapping it in one filesystem block. | 1567 | * Try mapping it in one filesystem block. |
1587 | */ | 1568 | */ |
1588 | nmap = 1; | 1569 | nmap = 1; |
1589 | ASSERT(args->firstblock != NULL); | 1570 | ASSERT(args->firstblock != NULL); |
1590 | if ((error = xfs_bmapi(tp, dp, bno, count, | 1571 | error = xfs_bmapi(tp, dp, *bno, count, |
1591 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| | 1572 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| |
1592 | XFS_BMAPI_CONTIG, | 1573 | XFS_BMAPI_CONTIG, |
1593 | args->firstblock, args->total, &map, &nmap, | 1574 | args->firstblock, args->total, &map, &nmap, |
1594 | args->flist))) { | 1575 | args->flist); |
1576 | if (error) | ||
1595 | return error; | 1577 | return error; |
1596 | } | 1578 | |
1597 | ASSERT(nmap <= 1); | 1579 | ASSERT(nmap <= 1); |
1598 | if (nmap == 1) { | 1580 | if (nmap == 1) { |
1599 | mapp = ↦ | 1581 | mapp = ↦ |
1600 | mapi = 1; | 1582 | mapi = 1; |
1601 | } | 1583 | } else if (nmap == 0 && count > 1) { |
1602 | /* | 1584 | xfs_fileoff_t b; |
1603 | * If we didn't get it and the block might work if fragmented, | 1585 | int c; |
1604 | * try without the CONTIG flag. Loop until we get it all. | 1586 | |
1605 | */ | 1587 | /* |
1606 | else if (nmap == 0 && count > 1) { | 1588 | * If we didn't get it and the block might work if fragmented, |
1589 | * try without the CONTIG flag. Loop until we get it all. | ||
1590 | */ | ||
1607 | mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP); | 1591 | mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP); |
1608 | for (b = bno, mapi = 0; b < bno + count; ) { | 1592 | for (b = *bno, mapi = 0; b < *bno + count; ) { |
1609 | nmap = MIN(XFS_BMAP_MAX_NMAP, count); | 1593 | nmap = MIN(XFS_BMAP_MAX_NMAP, count); |
1610 | c = (int)(bno + count - b); | 1594 | c = (int)(*bno + count - b); |
1611 | if ((error = xfs_bmapi(tp, dp, b, c, | 1595 | error = xfs_bmapi(tp, dp, b, c, |
1612 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE| | 1596 | xfs_bmapi_aflag(w)|XFS_BMAPI_WRITE| |
1613 | XFS_BMAPI_METADATA, | 1597 | XFS_BMAPI_METADATA, |
1614 | args->firstblock, args->total, | 1598 | args->firstblock, args->total, |
1615 | &mapp[mapi], &nmap, args->flist))) { | 1599 | &mapp[mapi], &nmap, args->flist); |
1616 | kmem_free(mapp); | 1600 | if (error) |
1617 | return error; | 1601 | goto out_free_map; |
1618 | } | ||
1619 | if (nmap < 1) | 1602 | if (nmap < 1) |
1620 | break; | 1603 | break; |
1621 | mapi += nmap; | 1604 | mapi += nmap; |
@@ -1626,24 +1609,53 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1626 | mapi = 0; | 1609 | mapi = 0; |
1627 | mapp = NULL; | 1610 | mapp = NULL; |
1628 | } | 1611 | } |
1612 | |||
1629 | /* | 1613 | /* |
1630 | * Count the blocks we got, make sure it matches the total. | 1614 | * Count the blocks we got, make sure it matches the total. |
1631 | */ | 1615 | */ |
1632 | for (i = 0, got = 0; i < mapi; i++) | 1616 | for (i = 0, got = 0; i < mapi; i++) |
1633 | got += mapp[i].br_blockcount; | 1617 | got += mapp[i].br_blockcount; |
1634 | if (got != count || mapp[0].br_startoff != bno || | 1618 | if (got != count || mapp[0].br_startoff != *bno || |
1635 | mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != | 1619 | mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != |
1636 | bno + count) { | 1620 | *bno + count) { |
1637 | if (mapp != &map) | 1621 | error = XFS_ERROR(ENOSPC); |
1638 | kmem_free(mapp); | 1622 | goto out_free_map; |
1639 | return XFS_ERROR(ENOSPC); | ||
1640 | } | 1623 | } |
1641 | if (mapp != &map) | 1624 | |
1642 | kmem_free(mapp); | ||
1643 | /* account for newly allocated blocks in reserved blocks total */ | 1625 | /* account for newly allocated blocks in reserved blocks total */ |
1644 | args->total -= dp->i_d.di_nblocks - nblks; | 1626 | args->total -= dp->i_d.di_nblocks - nblks; |
1645 | *new_blkno = (xfs_dablk_t)bno; | 1627 | |
1646 | return 0; | 1628 | out_free_map: |
1629 | if (mapp != &map) | ||
1630 | kmem_free(mapp); | ||
1631 | return error; | ||
1632 | } | ||
1633 | |||
1634 | /* | ||
1635 | * Add a block to the btree ahead of the file. | ||
1636 | * Return the new block number to the caller. | ||
1637 | */ | ||
1638 | int | ||
1639 | xfs_da_grow_inode( | ||
1640 | struct xfs_da_args *args, | ||
1641 | xfs_dablk_t *new_blkno) | ||
1642 | { | ||
1643 | xfs_fileoff_t bno; | ||
1644 | int count; | ||
1645 | int error; | ||
1646 | |||
1647 | if (args->whichfork == XFS_DATA_FORK) { | ||
1648 | bno = args->dp->i_mount->m_dirleafblk; | ||
1649 | count = args->dp->i_mount->m_dirblkfsbs; | ||
1650 | } else { | ||
1651 | bno = 0; | ||
1652 | count = 1; | ||
1653 | } | ||
1654 | |||
1655 | error = xfs_da_grow_inode_int(args, &bno, count); | ||
1656 | if (!error) | ||
1657 | *new_blkno = (xfs_dablk_t)bno; | ||
1658 | return error; | ||
1647 | } | 1659 | } |
1648 | 1660 | ||
1649 | /* | 1661 | /* |
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index fe9f5a8c1d2a..7b0a6ea59a04 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h | |||
@@ -248,6 +248,8 @@ int xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, | |||
248 | * Utility routines. | 248 | * Utility routines. |
249 | */ | 249 | */ |
250 | int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno); | 250 | int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno); |
251 | int xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno, | ||
252 | int count); | ||
251 | int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp, | 253 | int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp, |
252 | xfs_dablk_t bno, xfs_daddr_t mappedbno, | 254 | xfs_dablk_t bno, xfs_daddr_t mappedbno, |
253 | xfs_dabuf_t **bp, int whichfork); | 255 | xfs_dabuf_t **bp, int whichfork); |
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 6effbeb24e5a..4580ce00aeb4 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -497,129 +497,34 @@ xfs_dir_canenter( | |||
497 | 497 | ||
498 | /* | 498 | /* |
499 | * Add a block to the directory. | 499 | * Add a block to the directory. |
500 | * This routine is for data and free blocks, not leaf/node blocks | 500 | * |
501 | * which are handled by xfs_da_grow_inode. | 501 | * This routine is for data and free blocks, not leaf/node blocks which are |
502 | * handled by xfs_da_grow_inode. | ||
502 | */ | 503 | */ |
503 | int | 504 | int |
504 | xfs_dir2_grow_inode( | 505 | xfs_dir2_grow_inode( |
505 | xfs_da_args_t *args, | 506 | struct xfs_da_args *args, |
506 | int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ | 507 | int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ |
507 | xfs_dir2_db_t *dbp) /* out: block number added */ | 508 | xfs_dir2_db_t *dbp) /* out: block number added */ |
508 | { | 509 | { |
509 | xfs_fileoff_t bno; /* directory offset of new block */ | 510 | struct xfs_inode *dp = args->dp; |
510 | int count; /* count of filesystem blocks */ | 511 | struct xfs_mount *mp = dp->i_mount; |
511 | xfs_inode_t *dp; /* incore directory inode */ | 512 | xfs_fileoff_t bno; /* directory offset of new block */ |
512 | int error; | 513 | int count; /* count of filesystem blocks */ |
513 | int got; /* blocks actually mapped */ | 514 | int error; |
514 | int i; | ||
515 | xfs_bmbt_irec_t map; /* single structure for bmap */ | ||
516 | int mapi; /* mapping index */ | ||
517 | xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */ | ||
518 | xfs_mount_t *mp; | ||
519 | int nmap; /* number of bmap entries */ | ||
520 | xfs_trans_t *tp; | ||
521 | xfs_drfsbno_t nblks; | ||
522 | 515 | ||
523 | trace_xfs_dir2_grow_inode(args, space); | 516 | trace_xfs_dir2_grow_inode(args, space); |
524 | 517 | ||
525 | dp = args->dp; | ||
526 | tp = args->trans; | ||
527 | mp = dp->i_mount; | ||
528 | nblks = dp->i_d.di_nblocks; | ||
529 | /* | 518 | /* |
530 | * Set lowest possible block in the space requested. | 519 | * Set lowest possible block in the space requested. |
531 | */ | 520 | */ |
532 | bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); | 521 | bno = XFS_B_TO_FSBT(mp, space * XFS_DIR2_SPACE_SIZE); |
533 | count = mp->m_dirblkfsbs; | 522 | count = mp->m_dirblkfsbs; |
534 | /* | ||
535 | * Find the first hole for our block. | ||
536 | */ | ||
537 | if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) | ||
538 | return error; | ||
539 | nmap = 1; | ||
540 | ASSERT(args->firstblock != NULL); | ||
541 | /* | ||
542 | * Try mapping the new block contiguously (one extent). | ||
543 | */ | ||
544 | if ((error = xfs_bmapi(tp, dp, bno, count, | ||
545 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, | ||
546 | args->firstblock, args->total, &map, &nmap, | ||
547 | args->flist))) | ||
548 | return error; | ||
549 | ASSERT(nmap <= 1); | ||
550 | if (nmap == 1) { | ||
551 | mapp = ↦ | ||
552 | mapi = 1; | ||
553 | } | ||
554 | /* | ||
555 | * Didn't work and this is a multiple-fsb directory block. | ||
556 | * Try again with contiguous flag turned on. | ||
557 | */ | ||
558 | else if (nmap == 0 && count > 1) { | ||
559 | xfs_fileoff_t b; /* current file offset */ | ||
560 | 523 | ||
561 | /* | 524 | error = xfs_da_grow_inode_int(args, &bno, count); |
562 | * Space for maximum number of mappings. | 525 | if (error) |
563 | */ | 526 | return error; |
564 | mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP); | ||
565 | /* | ||
566 | * Iterate until we get to the end of our block. | ||
567 | */ | ||
568 | for (b = bno, mapi = 0; b < bno + count; ) { | ||
569 | int c; /* current fsb count */ | ||
570 | |||
571 | /* | ||
572 | * Can't map more than MAX_NMAP at once. | ||
573 | */ | ||
574 | nmap = MIN(XFS_BMAP_MAX_NMAP, count); | ||
575 | c = (int)(bno + count - b); | ||
576 | if ((error = xfs_bmapi(tp, dp, b, c, | ||
577 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, | ||
578 | args->firstblock, args->total, | ||
579 | &mapp[mapi], &nmap, args->flist))) { | ||
580 | kmem_free(mapp); | ||
581 | return error; | ||
582 | } | ||
583 | if (nmap < 1) | ||
584 | break; | ||
585 | /* | ||
586 | * Add this bunch into our table, go to the next offset. | ||
587 | */ | ||
588 | mapi += nmap; | ||
589 | b = mapp[mapi - 1].br_startoff + | ||
590 | mapp[mapi - 1].br_blockcount; | ||
591 | } | ||
592 | } | ||
593 | /* | ||
594 | * Didn't work. | ||
595 | */ | ||
596 | else { | ||
597 | mapi = 0; | ||
598 | mapp = NULL; | ||
599 | } | ||
600 | /* | ||
601 | * See how many fsb's we got. | ||
602 | */ | ||
603 | for (i = 0, got = 0; i < mapi; i++) | ||
604 | got += mapp[i].br_blockcount; | ||
605 | /* | ||
606 | * Didn't get enough fsb's, or the first/last block's are wrong. | ||
607 | */ | ||
608 | if (got != count || mapp[0].br_startoff != bno || | ||
609 | mapp[mapi - 1].br_startoff + mapp[mapi - 1].br_blockcount != | ||
610 | bno + count) { | ||
611 | if (mapp != &map) | ||
612 | kmem_free(mapp); | ||
613 | return XFS_ERROR(ENOSPC); | ||
614 | } | ||
615 | /* | ||
616 | * Done with the temporary mapping table. | ||
617 | */ | ||
618 | if (mapp != &map) | ||
619 | kmem_free(mapp); | ||
620 | 527 | ||
621 | /* account for newly allocated blocks in reserved blocks total */ | ||
622 | args->total -= dp->i_d.di_nblocks - nblks; | ||
623 | *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); | 528 | *dbp = xfs_dir2_da_to_db(mp, (xfs_dablk_t)bno); |
624 | 529 | ||
625 | /* | 530 | /* |
@@ -631,7 +536,7 @@ xfs_dir2_grow_inode( | |||
631 | size = XFS_FSB_TO_B(mp, bno + count); | 536 | size = XFS_FSB_TO_B(mp, bno + count); |
632 | if (size > dp->i_d.di_size) { | 537 | if (size > dp->i_d.di_size) { |
633 | dp->i_d.di_size = size; | 538 | dp->i_d.di_size = size; |
634 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); | 539 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); |
635 | } | 540 | } |
636 | } | 541 | } |
637 | return 0; | 542 | return 0; |