aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2008-02-12 09:48:39 -0500
committerSteven Whitehouse <swhiteho@redhat.com>2008-03-31 05:40:58 -0400
commite23159d2a7b2df5bce5f0ee8d57d3292243abf66 (patch)
treee7b447b7d1538b614bf041414e59603107c10151
parent77658aad226866fb94097236d14d41a88aaab2ec (diff)
[GFS2] Get inode buffer only once per block map call
In the case that we needed to grow the height of the metadata tree we were looking up the inode buffer and then brelse()ing it despite the fact that it is needed later in the block map process. This patch ensures that we look up the inode's buffer once and only once during the block map process. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/bmap.c48
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)