diff options
author | Allison Henderson <achender@linux.vnet.ibm.com> | 2011-05-25 07:41:26 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-05-25 07:41:26 -0400 |
commit | 55f020db66ce187fb8c8e4002a94b0eb714da450 (patch) | |
tree | e98214511542f57fa93074be12e27c4819520333 /fs/ext4/extents.c | |
parent | ae81230686282af745ebb7a74c0332349cb9131a (diff) |
ext4: add flag to ext4_has_free_blocks
This patch adds an allocation request flag to the ext4_has_free_blocks
function which enables the use of reserved blocks. This will allow a
punch hole to proceed even if the disk is full. Punching a hole may
require additional blocks to first split the extents.
Because ext4_has_free_blocks is a low level function, the flag needs
to be passed down through several functions listed below:
ext4_ext_insert_extent
ext4_ext_create_new_leaf
ext4_ext_grow_indepth
ext4_ext_split
ext4_ext_new_meta_block
ext4_mb_new_blocks
ext4_claim_free_blocks
ext4_has_free_blocks
[ext4 punch hole patch series 1/5 v7]
Signed-off-by: Allison Henderson <achender@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Reviewed-by: Mingming Cao <cmm@us.ibm.com>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ca62d748cc65..aa3a2601bada 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -192,12 +192,13 @@ static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode, | |||
192 | static ext4_fsblk_t | 192 | static ext4_fsblk_t |
193 | ext4_ext_new_meta_block(handle_t *handle, struct inode *inode, | 193 | ext4_ext_new_meta_block(handle_t *handle, struct inode *inode, |
194 | struct ext4_ext_path *path, | 194 | struct ext4_ext_path *path, |
195 | struct ext4_extent *ex, int *err) | 195 | struct ext4_extent *ex, int *err, unsigned int flags) |
196 | { | 196 | { |
197 | ext4_fsblk_t goal, newblock; | 197 | ext4_fsblk_t goal, newblock; |
198 | 198 | ||
199 | goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block)); | 199 | goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block)); |
200 | newblock = ext4_new_meta_blocks(handle, inode, goal, NULL, err); | 200 | newblock = ext4_new_meta_blocks(handle, inode, goal, flags, |
201 | NULL, err); | ||
201 | return newblock; | 202 | return newblock; |
202 | } | 203 | } |
203 | 204 | ||
@@ -792,8 +793,9 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, | |||
792 | * - initializes subtree | 793 | * - initializes subtree |
793 | */ | 794 | */ |
794 | static int ext4_ext_split(handle_t *handle, struct inode *inode, | 795 | static int ext4_ext_split(handle_t *handle, struct inode *inode, |
795 | struct ext4_ext_path *path, | 796 | unsigned int flags, |
796 | struct ext4_extent *newext, int at) | 797 | struct ext4_ext_path *path, |
798 | struct ext4_extent *newext, int at) | ||
797 | { | 799 | { |
798 | struct buffer_head *bh = NULL; | 800 | struct buffer_head *bh = NULL; |
799 | int depth = ext_depth(inode); | 801 | int depth = ext_depth(inode); |
@@ -847,7 +849,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
847 | ext_debug("allocate %d blocks for indexes/leaf\n", depth - at); | 849 | ext_debug("allocate %d blocks for indexes/leaf\n", depth - at); |
848 | for (a = 0; a < depth - at; a++) { | 850 | for (a = 0; a < depth - at; a++) { |
849 | newblock = ext4_ext_new_meta_block(handle, inode, path, | 851 | newblock = ext4_ext_new_meta_block(handle, inode, path, |
850 | newext, &err); | 852 | newext, &err, flags); |
851 | if (newblock == 0) | 853 | if (newblock == 0) |
852 | goto cleanup; | 854 | goto cleanup; |
853 | ablocks[a] = newblock; | 855 | ablocks[a] = newblock; |
@@ -1056,8 +1058,9 @@ cleanup: | |||
1056 | * just created block | 1058 | * just created block |
1057 | */ | 1059 | */ |
1058 | static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | 1060 | static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, |
1059 | struct ext4_ext_path *path, | 1061 | unsigned int flags, |
1060 | struct ext4_extent *newext) | 1062 | struct ext4_ext_path *path, |
1063 | struct ext4_extent *newext) | ||
1061 | { | 1064 | { |
1062 | struct ext4_ext_path *curp = path; | 1065 | struct ext4_ext_path *curp = path; |
1063 | struct ext4_extent_header *neh; | 1066 | struct ext4_extent_header *neh; |
@@ -1065,7 +1068,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
1065 | ext4_fsblk_t newblock; | 1068 | ext4_fsblk_t newblock; |
1066 | int err = 0; | 1069 | int err = 0; |
1067 | 1070 | ||
1068 | newblock = ext4_ext_new_meta_block(handle, inode, path, newext, &err); | 1071 | newblock = ext4_ext_new_meta_block(handle, inode, path, |
1072 | newext, &err, flags); | ||
1069 | if (newblock == 0) | 1073 | if (newblock == 0) |
1070 | return err; | 1074 | return err; |
1071 | 1075 | ||
@@ -1140,8 +1144,9 @@ out: | |||
1140 | * if no free index is found, then it requests in-depth growing. | 1144 | * if no free index is found, then it requests in-depth growing. |
1141 | */ | 1145 | */ |
1142 | static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode, | 1146 | static int ext4_ext_create_new_leaf(handle_t *handle, struct inode *inode, |
1143 | struct ext4_ext_path *path, | 1147 | unsigned int flags, |
1144 | struct ext4_extent *newext) | 1148 | struct ext4_ext_path *path, |
1149 | struct ext4_extent *newext) | ||
1145 | { | 1150 | { |
1146 | struct ext4_ext_path *curp; | 1151 | struct ext4_ext_path *curp; |
1147 | int depth, i, err = 0; | 1152 | int depth, i, err = 0; |
@@ -1161,7 +1166,7 @@ repeat: | |||
1161 | if (EXT_HAS_FREE_INDEX(curp)) { | 1166 | if (EXT_HAS_FREE_INDEX(curp)) { |
1162 | /* if we found index with free entry, then use that | 1167 | /* if we found index with free entry, then use that |
1163 | * entry: create all needed subtree and add new leaf */ | 1168 | * entry: create all needed subtree and add new leaf */ |
1164 | err = ext4_ext_split(handle, inode, path, newext, i); | 1169 | err = ext4_ext_split(handle, inode, flags, path, newext, i); |
1165 | if (err) | 1170 | if (err) |
1166 | goto out; | 1171 | goto out; |
1167 | 1172 | ||
@@ -1174,7 +1179,8 @@ repeat: | |||
1174 | err = PTR_ERR(path); | 1179 | err = PTR_ERR(path); |
1175 | } else { | 1180 | } else { |
1176 | /* tree is full, time to grow in depth */ | 1181 | /* tree is full, time to grow in depth */ |
1177 | err = ext4_ext_grow_indepth(handle, inode, path, newext); | 1182 | err = ext4_ext_grow_indepth(handle, inode, flags, |
1183 | path, newext); | ||
1178 | if (err) | 1184 | if (err) |
1179 | goto out; | 1185 | goto out; |
1180 | 1186 | ||
@@ -1693,6 +1699,7 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, | |||
1693 | int depth, len, err; | 1699 | int depth, len, err; |
1694 | ext4_lblk_t next; | 1700 | ext4_lblk_t next; |
1695 | unsigned uninitialized = 0; | 1701 | unsigned uninitialized = 0; |
1702 | int flags = 0; | ||
1696 | 1703 | ||
1697 | if (unlikely(ext4_ext_get_actual_len(newext) == 0)) { | 1704 | if (unlikely(ext4_ext_get_actual_len(newext) == 0)) { |
1698 | EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0"); | 1705 | EXT4_ERROR_INODE(inode, "ext4_ext_get_actual_len(newext) == 0"); |
@@ -1767,7 +1774,9 @@ repeat: | |||
1767 | * There is no free space in the found leaf. | 1774 | * There is no free space in the found leaf. |
1768 | * We're gonna add a new leaf in the tree. | 1775 | * We're gonna add a new leaf in the tree. |
1769 | */ | 1776 | */ |
1770 | err = ext4_ext_create_new_leaf(handle, inode, path, newext); | 1777 | if (flag & EXT4_GET_BLOCKS_PUNCH_OUT_EXT) |
1778 | flags = EXT4_MB_USE_ROOT_BLOCKS; | ||
1779 | err = ext4_ext_create_new_leaf(handle, inode, flags, path, newext); | ||
1771 | if (err) | 1780 | if (err) |
1772 | goto cleanup; | 1781 | goto cleanup; |
1773 | depth = ext_depth(inode); | 1782 | depth = ext_depth(inode); |