aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/dir.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2006-09-21 17:05:23 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2006-09-21 17:05:23 -0400
commit7276b3b0c77101f8b3f4e45e89a29cf9045e831a (patch)
tree3dd0a981218e490ddf47f925ba20c254e491ce98 /fs/gfs2/dir.c
parent91fa47964165a42401fbc1f41caa63ab78564305 (diff)
[GFS2] Tidy up meta_io code
Fix a bug in the directory reading code, where we might have dereferenced a NULL pointer in case of OOM. Updated the directory code to use the new & improved version of gfs2_meta_ra() which now returns the first block that was being read. Previously it was releasing it requiring following code to grab the block again at each point it was called. Also turned off readahead on directory lookups since we are reading a hash table, and therefore reading the entries in order is very unlikely. Readahead is still used for all other calls to the directory reading function (e.g. when growing the hash table). Removed the DIO_START constant. Everywhere this was used, it was used to unconditionally start i/o aside from a couple of places, so I've removed it and made the couple of exceptions to this rule into separate functions. Also hunted through the other DIO flags and removed them as arguments from functions which were always called with the same combination of arguments. Updated gfs2_meta_indirect_buffer to be a bit more efficient and hopefully also be a bit easier to read. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/dir.c')
-rw-r--r--fs/gfs2/dir.c56
1 files changed, 26 insertions, 30 deletions
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 739028688270..40e94ac0b93d 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -106,7 +106,7 @@ static int gfs2_dir_get_existing_buffer(struct gfs2_inode *ip, u64 block,
106 struct buffer_head *bh; 106 struct buffer_head *bh;
107 int error; 107 int error;
108 108
109 error = gfs2_meta_read(ip->i_gl, block, DIO_START | DIO_WAIT, &bh); 109 error = gfs2_meta_read(ip->i_gl, block, DIO_WAIT, &bh);
110 if (error) 110 if (error)
111 return error; 111 return error;
112 if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) { 112 if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) {
@@ -246,7 +246,7 @@ fail:
246} 246}
247 247
248static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, char *buf, 248static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, char *buf,
249 unsigned int offset, unsigned int size) 249 u64 offset, unsigned int size)
250{ 250{
251 struct buffer_head *dibh; 251 struct buffer_head *dibh;
252 int error; 252 int error;
@@ -271,8 +271,8 @@ static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, char *buf,
271 * 271 *
272 * Returns: The amount of data actually copied or the error 272 * Returns: The amount of data actually copied or the error
273 */ 273 */
274static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, 274static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset,
275 u64 offset, unsigned int size) 275 unsigned int size, unsigned ra)
276{ 276{
277 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 277 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
278 u64 lblock, dblock; 278 u64 lblock, dblock;
@@ -291,8 +291,7 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
291 return 0; 291 return 0;
292 292
293 if (gfs2_is_stuffed(ip)) 293 if (gfs2_is_stuffed(ip))
294 return gfs2_dir_read_stuffed(ip, buf, (unsigned int)offset, 294 return gfs2_dir_read_stuffed(ip, buf, offset, size);
295 size);
296 295
297 if (gfs2_assert_warn(sdp, gfs2_is_jdata(ip))) 296 if (gfs2_assert_warn(sdp, gfs2_is_jdata(ip)))
298 return -EINVAL; 297 return -EINVAL;
@@ -313,34 +312,31 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
313 new = 0; 312 new = 0;
314 error = gfs2_extent_map(&ip->i_inode, lblock, &new, 313 error = gfs2_extent_map(&ip->i_inode, lblock, &new,
315 &dblock, &extlen); 314 &dblock, &extlen);
316 if (error) 315 if (error || !dblock)
317 goto fail; 316 goto fail;
317 BUG_ON(extlen < 1);
318 if (!ra)
319 extlen = 1;
320 bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
318 } 321 }
319 322 if (!bh) {
320 if (extlen > 1) 323 error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, &bh);
321 gfs2_meta_ra(ip->i_gl, dblock, extlen);
322
323 if (dblock) {
324 if (new)
325 error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
326 else
327 error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
328 if (error) 324 if (error)
329 goto fail; 325 goto fail;
330 dblock++; 326 }
331 extlen--; 327 error = gfs2_metatype_check(sdp, bh, GFS2_METATYPE_JD);
332 } else 328 if (error) {
333 bh = NULL; 329 brelse(bh);
334 330 goto fail;
331 }
332 dblock++;
333 extlen--;
335 memcpy(buf, bh->b_data + o, amount); 334 memcpy(buf, bh->b_data + o, amount);
336 brelse(bh); 335 brelse(bh);
337 if (error) 336 bh = NULL;
338 goto fail;
339
340 buf += amount; 337 buf += amount;
341 copied += amount; 338 copied += amount;
342 lblock++; 339 lblock++;
343
344 o = sizeof(struct gfs2_meta_header); 340 o = sizeof(struct gfs2_meta_header);
345 } 341 }
346 342
@@ -701,7 +697,7 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
701{ 697{
702 int error; 698 int error;
703 699
704 error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_START | DIO_WAIT, bhp); 700 error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, bhp);
705 if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) { 701 if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) {
706 /* printk(KERN_INFO "block num=%llu\n", leaf_no); */ 702 /* printk(KERN_INFO "block num=%llu\n", leaf_no); */
707 error = -EIO; 703 error = -EIO;
@@ -727,7 +723,7 @@ static int get_leaf_nr(struct gfs2_inode *dip, u32 index,
727 723
728 error = gfs2_dir_read_data(dip, (char *)&leaf_no, 724 error = gfs2_dir_read_data(dip, (char *)&leaf_no,
729 index * sizeof(u64), 725 index * sizeof(u64),
730 sizeof(u64)); 726 sizeof(u64), 0);
731 if (error != sizeof(u64)) 727 if (error != sizeof(u64))
732 return (error < 0) ? error : -EIO; 728 return (error < 0) ? error : -EIO;
733 729
@@ -1095,7 +1091,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
1095 for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) { 1091 for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
1096 error = gfs2_dir_read_data(dip, (char *)buf, 1092 error = gfs2_dir_read_data(dip, (char *)buf,
1097 block * sdp->sd_hash_bsize, 1093 block * sdp->sd_hash_bsize,
1098 sdp->sd_hash_bsize); 1094 sdp->sd_hash_bsize, 1);
1099 if (error != sdp->sd_hash_bsize) { 1095 if (error != sdp->sd_hash_bsize) {
1100 if (error >= 0) 1096 if (error >= 0)
1101 error = -EIO; 1097 error = -EIO;
@@ -1375,7 +1371,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
1375 if (ht_offset_cur != ht_offset) { 1371 if (ht_offset_cur != ht_offset) {
1376 error = gfs2_dir_read_data(dip, (char *)lp, 1372 error = gfs2_dir_read_data(dip, (char *)lp,
1377 ht_offset * sizeof(u64), 1373 ht_offset * sizeof(u64),
1378 sdp->sd_hash_bsize); 1374 sdp->sd_hash_bsize, 1);
1379 if (error != sdp->sd_hash_bsize) { 1375 if (error != sdp->sd_hash_bsize) {
1380 if (error >= 0) 1376 if (error >= 0)
1381 error = -EIO; 1377 error = -EIO;
@@ -1745,7 +1741,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
1745 if (ht_offset_cur != ht_offset) { 1741 if (ht_offset_cur != ht_offset) {
1746 error = gfs2_dir_read_data(dip, (char *)lp, 1742 error = gfs2_dir_read_data(dip, (char *)lp,
1747 ht_offset * sizeof(u64), 1743 ht_offset * sizeof(u64),
1748 sdp->sd_hash_bsize); 1744 sdp->sd_hash_bsize, 1);
1749 if (error != sdp->sd_hash_bsize) { 1745 if (error != sdp->sd_hash_bsize) {
1750 if (error >= 0) 1746 if (error >= 0)
1751 error = -EIO; 1747 error = -EIO;