diff options
author | Alex Tomas <alex@clusterfs.com> | 2006-10-11 04:21:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-11 14:14:16 -0400 |
commit | f65e6fba163dfd0f962efb7d8f5528b6872e2b15 (patch) | |
tree | 75ee824ba0e97038754f0732c458c689c04a4182 | |
parent | 3a5b2ecdd1fa63a8f25bd769223bc1c2564ce45d (diff) |
[PATCH] ext4: 48bit physical block number support in extents
Signed-off-by: Alex Tomas <alex@clusterfs.com>
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/ext4/extents.c | 187 | ||||
-rw-r--r-- | include/linux/ext4_fs_extents.h | 2 | ||||
-rw-r--r-- | include/linux/ext4_fs_i.h | 8 |
3 files changed, 116 insertions, 81 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index f67b2ef6a71f..4a13b56e1540 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -44,6 +44,44 @@ | |||
44 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
45 | 45 | ||
46 | 46 | ||
47 | /* this macro combines low and hi parts of phys. blocknr into ext4_fsblk_t */ | ||
48 | static inline ext4_fsblk_t ext_pblock(struct ext4_extent *ex) | ||
49 | { | ||
50 | ext4_fsblk_t block; | ||
51 | |||
52 | block = le32_to_cpu(ex->ee_start); | ||
53 | if (sizeof(ext4_fsblk_t) > 4) | ||
54 | block |= ((ext4_fsblk_t) le16_to_cpu(ex->ee_start_hi) << 31) << 1; | ||
55 | return block; | ||
56 | } | ||
57 | |||
58 | /* this macro combines low and hi parts of phys. blocknr into ext4_fsblk_t */ | ||
59 | static inline ext4_fsblk_t idx_pblock(struct ext4_extent_idx *ix) | ||
60 | { | ||
61 | ext4_fsblk_t block; | ||
62 | |||
63 | block = le32_to_cpu(ix->ei_leaf); | ||
64 | if (sizeof(ext4_fsblk_t) > 4) | ||
65 | block |= ((ext4_fsblk_t) le16_to_cpu(ix->ei_leaf_hi) << 31) << 1; | ||
66 | return block; | ||
67 | } | ||
68 | |||
69 | /* the routine stores large phys. blocknr into extent breaking it into parts */ | ||
70 | static inline void ext4_ext_store_pblock(struct ext4_extent *ex, ext4_fsblk_t pb) | ||
71 | { | ||
72 | ex->ee_start = cpu_to_le32((unsigned long) (pb & 0xffffffff)); | ||
73 | if (sizeof(ext4_fsblk_t) > 4) | ||
74 | ex->ee_start_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff); | ||
75 | } | ||
76 | |||
77 | /* the routine stores large phys. blocknr into index breaking it into parts */ | ||
78 | static inline void ext4_idx_store_pblock(struct ext4_extent_idx *ix, ext4_fsblk_t pb) | ||
79 | { | ||
80 | ix->ei_leaf = cpu_to_le32((unsigned long) (pb & 0xffffffff)); | ||
81 | if (sizeof(ext4_fsblk_t) > 4) | ||
82 | ix->ei_leaf_hi = cpu_to_le16((unsigned long) ((pb >> 31) >> 1) & 0xffff); | ||
83 | } | ||
84 | |||
47 | static int ext4_ext_check_header(const char *function, struct inode *inode, | 85 | static int ext4_ext_check_header(const char *function, struct inode *inode, |
48 | struct ext4_extent_header *eh) | 86 | struct ext4_extent_header *eh) |
49 | { | 87 | { |
@@ -124,13 +162,13 @@ static int ext4_ext_dirty(handle_t *handle, struct inode *inode, | |||
124 | return err; | 162 | return err; |
125 | } | 163 | } |
126 | 164 | ||
127 | static int ext4_ext_find_goal(struct inode *inode, | 165 | static ext4_fsblk_t ext4_ext_find_goal(struct inode *inode, |
128 | struct ext4_ext_path *path, | 166 | struct ext4_ext_path *path, |
129 | unsigned long block) | 167 | ext4_fsblk_t block) |
130 | { | 168 | { |
131 | struct ext4_inode_info *ei = EXT4_I(inode); | 169 | struct ext4_inode_info *ei = EXT4_I(inode); |
132 | unsigned long bg_start; | 170 | ext4_fsblk_t bg_start; |
133 | unsigned long colour; | 171 | ext4_grpblk_t colour; |
134 | int depth; | 172 | int depth; |
135 | 173 | ||
136 | if (path) { | 174 | if (path) { |
@@ -139,8 +177,7 @@ static int ext4_ext_find_goal(struct inode *inode, | |||
139 | 177 | ||
140 | /* try to predict block placement */ | 178 | /* try to predict block placement */ |
141 | if ((ex = path[depth].p_ext)) | 179 | if ((ex = path[depth].p_ext)) |
142 | return le32_to_cpu(ex->ee_start) | 180 | return ext_pblock(ex)+(block-le32_to_cpu(ex->ee_block)); |
143 | + (block - le32_to_cpu(ex->ee_block)); | ||
144 | 181 | ||
145 | /* it looks index is empty | 182 | /* it looks index is empty |
146 | * try to find starting from index itself */ | 183 | * try to find starting from index itself */ |
@@ -156,12 +193,12 @@ static int ext4_ext_find_goal(struct inode *inode, | |||
156 | return bg_start + colour + block; | 193 | return bg_start + colour + block; |
157 | } | 194 | } |
158 | 195 | ||
159 | static int | 196 | static ext4_fsblk_t |
160 | ext4_ext_new_block(handle_t *handle, struct inode *inode, | 197 | ext4_ext_new_block(handle_t *handle, struct inode *inode, |
161 | struct ext4_ext_path *path, | 198 | struct ext4_ext_path *path, |
162 | struct ext4_extent *ex, int *err) | 199 | struct ext4_extent *ex, int *err) |
163 | { | 200 | { |
164 | int goal, newblock; | 201 | ext4_fsblk_t goal, newblock; |
165 | 202 | ||
166 | goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block)); | 203 | goal = ext4_ext_find_goal(inode, path, le32_to_cpu(ex->ee_block)); |
167 | newblock = ext4_new_block(handle, inode, goal, err); | 204 | newblock = ext4_new_block(handle, inode, goal, err); |
@@ -230,13 +267,13 @@ static void ext4_ext_show_path(struct inode *inode, struct ext4_ext_path *path) | |||
230 | ext_debug("path:"); | 267 | ext_debug("path:"); |
231 | for (k = 0; k <= l; k++, path++) { | 268 | for (k = 0; k <= l; k++, path++) { |
232 | if (path->p_idx) { | 269 | if (path->p_idx) { |
233 | ext_debug(" %d->%d", le32_to_cpu(path->p_idx->ei_block), | 270 | ext_debug(" %d->"E3FSBLK, le32_to_cpu(path->p_idx->ei_block), |
234 | le32_to_cpu(path->p_idx->ei_leaf)); | 271 | idx_pblock(path->p_idx)); |
235 | } else if (path->p_ext) { | 272 | } else if (path->p_ext) { |
236 | ext_debug(" %d:%d:%d", | 273 | ext_debug(" %d:%d:"E3FSBLK" ", |
237 | le32_to_cpu(path->p_ext->ee_block), | 274 | le32_to_cpu(path->p_ext->ee_block), |
238 | le16_to_cpu(path->p_ext->ee_len), | 275 | le16_to_cpu(path->p_ext->ee_len), |
239 | le32_to_cpu(path->p_ext->ee_start)); | 276 | ext_pblock(path->p_ext)); |
240 | } else | 277 | } else |
241 | ext_debug(" []"); | 278 | ext_debug(" []"); |
242 | } | 279 | } |
@@ -257,9 +294,8 @@ static void ext4_ext_show_leaf(struct inode *inode, struct ext4_ext_path *path) | |||
257 | ex = EXT_FIRST_EXTENT(eh); | 294 | ex = EXT_FIRST_EXTENT(eh); |
258 | 295 | ||
259 | for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ex++) { | 296 | for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ex++) { |
260 | ext_debug("%d:%d:%d ", le32_to_cpu(ex->ee_block), | 297 | ext_debug("%d:%d:"E3FSBLK" ", le32_to_cpu(ex->ee_block), |
261 | le16_to_cpu(ex->ee_len), | 298 | le16_to_cpu(ex->ee_len), ext_pblock(ex)); |
262 | le32_to_cpu(ex->ee_start)); | ||
263 | } | 299 | } |
264 | ext_debug("\n"); | 300 | ext_debug("\n"); |
265 | } | 301 | } |
@@ -308,8 +344,8 @@ ext4_ext_binsearch_idx(struct inode *inode, struct ext4_ext_path *path, int bloc | |||
308 | } | 344 | } |
309 | 345 | ||
310 | path->p_idx = l - 1; | 346 | path->p_idx = l - 1; |
311 | ext_debug(" -> %d->%d ", le32_to_cpu(path->p_idx->ei_block), | 347 | ext_debug(" -> %d->%lld ", le32_to_cpu(path->p_idx->ei_block), |
312 | le32_to_cpu(path->p_idx->ei_leaf)); | 348 | idx_block(path->p_idx)); |
313 | 349 | ||
314 | #ifdef CHECK_BINSEARCH | 350 | #ifdef CHECK_BINSEARCH |
315 | { | 351 | { |
@@ -374,10 +410,10 @@ ext4_ext_binsearch(struct inode *inode, struct ext4_ext_path *path, int block) | |||
374 | } | 410 | } |
375 | 411 | ||
376 | path->p_ext = l - 1; | 412 | path->p_ext = l - 1; |
377 | ext_debug(" -> %d:%d:%d ", | 413 | ext_debug(" -> %d:"E3FSBLK":%d ", |
378 | le32_to_cpu(path->p_ext->ee_block), | 414 | le32_to_cpu(path->p_ext->ee_block), |
379 | le32_to_cpu(path->p_ext->ee_start), | 415 | ext_pblock(path->p_ext), |
380 | le16_to_cpu(path->p_ext->ee_len)); | 416 | le16_to_cpu(path->p_ext->ee_len)); |
381 | 417 | ||
382 | #ifdef CHECK_BINSEARCH | 418 | #ifdef CHECK_BINSEARCH |
383 | { | 419 | { |
@@ -442,7 +478,7 @@ ext4_ext_find_extent(struct inode *inode, int block, struct ext4_ext_path *path) | |||
442 | ext_debug("depth %d: num %d, max %d\n", | 478 | ext_debug("depth %d: num %d, max %d\n", |
443 | ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max)); | 479 | ppos, le16_to_cpu(eh->eh_entries), le16_to_cpu(eh->eh_max)); |
444 | ext4_ext_binsearch_idx(inode, path + ppos, block); | 480 | ext4_ext_binsearch_idx(inode, path + ppos, block); |
445 | path[ppos].p_block = le32_to_cpu(path[ppos].p_idx->ei_leaf); | 481 | path[ppos].p_block = idx_pblock(path[ppos].p_idx); |
446 | path[ppos].p_depth = i; | 482 | path[ppos].p_depth = i; |
447 | path[ppos].p_ext = NULL; | 483 | path[ppos].p_ext = NULL; |
448 | 484 | ||
@@ -489,7 +525,7 @@ err: | |||
489 | */ | 525 | */ |
490 | static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, | 526 | static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, |
491 | struct ext4_ext_path *curp, | 527 | struct ext4_ext_path *curp, |
492 | int logical, int ptr) | 528 | int logical, ext4_fsblk_t ptr) |
493 | { | 529 | { |
494 | struct ext4_extent_idx *ix; | 530 | struct ext4_extent_idx *ix; |
495 | int len, err; | 531 | int len, err; |
@@ -524,7 +560,7 @@ static int ext4_ext_insert_index(handle_t *handle, struct inode *inode, | |||
524 | } | 560 | } |
525 | 561 | ||
526 | ix->ei_block = cpu_to_le32(logical); | 562 | ix->ei_block = cpu_to_le32(logical); |
527 | ix->ei_leaf = cpu_to_le32(ptr); | 563 | ext4_idx_store_pblock(ix, ptr); |
528 | curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1); | 564 | curp->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(curp->p_hdr->eh_entries)+1); |
529 | 565 | ||
530 | BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries) | 566 | BUG_ON(le16_to_cpu(curp->p_hdr->eh_entries) |
@@ -556,9 +592,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
556 | struct ext4_extent_idx *fidx; | 592 | struct ext4_extent_idx *fidx; |
557 | struct ext4_extent *ex; | 593 | struct ext4_extent *ex; |
558 | int i = at, k, m, a; | 594 | int i = at, k, m, a; |
559 | unsigned long newblock, oldblock; | 595 | ext4_fsblk_t newblock, oldblock; |
560 | __le32 border; | 596 | __le32 border; |
561 | int *ablocks = NULL; /* array of allocated blocks */ | 597 | ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */ |
562 | int err = 0; | 598 | int err = 0; |
563 | 599 | ||
564 | /* make decision: where to split? */ | 600 | /* make decision: where to split? */ |
@@ -591,10 +627,10 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
591 | * we need this to handle errors and free blocks | 627 | * we need this to handle errors and free blocks |
592 | * upon them | 628 | * upon them |
593 | */ | 629 | */ |
594 | ablocks = kmalloc(sizeof(unsigned long) * depth, GFP_NOFS); | 630 | ablocks = kmalloc(sizeof(ext4_fsblk_t) * depth, GFP_NOFS); |
595 | if (!ablocks) | 631 | if (!ablocks) |
596 | return -ENOMEM; | 632 | return -ENOMEM; |
597 | memset(ablocks, 0, sizeof(unsigned long) * depth); | 633 | memset(ablocks, 0, sizeof(ext4_fsblk_t) * depth); |
598 | 634 | ||
599 | /* allocate all needed blocks */ | 635 | /* allocate all needed blocks */ |
600 | ext_debug("allocate %d blocks for indexes/leaf\n", depth - at); | 636 | ext_debug("allocate %d blocks for indexes/leaf\n", depth - at); |
@@ -633,9 +669,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
633 | path[depth].p_ext++; | 669 | path[depth].p_ext++; |
634 | while (path[depth].p_ext <= | 670 | while (path[depth].p_ext <= |
635 | EXT_MAX_EXTENT(path[depth].p_hdr)) { | 671 | EXT_MAX_EXTENT(path[depth].p_hdr)) { |
636 | ext_debug("move %d:%d:%d in new leaf %lu\n", | 672 | ext_debug("move %d:"E3FSBLK":%d in new leaf "E3FSBLK"\n", |
637 | le32_to_cpu(path[depth].p_ext->ee_block), | 673 | le32_to_cpu(path[depth].p_ext->ee_block), |
638 | le32_to_cpu(path[depth].p_ext->ee_start), | 674 | ext_pblock(path[depth].p_ext), |
639 | le16_to_cpu(path[depth].p_ext->ee_len), | 675 | le16_to_cpu(path[depth].p_ext->ee_len), |
640 | newblock); | 676 | newblock); |
641 | /*memmove(ex++, path[depth].p_ext++, | 677 | /*memmove(ex++, path[depth].p_ext++, |
@@ -679,7 +715,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
679 | while (k--) { | 715 | while (k--) { |
680 | oldblock = newblock; | 716 | oldblock = newblock; |
681 | newblock = ablocks[--a]; | 717 | newblock = ablocks[--a]; |
682 | bh = sb_getblk(inode->i_sb, newblock); | 718 | bh = sb_getblk(inode->i_sb, (ext4_fsblk_t)newblock); |
683 | if (!bh) { | 719 | if (!bh) { |
684 | err = -EIO; | 720 | err = -EIO; |
685 | goto cleanup; | 721 | goto cleanup; |
@@ -696,9 +732,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
696 | neh->eh_depth = cpu_to_le16(depth - i); | 732 | neh->eh_depth = cpu_to_le16(depth - i); |
697 | fidx = EXT_FIRST_INDEX(neh); | 733 | fidx = EXT_FIRST_INDEX(neh); |
698 | fidx->ei_block = border; | 734 | fidx->ei_block = border; |
699 | fidx->ei_leaf = cpu_to_le32(oldblock); | 735 | ext4_idx_store_pblock(fidx, oldblock); |
700 | 736 | ||
701 | ext_debug("int.index at %d (block %lu): %lu -> %lu\n", i, | 737 | ext_debug("int.index at %d (block "E3FSBLK"): %lu -> "E3FSBLK"\n", i, |
702 | newblock, (unsigned long) le32_to_cpu(border), | 738 | newblock, (unsigned long) le32_to_cpu(border), |
703 | oldblock); | 739 | oldblock); |
704 | /* copy indexes */ | 740 | /* copy indexes */ |
@@ -710,9 +746,9 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, | |||
710 | BUG_ON(EXT_MAX_INDEX(path[i].p_hdr) != | 746 | BUG_ON(EXT_MAX_INDEX(path[i].p_hdr) != |
711 | EXT_LAST_INDEX(path[i].p_hdr)); | 747 | EXT_LAST_INDEX(path[i].p_hdr)); |
712 | while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { | 748 | while (path[i].p_idx <= EXT_MAX_INDEX(path[i].p_hdr)) { |
713 | ext_debug("%d: move %d:%d in new index %lu\n", i, | 749 | ext_debug("%d: move %d:%d in new index "E3FSBLK"\n", i, |
714 | le32_to_cpu(path[i].p_idx->ei_block), | 750 | le32_to_cpu(path[i].p_idx->ei_block), |
715 | le32_to_cpu(path[i].p_idx->ei_leaf), | 751 | idx_pblock(path[i].p_idx), |
716 | newblock); | 752 | newblock); |
717 | /*memmove(++fidx, path[i].p_idx++, | 753 | /*memmove(++fidx, path[i].p_idx++, |
718 | sizeof(struct ext4_extent_idx)); | 754 | sizeof(struct ext4_extent_idx)); |
@@ -791,7 +827,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
791 | struct ext4_extent_header *neh; | 827 | struct ext4_extent_header *neh; |
792 | struct ext4_extent_idx *fidx; | 828 | struct ext4_extent_idx *fidx; |
793 | struct buffer_head *bh; | 829 | struct buffer_head *bh; |
794 | unsigned long newblock; | 830 | ext4_fsblk_t newblock; |
795 | int err = 0; | 831 | int err = 0; |
796 | 832 | ||
797 | newblock = ext4_ext_new_block(handle, inode, path, newext, &err); | 833 | newblock = ext4_ext_new_block(handle, inode, path, newext, &err); |
@@ -839,13 +875,13 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, | |||
839 | curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); | 875 | curp->p_idx = EXT_FIRST_INDEX(curp->p_hdr); |
840 | /* FIXME: it works, but actually path[0] can be index */ | 876 | /* FIXME: it works, but actually path[0] can be index */ |
841 | curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block; | 877 | curp->p_idx->ei_block = EXT_FIRST_EXTENT(path[0].p_hdr)->ee_block; |
842 | curp->p_idx->ei_leaf = cpu_to_le32(newblock); | 878 | ext4_idx_store_pblock(curp->p_idx, newblock); |
843 | 879 | ||
844 | neh = ext_inode_hdr(inode); | 880 | neh = ext_inode_hdr(inode); |
845 | fidx = EXT_FIRST_INDEX(neh); | 881 | fidx = EXT_FIRST_INDEX(neh); |
846 | ext_debug("new root: num %d(%d), lblock %d, ptr %d\n", | 882 | ext_debug("new root: num %d(%d), lblock %d, ptr "E3FSBLK"\n", |
847 | le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max), | 883 | le16_to_cpu(neh->eh_entries), le16_to_cpu(neh->eh_max), |
848 | le32_to_cpu(fidx->ei_block), le32_to_cpu(fidx->ei_leaf)); | 884 | le32_to_cpu(fidx->ei_block), idx_pblock(fidx)); |
849 | 885 | ||
850 | neh->eh_depth = cpu_to_le16(path->p_depth + 1); | 886 | neh->eh_depth = cpu_to_le16(path->p_depth + 1); |
851 | err = ext4_ext_dirty(handle, inode, curp); | 887 | err = ext4_ext_dirty(handle, inode, curp); |
@@ -1042,7 +1078,6 @@ static int inline | |||
1042 | ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | 1078 | ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, |
1043 | struct ext4_extent *ex2) | 1079 | struct ext4_extent *ex2) |
1044 | { | 1080 | { |
1045 | /* FIXME: 48bit support */ | ||
1046 | if (le32_to_cpu(ex1->ee_block) + le16_to_cpu(ex1->ee_len) | 1081 | if (le32_to_cpu(ex1->ee_block) + le16_to_cpu(ex1->ee_len) |
1047 | != le32_to_cpu(ex2->ee_block)) | 1082 | != le32_to_cpu(ex2->ee_block)) |
1048 | return 0; | 1083 | return 0; |
@@ -1052,8 +1087,7 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1, | |||
1052 | return 0; | 1087 | return 0; |
1053 | #endif | 1088 | #endif |
1054 | 1089 | ||
1055 | if (le32_to_cpu(ex1->ee_start) + le16_to_cpu(ex1->ee_len) | 1090 | if (ext_pblock(ex1) + le16_to_cpu(ex1->ee_len) == ext_pblock(ex2)) |
1056 | == le32_to_cpu(ex2->ee_start)) | ||
1057 | return 1; | 1091 | return 1; |
1058 | return 0; | 1092 | return 0; |
1059 | } | 1093 | } |
@@ -1080,11 +1114,10 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, | |||
1080 | 1114 | ||
1081 | /* try to insert block into found extent and return */ | 1115 | /* try to insert block into found extent and return */ |
1082 | if (ex && ext4_can_extents_be_merged(inode, ex, newext)) { | 1116 | if (ex && ext4_can_extents_be_merged(inode, ex, newext)) { |
1083 | ext_debug("append %d block to %d:%d (from %d)\n", | 1117 | ext_debug("append %d block to %d:%d (from "E3FSBLK")\n", |
1084 | le16_to_cpu(newext->ee_len), | 1118 | le16_to_cpu(newext->ee_len), |
1085 | le32_to_cpu(ex->ee_block), | 1119 | le32_to_cpu(ex->ee_block), |
1086 | le16_to_cpu(ex->ee_len), | 1120 | le16_to_cpu(ex->ee_len), ext_pblock(ex)); |
1087 | le32_to_cpu(ex->ee_start)); | ||
1088 | if ((err = ext4_ext_get_access(handle, inode, path + depth))) | 1121 | if ((err = ext4_ext_get_access(handle, inode, path + depth))) |
1089 | return err; | 1122 | return err; |
1090 | ex->ee_len = cpu_to_le16(le16_to_cpu(ex->ee_len) | 1123 | ex->ee_len = cpu_to_le16(le16_to_cpu(ex->ee_len) |
@@ -1140,9 +1173,9 @@ has_space: | |||
1140 | 1173 | ||
1141 | if (!nearex) { | 1174 | if (!nearex) { |
1142 | /* there is no extent in this leaf, create first one */ | 1175 | /* there is no extent in this leaf, create first one */ |
1143 | ext_debug("first extent in the leaf: %d:%d:%d\n", | 1176 | ext_debug("first extent in the leaf: %d:"E3FSBLK":%d\n", |
1144 | le32_to_cpu(newext->ee_block), | 1177 | le32_to_cpu(newext->ee_block), |
1145 | le32_to_cpu(newext->ee_start), | 1178 | ext_pblock(newext), |
1146 | le16_to_cpu(newext->ee_len)); | 1179 | le16_to_cpu(newext->ee_len)); |
1147 | path[depth].p_ext = EXT_FIRST_EXTENT(eh); | 1180 | path[depth].p_ext = EXT_FIRST_EXTENT(eh); |
1148 | } else if (le32_to_cpu(newext->ee_block) | 1181 | } else if (le32_to_cpu(newext->ee_block) |
@@ -1152,10 +1185,10 @@ has_space: | |||
1152 | len = EXT_MAX_EXTENT(eh) - nearex; | 1185 | len = EXT_MAX_EXTENT(eh) - nearex; |
1153 | len = (len - 1) * sizeof(struct ext4_extent); | 1186 | len = (len - 1) * sizeof(struct ext4_extent); |
1154 | len = len < 0 ? 0 : len; | 1187 | len = len < 0 ? 0 : len; |
1155 | ext_debug("insert %d:%d:%d after: nearest 0x%p, " | 1188 | ext_debug("insert %d:"E3FSBLK":%d after: nearest 0x%p, " |
1156 | "move %d from 0x%p to 0x%p\n", | 1189 | "move %d from 0x%p to 0x%p\n", |
1157 | le32_to_cpu(newext->ee_block), | 1190 | le32_to_cpu(newext->ee_block), |
1158 | le32_to_cpu(newext->ee_start), | 1191 | ext_pblock(newext), |
1159 | le16_to_cpu(newext->ee_len), | 1192 | le16_to_cpu(newext->ee_len), |
1160 | nearex, len, nearex + 1, nearex + 2); | 1193 | nearex, len, nearex + 1, nearex + 2); |
1161 | memmove(nearex + 2, nearex + 1, len); | 1194 | memmove(nearex + 2, nearex + 1, len); |
@@ -1165,10 +1198,10 @@ has_space: | |||
1165 | BUG_ON(newext->ee_block == nearex->ee_block); | 1198 | BUG_ON(newext->ee_block == nearex->ee_block); |
1166 | len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext4_extent); | 1199 | len = (EXT_MAX_EXTENT(eh) - nearex) * sizeof(struct ext4_extent); |
1167 | len = len < 0 ? 0 : len; | 1200 | len = len < 0 ? 0 : len; |
1168 | ext_debug("insert %d:%d:%d before: nearest 0x%p, " | 1201 | ext_debug("insert %d:"E3FSBLK":%d before: nearest 0x%p, " |
1169 | "move %d from 0x%p to 0x%p\n", | 1202 | "move %d from 0x%p to 0x%p\n", |
1170 | le32_to_cpu(newext->ee_block), | 1203 | le32_to_cpu(newext->ee_block), |
1171 | le32_to_cpu(newext->ee_start), | 1204 | ext_pblock(newext), |
1172 | le16_to_cpu(newext->ee_len), | 1205 | le16_to_cpu(newext->ee_len), |
1173 | nearex, len, nearex + 1, nearex + 2); | 1206 | nearex, len, nearex + 1, nearex + 2); |
1174 | memmove(nearex + 1, nearex, len); | 1207 | memmove(nearex + 1, nearex, len); |
@@ -1179,9 +1212,8 @@ has_space: | |||
1179 | nearex = path[depth].p_ext; | 1212 | nearex = path[depth].p_ext; |
1180 | nearex->ee_block = newext->ee_block; | 1213 | nearex->ee_block = newext->ee_block; |
1181 | nearex->ee_start = newext->ee_start; | 1214 | nearex->ee_start = newext->ee_start; |
1215 | nearex->ee_start_hi = newext->ee_start_hi; | ||
1182 | nearex->ee_len = newext->ee_len; | 1216 | nearex->ee_len = newext->ee_len; |
1183 | /* FIXME: support for large fs */ | ||
1184 | nearex->ee_start_hi = 0; | ||
1185 | 1217 | ||
1186 | merge: | 1218 | merge: |
1187 | /* try to merge extents to the right */ | 1219 | /* try to merge extents to the right */ |
@@ -1290,7 +1322,7 @@ int ext4_ext_walk_space(struct inode *inode, unsigned long block, | |||
1290 | } else { | 1322 | } else { |
1291 | cbex.ec_block = le32_to_cpu(ex->ee_block); | 1323 | cbex.ec_block = le32_to_cpu(ex->ee_block); |
1292 | cbex.ec_len = le16_to_cpu(ex->ee_len); | 1324 | cbex.ec_len = le16_to_cpu(ex->ee_len); |
1293 | cbex.ec_start = le32_to_cpu(ex->ee_start); | 1325 | cbex.ec_start = ext_pblock(ex); |
1294 | cbex.ec_type = EXT4_EXT_CACHE_EXTENT; | 1326 | cbex.ec_type = EXT4_EXT_CACHE_EXTENT; |
1295 | } | 1327 | } |
1296 | 1328 | ||
@@ -1398,13 +1430,13 @@ ext4_ext_in_cache(struct inode *inode, unsigned long block, | |||
1398 | cex->ec_type != EXT4_EXT_CACHE_EXTENT); | 1430 | cex->ec_type != EXT4_EXT_CACHE_EXTENT); |
1399 | if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { | 1431 | if (block >= cex->ec_block && block < cex->ec_block + cex->ec_len) { |
1400 | ex->ee_block = cpu_to_le32(cex->ec_block); | 1432 | ex->ee_block = cpu_to_le32(cex->ec_block); |
1401 | ex->ee_start = cpu_to_le32(cex->ec_start); | 1433 | ext4_ext_store_pblock(ex, cex->ec_start); |
1402 | ex->ee_len = cpu_to_le16(cex->ec_len); | 1434 | ex->ee_len = cpu_to_le16(cex->ec_len); |
1403 | ext_debug("%lu cached by %lu:%lu:%lu\n", | 1435 | ext_debug("%lu cached by %lu:%lu:"E3FSBLK"\n", |
1404 | (unsigned long) block, | 1436 | (unsigned long) block, |
1405 | (unsigned long) cex->ec_block, | 1437 | (unsigned long) cex->ec_block, |
1406 | (unsigned long) cex->ec_len, | 1438 | (unsigned long) cex->ec_len, |
1407 | (unsigned long) cex->ec_start); | 1439 | cex->ec_start); |
1408 | return cex->ec_type; | 1440 | return cex->ec_type; |
1409 | } | 1441 | } |
1410 | 1442 | ||
@@ -1422,18 +1454,18 @@ int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, | |||
1422 | { | 1454 | { |
1423 | struct buffer_head *bh; | 1455 | struct buffer_head *bh; |
1424 | int err; | 1456 | int err; |
1425 | unsigned long leaf; | 1457 | ext4_fsblk_t leaf; |
1426 | 1458 | ||
1427 | /* free index block */ | 1459 | /* free index block */ |
1428 | path--; | 1460 | path--; |
1429 | leaf = le32_to_cpu(path->p_idx->ei_leaf); | 1461 | leaf = idx_pblock(path->p_idx); |
1430 | BUG_ON(path->p_hdr->eh_entries == 0); | 1462 | BUG_ON(path->p_hdr->eh_entries == 0); |
1431 | if ((err = ext4_ext_get_access(handle, inode, path))) | 1463 | if ((err = ext4_ext_get_access(handle, inode, path))) |
1432 | return err; | 1464 | return err; |
1433 | path->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1); | 1465 | path->p_hdr->eh_entries = cpu_to_le16(le16_to_cpu(path->p_hdr->eh_entries)-1); |
1434 | if ((err = ext4_ext_dirty(handle, inode, path))) | 1466 | if ((err = ext4_ext_dirty(handle, inode, path))) |
1435 | return err; | 1467 | return err; |
1436 | ext_debug("index is empty, remove it, free block %lu\n", leaf); | 1468 | ext_debug("index is empty, remove it, free block "E3FSBLK"\n", leaf); |
1437 | bh = sb_find_get_block(inode->i_sb, leaf); | 1469 | bh = sb_find_get_block(inode->i_sb, leaf); |
1438 | ext4_forget(handle, 1, inode, bh, leaf); | 1470 | ext4_forget(handle, 1, inode, bh, leaf); |
1439 | ext4_free_blocks(handle, inode, leaf, 1); | 1471 | ext4_free_blocks(handle, inode, leaf, 1); |
@@ -1515,10 +1547,11 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, | |||
1515 | if (from >= le32_to_cpu(ex->ee_block) | 1547 | if (from >= le32_to_cpu(ex->ee_block) |
1516 | && to == le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len) - 1) { | 1548 | && to == le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len) - 1) { |
1517 | /* tail removal */ | 1549 | /* tail removal */ |
1518 | unsigned long num, start; | 1550 | unsigned long num; |
1551 | ext4_fsblk_t start; | ||
1519 | num = le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len) - from; | 1552 | num = le32_to_cpu(ex->ee_block) + le16_to_cpu(ex->ee_len) - from; |
1520 | start = le32_to_cpu(ex->ee_start) + le16_to_cpu(ex->ee_len) - num; | 1553 | start = ext_pblock(ex) + le16_to_cpu(ex->ee_len) - num; |
1521 | ext_debug("free last %lu blocks starting %lu\n", num, start); | 1554 | ext_debug("free last %lu blocks starting "E3FSBLK"\n", num, start); |
1522 | for (i = 0; i < num; i++) { | 1555 | for (i = 0; i < num; i++) { |
1523 | bh = sb_find_get_block(inode->i_sb, start + i); | 1556 | bh = sb_find_get_block(inode->i_sb, start + i); |
1524 | ext4_forget(handle, 0, inode, bh, start + i); | 1557 | ext4_forget(handle, 0, inode, bh, start + i); |
@@ -1621,7 +1654,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
1621 | 1654 | ||
1622 | if (num == 0) { | 1655 | if (num == 0) { |
1623 | /* this extent is removed entirely mark slot unused */ | 1656 | /* this extent is removed entirely mark slot unused */ |
1624 | ex->ee_start = 0; | 1657 | ext4_ext_store_pblock(ex, 0); |
1625 | eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)-1); | 1658 | eh->eh_entries = cpu_to_le16(le16_to_cpu(eh->eh_entries)-1); |
1626 | } | 1659 | } |
1627 | 1660 | ||
@@ -1632,8 +1665,8 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
1632 | if (err) | 1665 | if (err) |
1633 | goto out; | 1666 | goto out; |
1634 | 1667 | ||
1635 | ext_debug("new extent: %u:%u:%u\n", block, num, | 1668 | ext_debug("new extent: %u:%u:"E3FSBLK"\n", block, num, |
1636 | le32_to_cpu(ex->ee_start)); | 1669 | ext_pblock(ex)); |
1637 | ex--; | 1670 | ex--; |
1638 | ex_ee_block = le32_to_cpu(ex->ee_block); | 1671 | ex_ee_block = le32_to_cpu(ex->ee_block); |
1639 | ex_ee_len = le16_to_cpu(ex->ee_len); | 1672 | ex_ee_len = le16_to_cpu(ex->ee_len); |
@@ -1748,11 +1781,11 @@ int ext4_ext_remove_space(struct inode *inode, unsigned long start) | |||
1748 | path[i].p_idx); | 1781 | path[i].p_idx); |
1749 | if (ext4_ext_more_to_rm(path + i)) { | 1782 | if (ext4_ext_more_to_rm(path + i)) { |
1750 | /* go to the next level */ | 1783 | /* go to the next level */ |
1751 | ext_debug("move to level %d (block %d)\n", | 1784 | ext_debug("move to level %d (block "E3FSBLK")\n", |
1752 | i + 1, le32_to_cpu(path[i].p_idx->ei_leaf)); | 1785 | i + 1, idx_pblock(path[i].p_idx)); |
1753 | memset(path + i + 1, 0, sizeof(*path)); | 1786 | memset(path + i + 1, 0, sizeof(*path)); |
1754 | path[i+1].p_bh = | 1787 | path[i+1].p_bh = |
1755 | sb_bread(sb, le32_to_cpu(path[i].p_idx->ei_leaf)); | 1788 | sb_bread(sb, idx_pblock(path[i].p_idx)); |
1756 | if (!path[i+1].p_bh) { | 1789 | if (!path[i+1].p_bh) { |
1757 | /* should we reset i_size? */ | 1790 | /* should we reset i_size? */ |
1758 | err = -EIO; | 1791 | err = -EIO; |
@@ -1851,13 +1884,15 @@ void ext4_ext_release(struct super_block *sb) | |||
1851 | #endif | 1884 | #endif |
1852 | } | 1885 | } |
1853 | 1886 | ||
1854 | int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, sector_t iblock, | 1887 | int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, |
1888 | ext4_fsblk_t iblock, | ||
1855 | unsigned long max_blocks, struct buffer_head *bh_result, | 1889 | unsigned long max_blocks, struct buffer_head *bh_result, |
1856 | int create, int extend_disksize) | 1890 | int create, int extend_disksize) |
1857 | { | 1891 | { |
1858 | struct ext4_ext_path *path = NULL; | 1892 | struct ext4_ext_path *path = NULL; |
1859 | struct ext4_extent newex, *ex; | 1893 | struct ext4_extent newex, *ex; |
1860 | int goal, newblock, err = 0, depth; | 1894 | ext4_fsblk_t goal, newblock; |
1895 | int err = 0, depth; | ||
1861 | unsigned long allocated = 0; | 1896 | unsigned long allocated = 0; |
1862 | 1897 | ||
1863 | __clear_bit(BH_New, &bh_result->b_state); | 1898 | __clear_bit(BH_New, &bh_result->b_state); |
@@ -1878,7 +1913,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, sector_t iblock, | |||
1878 | /* block is already allocated */ | 1913 | /* block is already allocated */ |
1879 | newblock = iblock | 1914 | newblock = iblock |
1880 | - le32_to_cpu(newex.ee_block) | 1915 | - le32_to_cpu(newex.ee_block) |
1881 | + le32_to_cpu(newex.ee_start); | 1916 | + ext_pblock(&newex); |
1882 | /* number of remain blocks in the extent */ | 1917 | /* number of remain blocks in the extent */ |
1883 | allocated = le16_to_cpu(newex.ee_len) - | 1918 | allocated = le16_to_cpu(newex.ee_len) - |
1884 | (iblock - le32_to_cpu(newex.ee_block)); | 1919 | (iblock - le32_to_cpu(newex.ee_block)); |
@@ -1907,14 +1942,14 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, sector_t iblock, | |||
1907 | 1942 | ||
1908 | if ((ex = path[depth].p_ext)) { | 1943 | if ((ex = path[depth].p_ext)) { |
1909 | unsigned long ee_block = le32_to_cpu(ex->ee_block); | 1944 | unsigned long ee_block = le32_to_cpu(ex->ee_block); |
1910 | unsigned long ee_start = le32_to_cpu(ex->ee_start); | 1945 | ext4_fsblk_t ee_start = ext_pblock(ex); |
1911 | unsigned short ee_len = le16_to_cpu(ex->ee_len); | 1946 | unsigned short ee_len = le16_to_cpu(ex->ee_len); |
1912 | /* if found exent covers block, simple return it */ | 1947 | /* if found exent covers block, simple return it */ |
1913 | if (iblock >= ee_block && iblock < ee_block + ee_len) { | 1948 | if (iblock >= ee_block && iblock < ee_block + ee_len) { |
1914 | newblock = iblock - ee_block + ee_start; | 1949 | newblock = iblock - ee_block + ee_start; |
1915 | /* number of remain blocks in the extent */ | 1950 | /* number of remain blocks in the extent */ |
1916 | allocated = ee_len - (iblock - ee_block); | 1951 | allocated = ee_len - (iblock - ee_block); |
1917 | ext_debug("%d fit into %lu:%d -> %d\n", (int) iblock, | 1952 | ext_debug("%d fit into %lu:%d -> "E3FSBLK"\n", (int) iblock, |
1918 | ee_block, ee_len, newblock); | 1953 | ee_block, ee_len, newblock); |
1919 | ext4_ext_put_in_cache(inode, ee_block, ee_len, | 1954 | ext4_ext_put_in_cache(inode, ee_block, ee_len, |
1920 | ee_start, EXT4_EXT_CACHE_EXTENT); | 1955 | ee_start, EXT4_EXT_CACHE_EXTENT); |
@@ -1944,12 +1979,12 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, sector_t iblock, | |||
1944 | newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err); | 1979 | newblock = ext4_new_blocks(handle, inode, goal, &allocated, &err); |
1945 | if (!newblock) | 1980 | if (!newblock) |
1946 | goto out2; | 1981 | goto out2; |
1947 | ext_debug("allocate new block: goal %d, found %d/%lu\n", | 1982 | ext_debug("allocate new block: goal "E3FSBLK", found "E3FSBLK"/%lu\n", |
1948 | goal, newblock, allocated); | 1983 | goal, newblock, allocated); |
1949 | 1984 | ||
1950 | /* try to insert new extent into found leaf and return */ | 1985 | /* try to insert new extent into found leaf and return */ |
1951 | newex.ee_block = cpu_to_le32(iblock); | 1986 | newex.ee_block = cpu_to_le32(iblock); |
1952 | newex.ee_start = cpu_to_le32(newblock); | 1987 | ext4_ext_store_pblock(&newex, newblock); |
1953 | newex.ee_len = cpu_to_le16(allocated); | 1988 | newex.ee_len = cpu_to_le16(allocated); |
1954 | err = ext4_ext_insert_extent(handle, inode, path, &newex); | 1989 | err = ext4_ext_insert_extent(handle, inode, path, &newex); |
1955 | if (err) | 1990 | if (err) |
@@ -1959,7 +1994,7 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode, sector_t iblock, | |||
1959 | EXT4_I(inode)->i_disksize = inode->i_size; | 1994 | EXT4_I(inode)->i_disksize = inode->i_size; |
1960 | 1995 | ||
1961 | /* previous routine could use block we allocated */ | 1996 | /* previous routine could use block we allocated */ |
1962 | newblock = le32_to_cpu(newex.ee_start); | 1997 | newblock = ext_pblock(&newex); |
1963 | __set_bit(BH_New, &bh_result->b_state); | 1998 | __set_bit(BH_New, &bh_result->b_state); |
1964 | 1999 | ||
1965 | ext4_ext_put_in_cache(inode, iblock, allocated, newblock, | 2000 | ext4_ext_put_in_cache(inode, iblock, allocated, newblock, |
diff --git a/include/linux/ext4_fs_extents.h b/include/linux/ext4_fs_extents.h index 8029879e29e2..facc76684d4f 100644 --- a/include/linux/ext4_fs_extents.h +++ b/include/linux/ext4_fs_extents.h | |||
@@ -108,7 +108,7 @@ struct ext4_extent_header { | |||
108 | * truncate uses it to simulate recursive walking | 108 | * truncate uses it to simulate recursive walking |
109 | */ | 109 | */ |
110 | struct ext4_ext_path { | 110 | struct ext4_ext_path { |
111 | __u32 p_block; | 111 | ext4_fsblk_t p_block; |
112 | __u16 p_depth; | 112 | __u16 p_depth; |
113 | struct ext4_extent *p_ext; | 113 | struct ext4_extent *p_ext; |
114 | struct ext4_extent_idx *p_idx; | 114 | struct ext4_extent_idx *p_idx; |
diff --git a/include/linux/ext4_fs_i.h b/include/linux/ext4_fs_i.h index b2ccd9876bd1..2bed0effdcae 100644 --- a/include/linux/ext4_fs_i.h +++ b/include/linux/ext4_fs_i.h | |||
@@ -72,10 +72,10 @@ struct ext4_block_alloc_info { | |||
72 | * storage for cached extent | 72 | * storage for cached extent |
73 | */ | 73 | */ |
74 | struct ext4_ext_cache { | 74 | struct ext4_ext_cache { |
75 | __u32 ec_start; | 75 | ext4_fsblk_t ec_start; |
76 | __u32 ec_block; | 76 | __u32 ec_block; |
77 | __u32 ec_len; /* must be 32bit to return holes */ | 77 | __u32 ec_len; /* must be 32bit to return holes */ |
78 | __u32 ec_type; | 78 | __u32 ec_type; |
79 | }; | 79 | }; |
80 | 80 | ||
81 | /* | 81 | /* |