diff options
Diffstat (limited to 'fs/gfs2')
-rw-r--r-- | fs/gfs2/bmap.c | 48 |
1 files changed, 21 insertions, 27 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index e27e66046f0a..f1f38ca77a52 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c | |||
@@ -188,50 +188,45 @@ static int build_height(struct inode *inode, struct metapath *mp, unsigned heigh | |||
188 | { | 188 | { |
189 | struct gfs2_inode *ip = GFS2_I(inode); | 189 | struct gfs2_inode *ip = GFS2_I(inode); |
190 | unsigned new_height = height - ip->i_height; | 190 | unsigned new_height = height - ip->i_height; |
191 | struct buffer_head *dibh; | 191 | struct buffer_head *dibh = mp->mp_bh[0]; |
192 | struct gfs2_dinode *di; | 192 | struct gfs2_dinode *di; |
193 | int error; | ||
194 | __be64 *bp; | 193 | __be64 *bp; |
195 | u64 bn; | 194 | u64 bn; |
196 | unsigned n, i = 0; | 195 | unsigned n, i = 0; |
197 | 196 | ||
198 | if (height <= ip->i_height) | 197 | BUG_ON(height <= ip->i_height); |
199 | return 0; | ||
200 | |||
201 | error = gfs2_meta_inode_buffer(ip, &dibh); | ||
202 | if (error) | ||
203 | return error; | ||
204 | 198 | ||
205 | do { | 199 | do { |
206 | n = new_height - i; | 200 | n = new_height - i; |
207 | bn = gfs2_alloc_block(ip, &n); | 201 | bn = gfs2_alloc_block(ip, &n); |
208 | gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, n); | 202 | gfs2_trans_add_unrevoke(GFS2_SB(inode), bn, n); |
209 | do { | 203 | do { |
210 | mp->mp_bh[i] = gfs2_meta_new(ip->i_gl, bn++); | 204 | mp->mp_bh[i + 1] = gfs2_meta_new(ip->i_gl, bn++); |
211 | gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i], 1); | 205 | gfs2_trans_add_bh(ip->i_gl, mp->mp_bh[i + 1], 1); |
212 | i++; | 206 | i++; |
213 | } while(i < n); | 207 | } while(i < n); |
214 | } while(i < new_height); | 208 | } while(i < new_height); |
215 | 209 | ||
216 | n = 0; | 210 | n = 0; |
217 | bn = mp->mp_bh[0]->b_blocknr; | 211 | bn = mp->mp_bh[1]->b_blocknr; |
218 | if (new_height > 1) { | 212 | if (new_height > 1) { |
219 | for(; n < new_height-1; n++) { | 213 | for(; n < new_height-1; n++) { |
220 | gfs2_metatype_set(mp->mp_bh[n], GFS2_METATYPE_IN, | 214 | gfs2_metatype_set(mp->mp_bh[n + 1], GFS2_METATYPE_IN, |
221 | GFS2_FORMAT_IN); | 215 | GFS2_FORMAT_IN); |
222 | gfs2_buffer_clear_tail(mp->mp_bh[n], | 216 | gfs2_buffer_clear_tail(mp->mp_bh[n + 1], |
223 | sizeof(struct gfs2_meta_header)); | 217 | sizeof(struct gfs2_meta_header)); |
224 | bp = (__be64 *)(mp->mp_bh[n]->b_data + | 218 | bp = (__be64 *)(mp->mp_bh[n + 1]->b_data + |
225 | sizeof(struct gfs2_meta_header)); | 219 | sizeof(struct gfs2_meta_header)); |
226 | *bp = cpu_to_be64(mp->mp_bh[n+1]->b_blocknr); | 220 | *bp = cpu_to_be64(mp->mp_bh[n+2]->b_blocknr); |
227 | brelse(mp->mp_bh[n]); | 221 | brelse(mp->mp_bh[n+1]); |
228 | mp->mp_bh[n] = NULL; | 222 | mp->mp_bh[n+1] = NULL; |
229 | } | 223 | } |
230 | } | 224 | } |
231 | gfs2_metatype_set(mp->mp_bh[n], GFS2_METATYPE_IN, GFS2_FORMAT_IN); | 225 | gfs2_metatype_set(mp->mp_bh[n+1], GFS2_METATYPE_IN, GFS2_FORMAT_IN); |
232 | gfs2_buffer_copy_tail(mp->mp_bh[n], sizeof(struct gfs2_meta_header), | 226 | gfs2_buffer_copy_tail(mp->mp_bh[n+1], sizeof(struct gfs2_meta_header), |
233 | dibh, sizeof(struct gfs2_dinode)); | 227 | dibh, sizeof(struct gfs2_dinode)); |
234 | brelse(mp->mp_bh[n]); | 228 | brelse(mp->mp_bh[n+1]); |
229 | mp->mp_bh[n+1] = NULL; | ||
235 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); | 230 | gfs2_trans_add_bh(ip->i_gl, dibh, 1); |
236 | di = (struct gfs2_dinode *)dibh->b_data; | 231 | di = (struct gfs2_dinode *)dibh->b_data; |
237 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); | 232 | gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); |
@@ -240,8 +235,7 @@ static int build_height(struct inode *inode, struct metapath *mp, unsigned heigh | |||
240 | gfs2_add_inode_blocks(&ip->i_inode, new_height); | 235 | gfs2_add_inode_blocks(&ip->i_inode, new_height); |
241 | di->di_height = cpu_to_be16(ip->i_height); | 236 | di->di_height = cpu_to_be16(ip->i_height); |
242 | di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); | 237 | di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); |
243 | brelse(dibh); | 238 | return 0; |
244 | return error; | ||
245 | } | 239 | } |
246 | 240 | ||
247 | /** | 241 | /** |
@@ -391,11 +385,7 @@ static int lookup_metapath(struct inode *inode, struct metapath *mp, | |||
391 | struct gfs2_inode *ip = GFS2_I(inode); | 385 | struct gfs2_inode *ip = GFS2_I(inode); |
392 | unsigned int end_of_metadata = ip->i_height - 1; | 386 | unsigned int end_of_metadata = ip->i_height - 1; |
393 | unsigned int x; | 387 | unsigned int x; |
394 | int ret = gfs2_meta_inode_buffer(ip, &bh); | 388 | int ret; |
395 | if (ret) | ||
396 | return ret; | ||
397 | |||
398 | mp->mp_bh[0] = bh; | ||
399 | 389 | ||
400 | for (x = 0; x < end_of_metadata; x++) { | 390 | for (x = 0; x < end_of_metadata; x++) { |
401 | lookup_block(ip, x, mp, create, new, dblock); | 391 | lookup_block(ip, x, mp, create, new, dblock); |
@@ -515,6 +505,10 @@ int gfs2_block_map(struct inode *inode, sector_t lblock, | |||
515 | } | 505 | } |
516 | size = (lblock + 1) * bsize; | 506 | size = (lblock + 1) * bsize; |
517 | 507 | ||
508 | error = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]); | ||
509 | if (error) | ||
510 | goto out_fail; | ||
511 | |||
518 | if (size > arr[ip->i_height]) { | 512 | if (size > arr[ip->i_height]) { |
519 | u8 height = ip->i_height; | 513 | u8 height = ip->i_height; |
520 | if (!create) | 514 | if (!create) |