aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3/inode.c')
-rw-r--r--fs/ext3/inode.c105
1 files changed, 76 insertions, 29 deletions
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index 76e22c9c9c6c..fcfb10f77120 100644
--- a/fs/ext3/inode.c
+++ b/fs/ext3/inode.c
@@ -330,7 +330,7 @@ static int ext3_block_to_path(struct inode *inode,
330 ext3_warning (inode->i_sb, "ext3_block_to_path", "block > big"); 330 ext3_warning (inode->i_sb, "ext3_block_to_path", "block > big");
331 } 331 }
332 if (boundary) 332 if (boundary)
333 *boundary = (i_block & (ptrs - 1)) == (final - 1); 333 *boundary = final - 1 - (i_block & (ptrs - 1));
334 return n; 334 return n;
335} 335}
336 336
@@ -669,11 +669,15 @@ err_out:
669 * akpm: `handle' can be NULL if create == 0. 669 * akpm: `handle' can be NULL if create == 0.
670 * 670 *
671 * The BKL may not be held on entry here. Be sure to take it early. 671 * The BKL may not be held on entry here. Be sure to take it early.
672 * return > 0, # of blocks mapped or allocated.
673 * return = 0, if plain lookup failed.
674 * return < 0, error case.
672 */ 675 */
673 676
674int 677int
675ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, 678ext3_get_blocks_handle(handle_t *handle, struct inode *inode, sector_t iblock,
676 struct buffer_head *bh_result, int create, int extend_disksize) 679 unsigned long maxblocks, struct buffer_head *bh_result,
680 int create, int extend_disksize)
677{ 681{
678 int err = -EIO; 682 int err = -EIO;
679 int offsets[4]; 683 int offsets[4];
@@ -681,11 +685,15 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
681 Indirect *partial; 685 Indirect *partial;
682 unsigned long goal; 686 unsigned long goal;
683 int left; 687 int left;
684 int boundary = 0; 688 int blocks_to_boundary = 0;
685 const int depth = ext3_block_to_path(inode, iblock, offsets, &boundary); 689 int depth;
686 struct ext3_inode_info *ei = EXT3_I(inode); 690 struct ext3_inode_info *ei = EXT3_I(inode);
691 int count = 0;
692 unsigned long first_block = 0;
693
687 694
688 J_ASSERT(handle != NULL || create == 0); 695 J_ASSERT(handle != NULL || create == 0);
696 depth = ext3_block_to_path(inode, iblock, offsets, &blocks_to_boundary);
689 697
690 if (depth == 0) 698 if (depth == 0)
691 goto out; 699 goto out;
@@ -694,8 +702,31 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
694 702
695 /* Simplest case - block found, no allocation needed */ 703 /* Simplest case - block found, no allocation needed */
696 if (!partial) { 704 if (!partial) {
705 first_block = chain[depth - 1].key;
697 clear_buffer_new(bh_result); 706 clear_buffer_new(bh_result);
698 goto got_it; 707 count++;
708 /*map more blocks*/
709 while (count < maxblocks && count <= blocks_to_boundary) {
710 if (!verify_chain(chain, partial)) {
711 /*
712 * Indirect block might be removed by
713 * truncate while we were reading it.
714 * Handling of that case: forget what we've
715 * got now. Flag the err as EAGAIN, so it
716 * will reread.
717 */
718 err = -EAGAIN;
719 count = 0;
720 break;
721 }
722 if (le32_to_cpu(*(chain[depth-1].p+count) ==
723 (first_block + count)))
724 count++;
725 else
726 break;
727 }
728 if (err != -EAGAIN)
729 goto got_it;
699 } 730 }
700 731
701 /* Next simple case - plain lookup or failed read of indirect block */ 732 /* Next simple case - plain lookup or failed read of indirect block */
@@ -723,6 +754,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
723 } 754 }
724 partial = ext3_get_branch(inode, depth, offsets, chain, &err); 755 partial = ext3_get_branch(inode, depth, offsets, chain, &err);
725 if (!partial) { 756 if (!partial) {
757 count++;
726 mutex_unlock(&ei->truncate_mutex); 758 mutex_unlock(&ei->truncate_mutex);
727 if (err) 759 if (err)
728 goto cleanup; 760 goto cleanup;
@@ -772,8 +804,9 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
772 set_buffer_new(bh_result); 804 set_buffer_new(bh_result);
773got_it: 805got_it:
774 map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key)); 806 map_bh(bh_result, inode->i_sb, le32_to_cpu(chain[depth-1].key));
775 if (boundary) 807 if (blocks_to_boundary == 0)
776 set_buffer_boundary(bh_result); 808 set_buffer_boundary(bh_result);
809 err = count;
777 /* Clean up and exit */ 810 /* Clean up and exit */
778 partial = chain + depth - 1; /* the whole chain */ 811 partial = chain + depth - 1; /* the whole chain */
779cleanup: 812cleanup:
@@ -787,21 +820,6 @@ out:
787 return err; 820 return err;
788} 821}
789 822
790static int ext3_get_block(struct inode *inode, sector_t iblock,
791 struct buffer_head *bh_result, int create)
792{
793 handle_t *handle = NULL;
794 int ret;
795
796 if (create) {
797 handle = ext3_journal_current_handle();
798 J_ASSERT(handle != 0);
799 }
800 ret = ext3_get_block_handle(handle, inode, iblock,
801 bh_result, create, 1);
802 return ret;
803}
804
805#define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32) 823#define DIO_CREDITS (EXT3_RESERVE_TRANS_BLOCKS + 32)
806 824
807static int 825static int
@@ -812,9 +830,12 @@ ext3_direct_io_get_blocks(struct inode *inode, sector_t iblock,
812 handle_t *handle = journal_current_handle(); 830 handle_t *handle = journal_current_handle();
813 int ret = 0; 831 int ret = 0;
814 832
815 if (!handle) 833 if (!create)
816 goto get_block; /* A read */ 834 goto get_block; /* A read */
817 835
836 if (max_blocks == 1)
837 goto get_block; /* A single block get */
838
818 if (handle->h_transaction->t_state == T_LOCKED) { 839 if (handle->h_transaction->t_state == T_LOCKED) {
819 /* 840 /*
820 * Huge direct-io writes can hold off commits for long 841 * Huge direct-io writes can hold off commits for long
@@ -841,13 +862,31 @@ ext3_direct_io_get_blocks(struct inode *inode, sector_t iblock,
841 } 862 }
842 863
843get_block: 864get_block:
844 if (ret == 0) 865 if (ret == 0) {
845 ret = ext3_get_block_handle(handle, inode, iblock, 866 ret = ext3_get_blocks_handle(handle, inode, iblock,
846 bh_result, create, 0); 867 max_blocks, bh_result, create, 0);
847 bh_result->b_size = (1 << inode->i_blkbits); 868 if (ret > 0) {
869 bh_result->b_size = (ret << inode->i_blkbits);
870 ret = 0;
871 }
872 }
848 return ret; 873 return ret;
849} 874}
850 875
876static int ext3_get_blocks(struct inode *inode, sector_t iblock,
877 unsigned long maxblocks, struct buffer_head *bh_result,
878 int create)
879{
880 return ext3_direct_io_get_blocks(inode, iblock, maxblocks,
881 bh_result, create);
882}
883
884static int ext3_get_block(struct inode *inode, sector_t iblock,
885 struct buffer_head *bh_result, int create)
886{
887 return ext3_get_blocks(inode, iblock, 1, bh_result, create);
888}
889
851/* 890/*
852 * `handle' can be NULL if create is zero 891 * `handle' can be NULL if create is zero
853 */ 892 */
@@ -862,8 +901,16 @@ struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
862 dummy.b_state = 0; 901 dummy.b_state = 0;
863 dummy.b_blocknr = -1000; 902 dummy.b_blocknr = -1000;
864 buffer_trace_init(&dummy.b_history); 903 buffer_trace_init(&dummy.b_history);
865 *errp = ext3_get_block_handle(handle, inode, block, &dummy, create, 1); 904 err = ext3_get_blocks_handle(handle, inode, block, 1,
866 if (!*errp && buffer_mapped(&dummy)) { 905 &dummy, create, 1);
906 if (err == 1) {
907 err = 0;
908 } else if (err >= 0) {
909 WARN_ON(1);
910 err = -EIO;
911 }
912 *errp = err;
913 if (!err && buffer_mapped(&dummy)) {
867 struct buffer_head *bh; 914 struct buffer_head *bh;
868 bh = sb_getblk(inode->i_sb, dummy.b_blocknr); 915 bh = sb_getblk(inode->i_sb, dummy.b_blocknr);
869 if (!bh) { 916 if (!bh) {