diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 7dd9b50d5ebc..8fab233cb05f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -382,7 +382,7 @@ no_block: | |||
382 | * @inode: owner | 382 | * @inode: owner |
383 | * @ind: descriptor of indirect block. | 383 | * @ind: descriptor of indirect block. |
384 | * | 384 | * |
385 | * This function returns the prefered place for block allocation. | 385 | * This function returns the preferred place for block allocation. |
386 | * It is used when heuristic for sequential allocation fails. | 386 | * It is used when heuristic for sequential allocation fails. |
387 | * Rules are: | 387 | * Rules are: |
388 | * + if there is a block to the left of our position - allocate near it. | 388 | * + if there is a block to the left of our position - allocate near it. |
@@ -403,6 +403,7 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind) | |||
403 | __le32 *start = ind->bh ? (__le32*) ind->bh->b_data : ei->i_data; | 403 | __le32 *start = ind->bh ? (__le32*) ind->bh->b_data : ei->i_data; |
404 | __le32 *p; | 404 | __le32 *p; |
405 | ext4_fsblk_t bg_start; | 405 | ext4_fsblk_t bg_start; |
406 | ext4_fsblk_t last_block; | ||
406 | ext4_grpblk_t colour; | 407 | ext4_grpblk_t colour; |
407 | 408 | ||
408 | /* Try to find previous block */ | 409 | /* Try to find previous block */ |
@@ -420,18 +421,23 @@ static ext4_fsblk_t ext4_find_near(struct inode *inode, Indirect *ind) | |||
420 | * into the same cylinder group then. | 421 | * into the same cylinder group then. |
421 | */ | 422 | */ |
422 | bg_start = ext4_group_first_block_no(inode->i_sb, ei->i_block_group); | 423 | bg_start = ext4_group_first_block_no(inode->i_sb, ei->i_block_group); |
423 | colour = (current->pid % 16) * | 424 | last_block = ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es) - 1; |
425 | |||
426 | if (bg_start + EXT4_BLOCKS_PER_GROUP(inode->i_sb) <= last_block) | ||
427 | colour = (current->pid % 16) * | ||
424 | (EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16); | 428 | (EXT4_BLOCKS_PER_GROUP(inode->i_sb) / 16); |
429 | else | ||
430 | colour = (current->pid % 16) * ((last_block - bg_start) / 16); | ||
425 | return bg_start + colour; | 431 | return bg_start + colour; |
426 | } | 432 | } |
427 | 433 | ||
428 | /** | 434 | /** |
429 | * ext4_find_goal - find a prefered place for allocation. | 435 | * ext4_find_goal - find a preferred place for allocation. |
430 | * @inode: owner | 436 | * @inode: owner |
431 | * @block: block we want | 437 | * @block: block we want |
432 | * @partial: pointer to the last triple within a chain | 438 | * @partial: pointer to the last triple within a chain |
433 | * | 439 | * |
434 | * Normally this function find the prefered place for block allocation, | 440 | * Normally this function find the preferred place for block allocation, |
435 | * returns it. | 441 | * returns it. |
436 | */ | 442 | */ |
437 | static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block, | 443 | static ext4_fsblk_t ext4_find_goal(struct inode *inode, ext4_lblk_t block, |
@@ -768,7 +774,6 @@ err_out: | |||
768 | * | 774 | * |
769 | * `handle' can be NULL if create == 0. | 775 | * `handle' can be NULL if create == 0. |
770 | * | 776 | * |
771 | * The BKL may not be held on entry here. Be sure to take it early. | ||
772 | * return > 0, # of blocks mapped or allocated. | 777 | * return > 0, # of blocks mapped or allocated. |
773 | * return = 0, if plain lookup failed. | 778 | * return = 0, if plain lookup failed. |
774 | * return < 0, error case. | 779 | * return < 0, error case. |
@@ -903,11 +908,38 @@ out: | |||
903 | */ | 908 | */ |
904 | #define DIO_CREDITS 25 | 909 | #define DIO_CREDITS 25 |
905 | 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 | */ | ||
906 | 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, |
907 | unsigned long max_blocks, struct buffer_head *bh, | 936 | unsigned long max_blocks, struct buffer_head *bh, |
908 | int create, int extend_disksize) | 937 | int create, int extend_disksize) |
909 | { | 938 | { |
910 | int retval; | 939 | int retval; |
940 | |||
941 | clear_buffer_mapped(bh); | ||
942 | |||
911 | /* | 943 | /* |
912 | * Try to see if we can get the block without requesting | 944 | * Try to see if we can get the block without requesting |
913 | * for new file system block. | 945 | * for new file system block. |
@@ -921,12 +953,26 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | |||
921 | inode, block, max_blocks, bh, 0, 0); | 953 | inode, block, max_blocks, bh, 0, 0); |
922 | } | 954 | } |
923 | up_read((&EXT4_I(inode)->i_data_sem)); | 955 | up_read((&EXT4_I(inode)->i_data_sem)); |
924 | 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)) | ||
925 | return retval; | 969 | return retval; |
926 | 970 | ||
927 | /* | 971 | /* |
928 | * We need to allocate new blocks which will result | 972 | * New blocks allocate and/or writing to uninitialized extent |
929 | * 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. | ||
930 | */ | 976 | */ |
931 | down_write((&EXT4_I(inode)->i_data_sem)); | 977 | down_write((&EXT4_I(inode)->i_data_sem)); |
932 | /* | 978 | /* |