diff options
author | Yongqiang Yang <xiaoqiangnk@gmail.com> | 2011-05-25 17:41:48 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-05-25 17:41:48 -0400 |
commit | 1b16da77f90328661fc7e556ad591f9ee6b7ef6a (patch) | |
tree | b86caf7fd1c4e0f205a69d8bb7ca1ebb883cab63 /fs/ext4/extents.c | |
parent | ae24f28d39610a4810c78185cf599a771cf6ee1f (diff) |
ext4: teach ext4_ext_split to calculate extents efficiently
Make ext4_ext_split() get extents to be moved by calculating in a statement
instead of counting in a loop.
Signed-off-by: Yongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 84 |
1 files changed, 46 insertions, 38 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index ae65f247ceda..5199bac7fc62 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -482,9 +482,43 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path) | |||
482 | } | 482 | } |
483 | ext_debug("\n"); | 483 | ext_debug("\n"); |
484 | } | 484 | } |
485 | |||
486 | static void ext4_ext_show_move(struct inode *inode, struct ext4_ext_path *path, | ||
487 | ext4_fsblk_t newblock, int level) | ||
488 | { | ||
489 | int depth = ext_depth(inode); | ||
490 | struct ext4_extent *ex; | ||
491 | |||
492 | if (depth != level) { | ||
493 | struct ext4_extent_idx *idx; | ||
494 | idx = path[level].p_idx; | ||
495 | while (idx <= EXT_MAX_INDEX(path[level].p_hdr)) { | ||
496 | ext_debug("%d: move %d:%llu in new index %llu\n", level, | ||
497 | le32_to_cpu(idx->ei_block), | ||
498 | ext4_idx_pblock(idx), | ||
499 | newblock); | ||
500 | idx++; | ||
501 | } | ||
502 | |||
503 | return; | ||
504 | } | ||
505 | |||
506 | ex = path[depth].p_ext; | ||
507 | while (ex <= EXT_MAX_EXTENT(path[depth].p_hdr)) { | ||
508 | ext_debug("move %d:%llu:[%d]%d in new leaf %llu\n", | ||
509 | le32_to_cpu(ex->ee_block), | ||
510 | ext4_ext_pblock(ex), | ||
511 | ext4_ext_is_uninitialized(ex), | ||
512 | ext4_ext_get_actual_len(ex), | ||
513 | newblock); | ||
514 | ex++; | ||
515 | } | ||
516 | } | ||
517 | |||
485 | #else | 518 | #else |
486 | #define ext4_ext_show_path(inode, path) | 519 | #define ext4_ext_show_path(inode, path) |
487 | #define ext4_ext_show_leaf(inode, path) | 520 | #define ext4_ext_show_leaf(inode, path) |
521 | #define ext4_ext_show_move(inode, path, newblock, level) | ||
488 | #endif | 522 | #endif |
489 | 523 | ||
490 | void ext4_ext_drop_refs(struct ext4_ext_path *path) | 524 | void ext4_ext_drop_refs(struct ext4_ext_path *path) |
@@ -808,7 +842,6 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
808 | int depth = ext_depth(inode); | 842 | int depth = ext_depth(inode); |
809 | struct ext4_extent_header *neh; | 843 | struct ext4_extent_header *neh; |
810 | struct ext4_extent_idx *fidx; | 844 | struct ext4_extent_idx *fidx; |
811 | struct ext4_extent *ex; | ||
812 | int i = at, k, m, a; | 845 | int i = at, k, m, a; |
813 | ext4_fsblk_t newblock, oldblock; | 846 | ext4_fsblk_t newblock, oldblock; |
814 | __le32 border; | 847 | __le32 border; |
@@ -885,7 +918,6 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
885 | neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); | 918 | neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); |
886 | neh->eh_magic = EXT4_EXT_MAGIC; | 919 | neh->eh_magic = EXT4_EXT_MAGIC; |
887 | neh->eh_depth = 0; | 920 | neh->eh_depth = 0; |
888 | ex = EXT_FIRST_EXTENT(neh); | ||
889 | 921 | ||
890 | /* move remainder of path[depth] to the new leaf */ | 922 | /* move remainder of path[depth] to the new leaf */ |
891 | if (unlikely(path[depth].p_hdr->eh_entries != | 923 | if (unlikely(path[depth].p_hdr->eh_entries != |
@@ -897,25 +929,12 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
897 | goto cleanup; | 929 | goto cleanup; |
898 | } | 930 | } |
899 | /* start copy from next extent */ | 931 | /* start copy from next extent */ |
900 | /* TODO: we could do it by single memmove */ | 932 | m = EXT_MAX_EXTENT(path[depth].p_hdr) - path[depth].p_ext++; |
901 | m = 0; | 933 | ext4_ext_show_move(inode, path, newblock, depth); |
902 | path[depth].p_ext++; | ||
903 | while (path[depth].p_ext <= | ||
904 | EXT_MAX_EXTENT(path[depth].p_hdr)) { | ||
905 | ext_debug("move %d:%llu:[%d]%d in new leaf %llu\n", | ||
906 | le32_to_cpu(path[depth].p_ext->ee_block), | ||
907 | ext4_ext_pblock(path[depth].p_ext), | ||
908 | ext4_ext_is_uninitialized(path[depth].p_ext), | ||
909 | ext4_ext_get_actual_len(path[depth].p_ext), | ||
910 | newblock); | ||
911 | /*memmove(ex++, path[depth].p_ext++, | ||
912 | sizeof(struct ext4_extent)); | ||
913 | neh->eh_entries++;*/ | ||
914 | path[depth].p_ext++; | ||
915 | m++; | ||
916 | } | ||
917 | if (m) { | 934 | if (m) { |
918 | memmove(ex, path[depth].p_ext-m, sizeof(struct ext4_extent)*m); | 935 | struct ext4_extent *ex; |
936 | ex = EXT_FIRST_EXTENT(neh); | ||
937 | memmove(ex, path[depth].p_ext, sizeof(struct ext4_extent) * m); | ||
919 | le16_add_cpu(&neh->eh_entries, m); | 938 | le16_add_cpu(&neh->eh_entries, m); |
920 | } | 939 | } |
921 | 940 | ||
@@ -977,12 +996,8 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
977 | 996 | ||
978 | ext_debug("int.index at %d (block %llu): %u -> %llu\n", | 997 | ext_debug("int.index at %d (block %llu): %u -> %llu\n", |
979 | i, newblock, le32_to_cpu(border), oldblock); | 998 | i, newblock, le32_to_cpu(border), oldblock); |
980 | /* copy indexes */ | ||
981 | m = 0; | ||
982 | path[i].p_idx++; | ||
983 | 999 | ||
984 | ext_debug("cur 0x%p, last 0x%p\n", path[i].p_idx, | 1000 | /* move remainder of path[i] to the new index block */ |
985 | EXT_MAX_INDEX(path[i].p_hdr)); | ||
986 | if (unlikely(EXT_MAX_INDEX(path[i].p_hdr) != | 1001 | if (unlikely(EXT_MAX_INDEX(path[i].p_hdr) != |
987 | EXT_LAST_INDEX(path[i].p_hdr))) { | 1002 | EXT_LAST_INDEX(path[i].p_hdr))) { |
988 | EXT4_ERROR_INODE(inode, | 1003 | EXT4_ERROR_INODE(inode, |
@@ -991,20 +1006,13 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
991 | err = -EIO; | 1006 | err = -EIO; |
992 | goto cleanup; | 1007 | goto cleanup; |
993 | } | 1008 | } |
994 | while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { | 1009 | /* start copy indexes */ |
995 | ext_debug("%d: move %d:%llu in new index %llu\n", i, | 1010 | m = EXT_MAX_INDEX(path[i].p_hdr) - path[i].p_idx++; |
996 | le32_to_cpu(path[i].p_idx->ei_block), | 1011 | ext_debug("cur 0x%p, last 0x%p\n", path[i].p_idx, |
997 | ext4_idx_pblock(path[i].p_idx), | 1012 | EXT_MAX_INDEX(path[i].p_hdr)); |
998 | newblock); | 1013 | ext4_ext_show_move(inode, path, newblock, i); |
999 | /*memmove(++fidx, path[i].p_idx++, | ||
1000 | sizeof(struct ext4_extent_idx)); | ||
1001 | neh->eh_entries++; | ||
1002 | BUG_ON(neh->eh_entries > neh->eh_max);*/ | ||
1003 | path[i].p_idx++; | ||
1004 | m++; | ||
1005 | } | ||
1006 | if (m) { | 1014 | if (m) { |
1007 | memmove(++fidx, path[i].p_idx - m, | 1015 | memmove(++fidx, path[i].p_idx, |
1008 | sizeof(struct ext4_extent_idx) * m); | 1016 | sizeof(struct ext4_extent_idx) * m); |
1009 | le16_add_cpu(&neh->eh_entries, m); | 1017 | le16_add_cpu(&neh->eh_entries, m); |
1010 | } | 1018 | } |