diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2011-10-22 01:26:05 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-10-22 01:26:05 -0400 |
commit | 1939dd84b3f52e9c8d1b46dffae2058f16a3ff6a (patch) | |
tree | f1b30614ea4c4e991abb279c9d7d181e207c7148 /fs/ext4 | |
parent | 45dc63e7d8412546567399b94caeb683af58843e (diff) |
ext4: cleanup ext4_ext_grow_indepth code
Currently code make an impression what grow procedure is very complicated
and some mythical paths, blocks are involved. But in fact grow in depth
it relatively simple procedure:
1) Just create new meta block and copy root data to that block.
2) Convert root from extent to index if old depth == 0
3) Update root block pointer
This patch does:
- Reorganize code to make it more self explanatory
- Do not pass path parameter to new_meta_block() in order to
provoke allocation from inode's group because top-level block
should site closer to it's inode, but not to leaf data block.
[ This happens anyway, due to logic in mballoc; we should drop
the path parameter from new_meta_block() entirely. -- tytso ]
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/extents.c | 41 |
1 files changed, 15 insertions, 26 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 2fc6cc0a51ca..385ebb435332 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -1050,16 +1050,14 @@ cleanup: | |||
1050 | */ | 1050 | */ |
1051 | static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | 1051 | static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, |
1052 | unsigned int flags, | 1052 | unsigned int flags, |
1053 | struct ext4_ext_path *path, | ||
1054 | struct ext4_extent *newext) | 1053 | struct ext4_extent *newext) |
1055 | { | 1054 | { |
1056 | struct ext4_ext_path *curp = path; | ||
1057 | struct ext4_extent_header *neh; | 1055 | struct ext4_extent_header *neh; |
1058 | struct buffer_head *bh; | 1056 | struct buffer_head *bh; |
1059 | ext4_fsblk_t newblock; | 1057 | ext4_fsblk_t newblock; |
1060 | int err = 0; | 1058 | int err = 0; |
1061 | 1059 | ||
1062 | newblock = ext4_ext_new_meta_block(handle, inode, path, | 1060 | newblock = ext4_ext_new_meta_block(handle, inode, NULL, |
1063 | newext, &err, flags); | 1061 | newext, &err, flags); |
1064 | if (newblock == 0) | 1062 | if (newblock == 0) |
1065 | return err; | 1063 | return err; |
@@ -1079,7 +1077,8 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
1079 | } | 1077 | } |
1080 | 1078 | ||
1081 | /* move top-level index/leaf into new block */ | 1079 | /* move top-level index/leaf into new block */ |
1082 | memmove(bh->b_data, curp->p_hdr, sizeof(EXT4_I(inode)->i_data)); | 1080 | memmove(bh->b_data, EXT4_I(inode)->i_data, |
1081 | sizeof(EXT4_I(inode)->i_data)); | ||
1083 | 1082 | ||
1084 | /* set size of new block */ | 1083 | /* set size of new block */ |
1085 | neh = ext_block_hdr(bh); | 1084 | neh = ext_block_hdr(bh); |
@@ -1097,32 +1096,23 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
1097 | if (err) | 1096 | if (err) |
1098 | goto out; | 1097 | goto out; |
1099 | 1098 | ||
1100 | /* create index in new top-level index: num,max,pointer */ | 1099 | /* Update top-level index: num,max,pointer */ |
1101 | err = ext4_ext_get_access(handle, inode, curp); | ||
1102 | if (err) | ||
1103 | goto out; | ||
1104 | |||
1105 | curp->p_hdr->eh_magic = EXT4_EXT_MAGIC; | ||
1106 | curp->p_hdr->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0)); | ||
1107 | curp->p_hdr->eh_entries = cpu_to_le16(1); | ||
1108 | curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); | ||
1109 | |||
1110 | if (path[0].p_hdr->eh_depth) | ||
1111 | curp->p_idx->ei_block = | ||
1112 | EXT_FIRST_INDEX(path[0].p_hdr)->ei_block; | ||
1113 | else | ||
1114 | curp->p_idx->ei_block = | ||
1115 | EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block; | ||
1116 | ext4_idx_store_pblock(curp->p_idx, newblock); | ||
1117 | |||
1118 | neh = ext_inode_hdr(inode); | 1100 | neh = ext_inode_hdr(inode); |
1101 | neh->eh_entries = cpu_to_le16(1); | ||
1102 | ext4_idx_store_pblock(EXT_FIRST_INDEX(neh), newblock); | ||
1103 | if (neh->eh_depth == 0) { | ||
1104 | /* Root extent block becomes index block */ | ||
1105 | neh->eh_max = cpu_to_le16(ext4_ext_space_root_idx(inode, 0)); | ||
1106 | EXT_FIRST_INDEX(neh)->ei_block = | ||
1107 | EXT_FIRST_EXTENT(neh)->ee_block; | ||
1108 | } | ||
1119 | ext_debug("new root: num %d(%d), lblock %d, ptr %llu\n", | 1109 | ext_debug("new root: num %d(%d), lblock %d, ptr %llu\n", |
1120 | le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max), | 1110 | le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max), |
1121 | le32_to_cpu(EXT_FIRST_INDEX(neh)->ei_block), | 1111 | le32_to_cpu(EXT_FIRST_INDEX(neh)->ei_block), |
1122 | ext4_idx_pblock(EXT_FIRST_INDEX(neh))); | 1112 | ext4_idx_pblock(EXT_FIRST_INDEX(neh))); |
1123 | 1113 | ||
1124 | neh->eh_depth = cpu_to_le16(path->p_depth + 1); | 1114 | neh->eh_depth = cpu_to_le16(neh->eh_depth + 1); |
1125 | err = ext4_ext_dirty(handle, inode, curp); | 1115 | ext4_mark_inode_dirty(handle, inode); |
1126 | out: | 1116 | out: |
1127 | brelse(bh); | 1117 | brelse(bh); |
1128 | 1118 | ||
@@ -1170,8 +1160,7 @@ repeat: | |||
1170 | err = PTR_ERR(path); | 1160 | err = PTR_ERR(path); |
1171 | } else { | 1161 | } else { |
1172 | /* tree is full, time to grow in depth */ | 1162 | /* tree is full, time to grow in depth */ |
1173 | err = ext4_ext_grow_indepth(handle, inode, flags, | 1163 | err = ext4_ext_grow_indepth(handle, inode, flags, newext); |
1174 | path, newext); | ||
1175 | if (err) | 1164 | if (err) |
1176 | goto out; | 1165 | goto out; |
1177 | 1166 | ||