diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 34f3eb615fd5..945cbf6cb1fc 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -908,11 +908,38 @@ out: | |||
908 | */ | 908 | */ |
909 | #define DIO_CREDITS 25 | 909 | #define DIO_CREDITS 25 |
910 | 910 | ||
911 | |||
912 | /* | ||
913 | * | ||
914 | * | ||
915 | * ext4_ext4 get_block() wrapper function | ||
916 | * It will do a look up first, and returns if the blocks already mapped. | ||
917 | * Otherwise it takes the write lock of the i_data_sem and allocate blocks | ||
918 | * and store the allocated blocks in the result buffer head and mark it | ||
919 | * mapped. | ||
920 | * | ||
921 | * If file type is extents based, it will call ext4_ext_get_blocks(), | ||
922 | * Otherwise, call with ext4_get_blocks_handle() to handle indirect mapping | ||
923 | * based files | ||
924 | * | ||
925 | * On success, it returns the number of blocks being mapped or allocate. | ||
926 | * if create==0 and the blocks are pre-allocated and uninitialized block, | ||
927 | * the result buffer head is unmapped. If the create ==1, it will make sure | ||
928 | * the buffer head is mapped. | ||
929 | * | ||
930 | * It returns 0 if plain look up failed (blocks have not been allocated), in | ||
931 | * that casem, buffer head is unmapped | ||
932 | * | ||
933 | * It returns the error in case of allocation failure. | ||
934 | */ | ||
911 | int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | 935 | int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, |
912 | unsigned long max_blocks, struct buffer_head *bh, | 936 | unsigned long max_blocks, struct buffer_head *bh, |
913 | int create, int extend_disksize) | 937 | int create, int extend_disksize) |
914 | { | 938 | { |
915 | int retval; | 939 | int retval; |
940 | |||
941 | clear_buffer_mapped(bh); | ||
942 | |||
916 | /* | 943 | /* |
917 | * Try to see if we can get the block without requesting | 944 | * Try to see if we can get the block without requesting |
918 | * for new file system block. | 945 | * for new file system block. |
@@ -926,12 +953,26 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | |||
926 | inode, block, max_blocks, bh, 0, 0); | 953 | inode, block, max_blocks, bh, 0, 0); |
927 | } | 954 | } |
928 | up_read((&EXT4_I(inode)->i_data_sem)); | 955 | up_read((&EXT4_I(inode)->i_data_sem)); |
929 | if (!create || (retval > 0)) | 956 | |
957 | /* If it is only a block(s) look up */ | ||
958 | if (!create) | ||
959 | return retval; | ||
960 | |||
961 | /* | ||
962 | * Returns if the blocks have already allocated | ||
963 | * | ||
964 | * Note that if blocks have been preallocated | ||
965 | * ext4_ext_get_block() returns th create = 0 | ||
966 | * with buffer head unmapped. | ||
967 | */ | ||
968 | if (retval > 0 && buffer_mapped(bh)) | ||
930 | return retval; | 969 | return retval; |
931 | 970 | ||
932 | /* | 971 | /* |
933 | * We need to allocate new blocks which will result | 972 | * New blocks allocate and/or writing to uninitialized extent |
934 | * in i_data update | 973 | * will possibly result in updating i_data, so we take |
974 | * the write lock of i_data_sem, and call get_blocks() | ||
975 | * with create == 1 flag. | ||
935 | */ | 976 | */ |
936 | down_write((&EXT4_I(inode)->i_data_sem)); | 977 | down_write((&EXT4_I(inode)->i_data_sem)); |
937 | /* | 978 | /* |