diff options
author | Mark Fasheh <mark.fasheh@oracle.com> | 2007-03-09 19:26:50 -0500 |
---|---|---|
committer | Mark Fasheh <mark.fasheh@oracle.com> | 2007-04-26 18:02:45 -0400 |
commit | 4f902c37727bbedbc0508a1477874c58ddcc9af8 (patch) | |
tree | 841b35387cfea5d2518c258c4de6ef868948369b /fs/ocfs2 | |
parent | 49cb8d2d496ce06869ccca2ab368ed6b0b5b979d (diff) |
ocfs2: Fix extent lookup to return true size of holes
Initially, we had wired things to return a size '1' of holes. Cook up a
small amount of code to find the next extent and calculate the number of
clusters between the virtual offset and the next allocated extent.
Signed-off-by: Mark Fasheh <mark.fasheh@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/aops.c | 3 | ||||
-rw-r--r-- | fs/ocfs2/extent_map.c | 107 | ||||
-rw-r--r-- | fs/ocfs2/extent_map.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/journal.c | 6 | ||||
-rw-r--r-- | fs/ocfs2/namei.c | 3 |
5 files changed, 109 insertions, 12 deletions
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index eb67c902b002..ff71e0b430cd 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c | |||
@@ -439,8 +439,7 @@ static int ocfs2_direct_IO_get_blocks(struct inode *inode, sector_t iblock, | |||
439 | struct buffer_head *bh_result, int create) | 439 | struct buffer_head *bh_result, int create) |
440 | { | 440 | { |
441 | int ret; | 441 | int ret; |
442 | u64 p_blkno, inode_blocks; | 442 | u64 p_blkno, inode_blocks, contig_blocks; |
443 | int contig_blocks; | ||
444 | unsigned int ext_flags; | 443 | unsigned int ext_flags; |
445 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; | 444 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; |
446 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; | 445 | unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; |
diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index eef6c1887708..f35e04f27f32 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c | |||
@@ -39,6 +39,97 @@ | |||
39 | #include "buffer_head_io.h" | 39 | #include "buffer_head_io.h" |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Return the 1st index within el which contains an extent start | ||
43 | * larger than v_cluster. | ||
44 | */ | ||
45 | static int ocfs2_search_for_hole_index(struct ocfs2_extent_list *el, | ||
46 | u32 v_cluster) | ||
47 | { | ||
48 | int i; | ||
49 | struct ocfs2_extent_rec *rec; | ||
50 | |||
51 | for(i = 0; i < le16_to_cpu(el->l_next_free_rec); i++) { | ||
52 | rec = &el->l_recs[i]; | ||
53 | |||
54 | if (v_cluster < le32_to_cpu(rec->e_cpos)) | ||
55 | break; | ||
56 | } | ||
57 | |||
58 | return i; | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Figure out the size of a hole which starts at v_cluster within the given | ||
63 | * extent list. | ||
64 | * | ||
65 | * If there is no more allocation past v_cluster, we return the maximum | ||
66 | * cluster size minus v_cluster. | ||
67 | * | ||
68 | * If we have in-inode extents, then el points to the dinode list and | ||
69 | * eb_bh is NULL. Otherwise, eb_bh should point to the extent block | ||
70 | * containing el. | ||
71 | */ | ||
72 | static int ocfs2_figure_hole_clusters(struct inode *inode, | ||
73 | struct ocfs2_extent_list *el, | ||
74 | struct buffer_head *eb_bh, | ||
75 | u32 v_cluster, | ||
76 | u32 *num_clusters) | ||
77 | { | ||
78 | int ret, i; | ||
79 | struct buffer_head *next_eb_bh = NULL; | ||
80 | struct ocfs2_extent_block *eb, *next_eb; | ||
81 | |||
82 | i = ocfs2_search_for_hole_index(el, v_cluster); | ||
83 | |||
84 | if (i == le16_to_cpu(el->l_next_free_rec) && eb_bh) { | ||
85 | eb = (struct ocfs2_extent_block *)eb_bh->b_data; | ||
86 | |||
87 | /* | ||
88 | * Check the next leaf for any extents. | ||
89 | */ | ||
90 | |||
91 | if (le64_to_cpu(eb->h_next_leaf_blk) == 0ULL) | ||
92 | goto no_more_extents; | ||
93 | |||
94 | ret = ocfs2_read_block(OCFS2_SB(inode->i_sb), | ||
95 | le64_to_cpu(eb->h_next_leaf_blk), | ||
96 | &next_eb_bh, OCFS2_BH_CACHED, inode); | ||
97 | if (ret) { | ||
98 | mlog_errno(ret); | ||
99 | goto out; | ||
100 | } | ||
101 | next_eb = (struct ocfs2_extent_block *)next_eb_bh->b_data; | ||
102 | |||
103 | if (!OCFS2_IS_VALID_EXTENT_BLOCK(next_eb)) { | ||
104 | ret = -EROFS; | ||
105 | OCFS2_RO_ON_INVALID_EXTENT_BLOCK(inode->i_sb, next_eb); | ||
106 | goto out; | ||
107 | } | ||
108 | |||
109 | el = &next_eb->h_list; | ||
110 | |||
111 | i = ocfs2_search_for_hole_index(el, v_cluster); | ||
112 | } | ||
113 | |||
114 | no_more_extents: | ||
115 | if (i == le16_to_cpu(el->l_next_free_rec)) { | ||
116 | /* | ||
117 | * We're at the end of our existing allocation. Just | ||
118 | * return the maximum number of clusters we could | ||
119 | * possibly allocate. | ||
120 | */ | ||
121 | *num_clusters = UINT_MAX - v_cluster; | ||
122 | } else { | ||
123 | *num_clusters = le32_to_cpu(el->l_recs[i].e_cpos) - v_cluster; | ||
124 | } | ||
125 | |||
126 | ret = 0; | ||
127 | out: | ||
128 | brelse(next_eb_bh); | ||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | /* | ||
42 | * Return the index of the extent record which contains cluster #v_cluster. | 133 | * Return the index of the extent record which contains cluster #v_cluster. |
43 | * -1 is returned if it was not found. | 134 | * -1 is returned if it was not found. |
44 | * | 135 | * |
@@ -117,11 +208,19 @@ int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, | |||
117 | if (i == -1) { | 208 | if (i == -1) { |
118 | /* | 209 | /* |
119 | * A hole was found. Return some canned values that | 210 | * A hole was found. Return some canned values that |
120 | * callers can key on. | 211 | * callers can key on. If asked for, num_clusters will |
212 | * be populated with the size of the hole. | ||
121 | */ | 213 | */ |
122 | *p_cluster = 0; | 214 | *p_cluster = 0; |
123 | if (num_clusters) | 215 | if (num_clusters) { |
124 | *num_clusters = 1; | 216 | ret = ocfs2_figure_hole_clusters(inode, el, eb_bh, |
217 | v_cluster, | ||
218 | num_clusters); | ||
219 | if (ret) { | ||
220 | mlog_errno(ret); | ||
221 | goto out; | ||
222 | } | ||
223 | } | ||
125 | } else { | 224 | } else { |
126 | rec = &el->l_recs[i]; | 225 | rec = &el->l_recs[i]; |
127 | 226 | ||
@@ -162,7 +261,7 @@ out: | |||
162 | * all while the map is in the process of being updated. | 261 | * all while the map is in the process of being updated. |
163 | */ | 262 | */ |
164 | int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, | 263 | int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, |
165 | int *ret_count, unsigned int *extent_flags) | 264 | u64 *ret_count, unsigned int *extent_flags) |
166 | { | 265 | { |
167 | int ret; | 266 | int ret; |
168 | int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); | 267 | int bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); |
diff --git a/fs/ocfs2/extent_map.h b/fs/ocfs2/extent_map.h index 0031c59c347f..1d745e174afc 100644 --- a/fs/ocfs2/extent_map.h +++ b/fs/ocfs2/extent_map.h | |||
@@ -28,6 +28,6 @@ | |||
28 | int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster, | 28 | int ocfs2_get_clusters(struct inode *inode, u32 v_cluster, u32 *p_cluster, |
29 | u32 *num_clusters, unsigned int *extent_flags); | 29 | u32 *num_clusters, unsigned int *extent_flags); |
30 | int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, | 30 | int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno, |
31 | int *ret_count, unsigned int *extent_flags); | 31 | u64 *ret_count, unsigned int *extent_flags); |
32 | 32 | ||
33 | #endif /* _EXTENT_MAP_H */ | 33 | #endif /* _EXTENT_MAP_H */ |
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c index db77e0996bb7..12d2340eee29 100644 --- a/fs/ocfs2/journal.c +++ b/fs/ocfs2/journal.c | |||
@@ -649,9 +649,9 @@ bail: | |||
649 | static int ocfs2_force_read_journal(struct inode *inode) | 649 | static int ocfs2_force_read_journal(struct inode *inode) |
650 | { | 650 | { |
651 | int status = 0; | 651 | int status = 0; |
652 | int i, p_blocks; | 652 | int i; |
653 | u64 v_blkno, p_blkno; | 653 | u64 v_blkno, p_blkno, p_blocks; |
654 | #define CONCURRENT_JOURNAL_FILL 32 | 654 | #define CONCURRENT_JOURNAL_FILL 32ULL |
655 | struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL]; | 655 | struct buffer_head *bhs[CONCURRENT_JOURNAL_FILL]; |
656 | 656 | ||
657 | mlog_entry_void(); | 657 | mlog_entry_void(); |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index 395859edb51f..9bdbe4ae92f8 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
@@ -1483,8 +1483,7 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb, | |||
1483 | struct buffer_head **bhs = NULL; | 1483 | struct buffer_head **bhs = NULL; |
1484 | const char *c; | 1484 | const char *c; |
1485 | struct super_block *sb = osb->sb; | 1485 | struct super_block *sb = osb->sb; |
1486 | u64 p_blkno; | 1486 | u64 p_blkno, p_blocks; |
1487 | int p_blocks; | ||
1488 | int virtual, blocks, status, i, bytes_left; | 1487 | int virtual, blocks, status, i, bytes_left; |
1489 | 1488 | ||
1490 | bytes_left = i_size_read(inode) + 1; | 1489 | bytes_left = i_size_read(inode) + 1; |