aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c72
1 files changed, 54 insertions, 18 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 7cce96a6935e..bc950562b5ba 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -508,11 +508,12 @@ static int ext4_blks_to_allocate(Indirect *branch, int k, unsigned long blks,
508 * direct blocks 508 * direct blocks
509 */ 509 */
510static int ext4_alloc_blocks(handle_t *handle, struct inode *inode, 510static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
511 ext4_fsblk_t goal, int indirect_blks, int blks, 511 ext4_lblk_t iblock, ext4_fsblk_t goal,
512 ext4_fsblk_t new_blocks[4], int *err) 512 int indirect_blks, int blks,
513 ext4_fsblk_t new_blocks[4], int *err)
513{ 514{
514 int target, i; 515 int target, i;
515 unsigned long count = 0; 516 unsigned long count = 0, blk_allocated = 0;
516 int index = 0; 517 int index = 0;
517 ext4_fsblk_t current_block = 0; 518 ext4_fsblk_t current_block = 0;
518 int ret = 0; 519 int ret = 0;
@@ -525,12 +526,13 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
525 * the first direct block of this branch. That's the 526 * the first direct block of this branch. That's the
526 * minimum number of blocks need to allocate(required) 527 * minimum number of blocks need to allocate(required)
527 */ 528 */
528 target = blks + indirect_blks; 529 /* first we try to allocate the indirect blocks */
529 530 target = indirect_blks;
530 while (1) { 531 while (target > 0) {
531 count = target; 532 count = target;
532 /* allocating blocks for indirect blocks and direct blocks */ 533 /* allocating blocks for indirect blocks and direct blocks */
533 current_block = ext4_new_blocks(handle,inode,goal,&count,err); 534 current_block = ext4_new_meta_blocks(handle, inode,
535 goal, &count, err);
534 if (*err) 536 if (*err)
535 goto failed_out; 537 goto failed_out;
536 538
@@ -540,16 +542,48 @@ static int ext4_alloc_blocks(handle_t *handle, struct inode *inode,
540 new_blocks[index++] = current_block++; 542 new_blocks[index++] = current_block++;
541 count--; 543 count--;
542 } 544 }
543 545 if (count > 0) {
544 if (count > 0) 546 /*
547 * save the new block number
548 * for the first direct block
549 */
550 new_blocks[index] = current_block;
551 printk(KERN_INFO "%s returned more blocks than "
552 "requested\n", __func__);
553 WARN_ON(1);
545 break; 554 break;
555 }
546 } 556 }
547 557
548 /* save the new block number for the first direct block */ 558 target = blks - count ;
549 new_blocks[index] = current_block; 559 blk_allocated = count;
550 560 if (!target)
561 goto allocated;
562 /* Now allocate data blocks */
563 count = target;
564 /* allocating blocks for indirect blocks and direct blocks */
565 current_block = ext4_new_blocks(handle, inode, iblock,
566 goal, &count, err);
567 if (*err && (target == blks)) {
568 /*
569 * if the allocation failed and we didn't allocate
570 * any blocks before
571 */
572 goto failed_out;
573 }
574 if (!*err) {
575 if (target == blks) {
576 /*
577 * save the new block number
578 * for the first direct block
579 */
580 new_blocks[index] = current_block;
581 }
582 blk_allocated += count;
583 }
584allocated:
551 /* total number of blocks allocated for direct blocks */ 585 /* total number of blocks allocated for direct blocks */
552 ret = count; 586 ret = blk_allocated;
553 *err = 0; 587 *err = 0;
554 return ret; 588 return ret;
555failed_out: 589failed_out:
@@ -584,8 +618,9 @@ failed_out:
584 * as described above and return 0. 618 * as described above and return 0.
585 */ 619 */
586static int ext4_alloc_branch(handle_t *handle, struct inode *inode, 620static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
587 int indirect_blks, int *blks, ext4_fsblk_t goal, 621 ext4_lblk_t iblock, int indirect_blks,
588 ext4_lblk_t *offsets, Indirect *branch) 622 int *blks, ext4_fsblk_t goal,
623 ext4_lblk_t *offsets, Indirect *branch)
589{ 624{
590 int blocksize = inode->i_sb->s_blocksize; 625 int blocksize = inode->i_sb->s_blocksize;
591 int i, n = 0; 626 int i, n = 0;
@@ -595,7 +630,7 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
595 ext4_fsblk_t new_blocks[4]; 630 ext4_fsblk_t new_blocks[4];
596 ext4_fsblk_t current_block; 631 ext4_fsblk_t current_block;
597 632
598 num = ext4_alloc_blocks(handle, inode, goal, indirect_blks, 633 num = ext4_alloc_blocks(handle, inode, iblock, goal, indirect_blks,
599 *blks, new_blocks, &err); 634 *blks, new_blocks, &err);
600 if (err) 635 if (err)
601 return err; 636 return err;
@@ -855,8 +890,9 @@ int ext4_get_blocks_handle(handle_t *handle, struct inode *inode,
855 /* 890 /*
856 * Block out ext4_truncate while we alter the tree 891 * Block out ext4_truncate while we alter the tree
857 */ 892 */
858 err = ext4_alloc_branch(handle, inode, indirect_blks, &count, goal, 893 err = ext4_alloc_branch(handle, inode, iblock, indirect_blks,
859 offsets + (partial - chain), partial); 894 &count, goal,
895 offsets + (partial - chain), partial);
860 896
861 /* 897 /*
862 * The ext4_splice_branch call will free and forget any buffers 898 * The ext4_splice_branch call will free and forget any buffers