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/xfs/xfs_dir2.c | |
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/xfs/xfs_dir2.c')
-rw-r--r-- | fs/xfs/xfs_dir2.c | 125 |
1 files changed, 15 insertions, 110 deletions
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; |