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/extent_map.c | |
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/extent_map.c')
-rw-r--r-- | fs/ocfs2/extent_map.c | 107 |
1 files changed, 103 insertions, 4 deletions
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); |