aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2011-07-13 07:43:49 -0400
committerChristoph Hellwig <hch@lst.de>2011-07-13 07:43:49 -0400
commit77936d0280616d84d1eb0eb38a6f857d2827a434 (patch)
tree3076e827144b7312d84e9ed52c5d2f92b1a10fb6 /fs
parenta230a1df40864ef68ff6fbd09302f16d2a216ea5 (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.c126
-rw-r--r--fs/xfs/xfs_da_btree.h2
-rw-r--r--fs/xfs/xfs_dir2.c125
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 */
1550int 1546int
1551xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) 1547xfs_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 = &map; 1581 mapp = &map;
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; 1628out_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 */
1638int
1639xfs_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 */
250int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno); 250int xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno);
251int xfs_da_grow_inode_int(struct xfs_da_args *args, xfs_fileoff_t *bno,
252 int count);
251int xfs_da_get_buf(struct xfs_trans *trans, struct xfs_inode *dp, 253int 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 */
503int 504int
504xfs_dir2_grow_inode( 505xfs_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 = &map;
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;