aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
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
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')
-rw-r--r--fs/gfs2/bmap.c4
-rw-r--r--fs/gfs2/dir.c56
-rw-r--r--fs/gfs2/eattr.c23
-rw-r--r--fs/gfs2/glops.c55
-rw-r--r--fs/gfs2/incore.h1
-rw-r--r--fs/gfs2/lops.c9
-rw-r--r--fs/gfs2/meta_io.c173
-rw-r--r--fs/gfs2/meta_io.h6
-rw-r--r--fs/gfs2/ops_address.c2
-rw-r--r--fs/gfs2/quota.c16
-rw-r--r--fs/gfs2/recovery.c3
-rw-r--r--fs/gfs2/rgrp.c5
12 files changed, 163 insertions, 190 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 19b9bfc10349..3fb9a26b6f58 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -448,6 +448,8 @@ static int gfs2_block_pointers(struct inode *inode, u64 lblock, int create,
448 u64 dblock = 0; 448 u64 dblock = 0;
449 int boundary; 449 int boundary;
450 450
451 BUG_ON(maxlen == 0);
452
451 if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip))) 453 if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
452 return 0; 454 return 0;
453 455
@@ -561,7 +563,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
561 BUG_ON(!new); 563 BUG_ON(!new);
562 564
563 bmap_lock(inode, create); 565 bmap_lock(inode, create);
564 ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp, *extlen); 566 ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp, 32);
565 bmap_unlock(inode, create); 567 bmap_unlock(inode, create);
566 *extlen = bh.b_size >> inode->i_blkbits; 568 *extlen = bh.b_size >> inode->i_blkbits;
567 *dblock = bh.b_blocknr; 569 *dblock = bh.b_blocknr;
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;
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index 698942ec7c99..bd5ca602f9f0 100644
--- a/fs/gfs2/eattr.c
+++ b/fs/gfs2/eattr.c
@@ -115,7 +115,7 @@ static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data)
115 u64 *eablk, *end; 115 u64 *eablk, *end;
116 int error; 116 int error;
117 117
118 error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_START | DIO_WAIT, &bh); 118 error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &bh);
119 if (error) 119 if (error)
120 return error; 120 return error;
121 121
@@ -139,7 +139,7 @@ static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data)
139 break; 139 break;
140 bn = be64_to_cpu(*eablk); 140 bn = be64_to_cpu(*eablk);
141 141
142 error = gfs2_meta_read(ip->i_gl, bn, DIO_START | DIO_WAIT, &eabh); 142 error = gfs2_meta_read(ip->i_gl, bn, DIO_WAIT, &eabh);
143 if (error) 143 if (error)
144 break; 144 break;
145 error = ea_foreach_i(ip, eabh, ea_call, data); 145 error = ea_foreach_i(ip, eabh, ea_call, data);
@@ -453,8 +453,8 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
453 return -ENOMEM; 453 return -ENOMEM;
454 454
455 for (x = 0; x < nptrs; x++) { 455 for (x = 0; x < nptrs; x++) {
456 error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 456 error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0,
457 DIO_START, bh + x); 457 bh + x);
458 if (error) { 458 if (error) {
459 while (x--) 459 while (x--)
460 brelse(bh[x]); 460 brelse(bh[x]);
@@ -464,7 +464,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
464 } 464 }
465 465
466 for (x = 0; x < nptrs; x++) { 466 for (x = 0; x < nptrs; x++) {
467 error = gfs2_meta_reread(sdp, bh[x], DIO_WAIT); 467 error = gfs2_meta_wait(sdp, bh[x]);
468 if (error) { 468 if (error) {
469 for (; x < nptrs; x++) 469 for (; x < nptrs; x++)
470 brelse(bh[x]); 470 brelse(bh[x]);
@@ -938,8 +938,8 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
938 if (ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT) { 938 if (ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT) {
939 u64 *end; 939 u64 *end;
940 940
941 error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, 941 error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT,
942 DIO_START | DIO_WAIT, &indbh); 942 &indbh);
943 if (error) 943 if (error)
944 return error; 944 return error;
945 945
@@ -1215,8 +1215,8 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
1215 goto out; 1215 goto out;
1216 1216
1217 for (x = 0; x < nptrs; x++) { 1217 for (x = 0; x < nptrs; x++) {
1218 error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 1218 error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0,
1219 DIO_START, bh + x); 1219 bh + x);
1220 if (error) { 1220 if (error) {
1221 while (x--) 1221 while (x--)
1222 brelse(bh[x]); 1222 brelse(bh[x]);
@@ -1226,7 +1226,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
1226 } 1226 }
1227 1227
1228 for (x = 0; x < nptrs; x++) { 1228 for (x = 0; x < nptrs; x++) {
1229 error = gfs2_meta_reread(sdp, bh[x], DIO_WAIT); 1229 error = gfs2_meta_wait(sdp, bh[x]);
1230 if (error) { 1230 if (error) {
1231 for (; x < nptrs; x++) 1231 for (; x < nptrs; x++)
1232 brelse(bh[x]); 1232 brelse(bh[x]);
@@ -1310,8 +1310,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
1310 1310
1311 memset(&rlist, 0, sizeof(struct gfs2_rgrp_list)); 1311 memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
1312 1312
1313 error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, 1313 error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &indbh);
1314 DIO_START | DIO_WAIT, &indbh);
1315 if (error) 1314 if (error)
1316 return error; 1315 return error;
1317 1316
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 9c046dbf4729..ef1492e2d445 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -77,32 +77,24 @@ static void gfs2_page_inval(struct gfs2_glock *gl)
77} 77}
78 78
79/** 79/**
80 * gfs2_page_sync - Sync the data pages (not metadata) associated with a glock 80 * gfs2_page_wait - Wait for writeback of data
81 * @gl: the glock 81 * @gl: the glock
82 * @flags: DIO_START | DIO_WAIT
83 * 82 *
84 * Syncs data (not metadata) for a regular file. 83 * Syncs data (not metadata) for a regular file.
85 * No-op for all other types. 84 * No-op for all other types.
86 */ 85 */
87 86
88static void gfs2_page_sync(struct gfs2_glock *gl, int flags) 87static void gfs2_page_wait(struct gfs2_glock *gl)
89{ 88{
90 struct gfs2_inode *ip; 89 struct gfs2_inode *ip = gl->gl_object;
91 struct inode *inode; 90 struct inode *inode = &ip->i_inode;
92 struct address_space *mapping; 91 struct address_space *mapping = inode->i_mapping;
93 int error = 0; 92 int error;
94 93
95 ip = gl->gl_object; 94 if (!S_ISREG(ip->i_di.di_mode))
96 inode = &ip->i_inode;
97 if (!ip || !S_ISREG(ip->i_di.di_mode))
98 return; 95 return;
99 96
100 mapping = inode->i_mapping; 97 error = filemap_fdatawait(mapping);
101
102 if (flags & DIO_START)
103 filemap_fdatawrite(mapping);
104 if (!error && (flags & DIO_WAIT))
105 error = filemap_fdatawait(mapping);
106 98
107 /* Put back any errors cleared by filemap_fdatawait() 99 /* Put back any errors cleared by filemap_fdatawait()
108 so they can be caught by someone who can pass them 100 so they can be caught by someone who can pass them
@@ -115,6 +107,18 @@ static void gfs2_page_sync(struct gfs2_glock *gl, int flags)
115 107
116} 108}
117 109
110static void gfs2_page_writeback(struct gfs2_glock *gl)
111{
112 struct gfs2_inode *ip = gl->gl_object;
113 struct inode *inode = &ip->i_inode;
114 struct address_space *mapping = inode->i_mapping;
115
116 if (!S_ISREG(ip->i_di.di_mode))
117 return;
118
119 filemap_fdatawrite(mapping);
120}
121
118/** 122/**
119 * meta_go_sync - sync out the metadata for this glock 123 * meta_go_sync - sync out the metadata for this glock
120 * @gl: the glock 124 * @gl: the glock
@@ -132,7 +136,7 @@ static void meta_go_sync(struct gfs2_glock *gl, int flags)
132 136
133 if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) { 137 if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) {
134 gfs2_log_flush(gl->gl_sbd, gl); 138 gfs2_log_flush(gl->gl_sbd, gl);
135 gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT); 139 gfs2_meta_sync(gl);
136 if (flags & DIO_RELEASE) 140 if (flags & DIO_RELEASE)
137 gfs2_ail_empty_gl(gl); 141 gfs2_ail_empty_gl(gl);
138 } 142 }
@@ -185,8 +189,7 @@ static void inode_go_xmote_bh(struct gfs2_glock *gl)
185 189
186 if (gl->gl_state != LM_ST_UNLOCKED && 190 if (gl->gl_state != LM_ST_UNLOCKED &&
187 (!gh || !(gh->gh_flags & GL_SKIP))) { 191 (!gh || !(gh->gh_flags & GL_SKIP))) {
188 error = gfs2_meta_read(gl, gl->gl_name.ln_number, DIO_START, 192 error = gfs2_meta_read(gl, gl->gl_name.ln_number, 0, &bh);
189 &bh);
190 if (!error) 193 if (!error)
191 brelse(bh); 194 brelse(bh);
192 } 195 }
@@ -221,16 +224,18 @@ static void inode_go_sync(struct gfs2_glock *gl, int flags)
221 224
222 if (test_bit(GLF_DIRTY, &gl->gl_flags)) { 225 if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
223 if (meta && data) { 226 if (meta && data) {
224 gfs2_page_sync(gl, flags | DIO_START); 227 gfs2_page_writeback(gl);
225 gfs2_log_flush(gl->gl_sbd, gl); 228 gfs2_log_flush(gl->gl_sbd, gl);
226 gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT); 229 gfs2_meta_sync(gl);
227 gfs2_page_sync(gl, flags | DIO_WAIT); 230 gfs2_page_wait(gl);
228 clear_bit(GLF_DIRTY, &gl->gl_flags); 231 clear_bit(GLF_DIRTY, &gl->gl_flags);
229 } else if (meta) { 232 } else if (meta) {
230 gfs2_log_flush(gl->gl_sbd, gl); 233 gfs2_log_flush(gl->gl_sbd, gl);
231 gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT); 234 gfs2_meta_sync(gl);
232 } else if (data) 235 } else if (data) {
233 gfs2_page_sync(gl, flags | DIO_START | DIO_WAIT); 236 gfs2_page_writeback(gl);
237 gfs2_page_wait(gl);
238 }
234 if (flags & DIO_RELEASE) 239 if (flags & DIO_RELEASE)
235 gfs2_ail_empty_gl(gl); 240 gfs2_ail_empty_gl(gl);
236 } 241 }
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 7183dcf03563..118dc693d111 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -12,7 +12,6 @@
12 12
13#include <linux/fs.h> 13#include <linux/fs.h>
14 14
15#define DIO_START 0x00000008
16#define DIO_WAIT 0x00000010 15#define DIO_WAIT 0x00000010
17#define DIO_METADATA 0x00000020 16#define DIO_METADATA 0x00000020
18#define DIO_DATA 0x00000040 17#define DIO_DATA 0x00000040
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index e44d245d51d4..2a98cbe3290f 100644
--- a/fs/gfs2/lops.c
+++ b/fs/gfs2/lops.c
@@ -248,13 +248,13 @@ static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
248 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); 248 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
249 249
250 if (error) { 250 if (error) {
251 gfs2_meta_sync(ip->i_gl, DIO_START | DIO_WAIT); 251 gfs2_meta_sync(ip->i_gl);
252 return; 252 return;
253 } 253 }
254 if (pass != 1) 254 if (pass != 1)
255 return; 255 return;
256 256
257 gfs2_meta_sync(ip->i_gl, DIO_START | DIO_WAIT); 257 gfs2_meta_sync(ip->i_gl);
258 258
259 fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n", 259 fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",
260 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); 260 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
@@ -726,15 +726,14 @@ static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass)
726 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); 726 struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
727 727
728 if (error) { 728 if (error) {
729 gfs2_meta_sync(ip->i_gl, 729 gfs2_meta_sync(ip->i_gl);
730 DIO_START | DIO_WAIT);
731 return; 730 return;
732 } 731 }
733 if (pass != 1) 732 if (pass != 1)
734 return; 733 return;
735 734
736 /* data sync? */ 735 /* data sync? */
737 gfs2_meta_sync(ip->i_gl, DIO_START | DIO_WAIT); 736 gfs2_meta_sync(ip->i_gl);
738 737
739 fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n", 738 fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n",
740 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks); 739 jd->jd_jid, sdp->sd_replayed_blocks, sdp->sd_found_blocks);
diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c
index 6b52aacb0736..d3708af0a4d1 100644
--- a/fs/gfs2/meta_io.c
+++ b/fs/gfs2/meta_io.c
@@ -273,19 +273,16 @@ void gfs2_meta_inval(struct gfs2_glock *gl)
273/** 273/**
274 * gfs2_meta_sync - Sync all buffers associated with a glock 274 * gfs2_meta_sync - Sync all buffers associated with a glock
275 * @gl: The glock 275 * @gl: The glock
276 * @flags: DIO_START | DIO_WAIT
277 * 276 *
278 */ 277 */
279 278
280void gfs2_meta_sync(struct gfs2_glock *gl, int flags) 279void gfs2_meta_sync(struct gfs2_glock *gl)
281{ 280{
282 struct address_space *mapping = gl->gl_aspace->i_mapping; 281 struct address_space *mapping = gl->gl_aspace->i_mapping;
283 int error = 0; 282 int error;
284 283
285 if (flags & DIO_START) 284 filemap_fdatawrite(mapping);
286 filemap_fdatawrite(mapping); 285 error = filemap_fdatawait(mapping);
287 if (!error && (flags & DIO_WAIT))
288 error = filemap_fdatawait(mapping);
289 286
290 if (error) 287 if (error)
291 gfs2_io_error(gl->gl_sbd); 288 gfs2_io_error(gl->gl_sbd);
@@ -377,7 +374,7 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
377 * gfs2_meta_read - Read a block from disk 374 * gfs2_meta_read - Read a block from disk
378 * @gl: The glock covering the block 375 * @gl: The glock covering the block
379 * @blkno: The block number 376 * @blkno: The block number
380 * @flags: flags to gfs2_dreread() 377 * @flags: flags
381 * @bhp: the place where the buffer is returned (NULL on failure) 378 * @bhp: the place where the buffer is returned (NULL on failure)
382 * 379 *
383 * Returns: errno 380 * Returns: errno
@@ -386,45 +383,43 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
386int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, 383int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
387 struct buffer_head **bhp) 384 struct buffer_head **bhp)
388{ 385{
389 int error;
390
391 *bhp = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE); 386 *bhp = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE);
392 error = gfs2_meta_reread(gl->gl_sbd, *bhp, flags); 387 if (!buffer_uptodate(*bhp))
393 if (error) 388 ll_rw_block(READ, 1, bhp);
394 brelse(*bhp); 389 if (flags & DIO_WAIT) {
390 int error = gfs2_meta_wait(gl->gl_sbd, *bhp);
391 if (error) {
392 brelse(*bhp);
393 return error;
394 }
395 }
395 396
396 return error; 397 return 0;
397} 398}
398 399
399/** 400/**
400 * gfs2_meta_reread - Reread a block from disk 401 * gfs2_meta_wait - Reread a block from disk
401 * @sdp: the filesystem 402 * @sdp: the filesystem
402 * @bh: The block to read 403 * @bh: The block to wait for
403 * @flags: Flags that control the read
404 * 404 *
405 * Returns: errno 405 * Returns: errno
406 */ 406 */
407 407
408int gfs2_meta_reread(struct gfs2_sbd *sdp, struct buffer_head *bh, int flags) 408int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)
409{ 409{
410 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) 410 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
411 return -EIO; 411 return -EIO;
412 412
413 if ((flags & DIO_START) && !buffer_uptodate(bh)) 413 wait_on_buffer(bh);
414 ll_rw_block(READ, 1, &bh);
415
416 if (flags & DIO_WAIT) {
417 wait_on_buffer(bh);
418 414
419 if (!buffer_uptodate(bh)) { 415 if (!buffer_uptodate(bh)) {
420 struct gfs2_trans *tr = current->journal_info; 416 struct gfs2_trans *tr = current->journal_info;
421 if (tr && tr->tr_touched) 417 if (tr && tr->tr_touched)
422 gfs2_io_error_bh(sdp, bh); 418 gfs2_io_error_bh(sdp, bh);
423 return -EIO; 419 return -EIO;
424 }
425 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
426 return -EIO;
427 } 420 }
421 if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
422 return -EIO;
428 423
429 return 0; 424 return 0;
430} 425}
@@ -635,67 +630,57 @@ void gfs2_meta_cache_flush(struct gfs2_inode *ip)
635int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num, 630int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
636 int new, struct buffer_head **bhp) 631 int new, struct buffer_head **bhp)
637{ 632{
638 struct buffer_head *bh, **bh_slot = ip->i_cache + height; 633 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
639 int error; 634 struct gfs2_glock *gl = ip->i_gl;
635 struct buffer_head *bh = NULL, **bh_slot = ip->i_cache + height;
636 int in_cache = 0;
640 637
641 spin_lock(&ip->i_spin); 638 spin_lock(&ip->i_spin);
642 bh = *bh_slot; 639 if (*bh_slot && (*bh_slot)->b_blocknr == num) {
643 if (bh) { 640 bh = *bh_slot;
644 if (bh->b_blocknr == num) 641 get_bh(bh);
645 get_bh(bh); 642 in_cache = 1;
646 else
647 bh = NULL;
648 } 643 }
649 spin_unlock(&ip->i_spin); 644 spin_unlock(&ip->i_spin);
650 645
651 if (bh) { 646 if (!bh)
652 if (new) 647 bh = getbuf(gl->gl_sbd, gl->gl_aspace, num, CREATE);
653 meta_prep_new(bh);
654 else {
655 error = gfs2_meta_reread(GFS2_SB(&ip->i_inode), bh,
656 DIO_START | DIO_WAIT);
657 if (error) {
658 brelse(bh);
659 return error;
660 }
661 }
662 } else {
663 if (new)
664 bh = gfs2_meta_new(ip->i_gl, num);
665 else {
666 error = gfs2_meta_read(ip->i_gl, num,
667 DIO_START | DIO_WAIT, &bh);
668 if (error)
669 return error;
670 }
671 648
672 spin_lock(&ip->i_spin); 649 if (!bh)
673 if (*bh_slot != bh) { 650 return -ENOBUFS;
674 brelse(*bh_slot);
675 *bh_slot = bh;
676 get_bh(bh);
677 }
678 spin_unlock(&ip->i_spin);
679 }
680 651
681 if (new) { 652 if (new) {
682 if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), height)) { 653 if (gfs2_assert_warn(sdp, height))
683 brelse(bh); 654 goto err;
684 return -EIO; 655 meta_prep_new(bh);
685 }
686 gfs2_trans_add_bh(ip->i_gl, bh, 1); 656 gfs2_trans_add_bh(ip->i_gl, bh, 1);
687 gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); 657 gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
688 gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header)); 658 gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
659 } else {
660 u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI;
661 if (!buffer_uptodate(bh)) {
662 ll_rw_block(READ, 1, &bh);
663 if (gfs2_meta_wait(sdp, bh))
664 goto err;
665 }
666 if (gfs2_metatype_check(sdp, bh, mtype))
667 goto err;
668 }
689 669
690 } else if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, 670 if (!in_cache) {
691 (height) ? GFS2_METATYPE_IN : GFS2_METATYPE_DI)) { 671 spin_lock(&ip->i_spin);
692 brelse(bh); 672 if (*bh_slot)
693 return -EIO; 673 brelse(*bh_slot);
674 *bh_slot = bh;
675 get_bh(bh);
676 spin_unlock(&ip->i_spin);
694 } 677 }
695 678
696 *bhp = bh; 679 *bhp = bh;
697
698 return 0; 680 return 0;
681err:
682 brelse(bh);
683 return -EIO;
699} 684}
700 685
701/** 686/**
@@ -704,19 +689,21 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
704 * @dblock: the starting disk block 689 * @dblock: the starting disk block
705 * @extlen: the number of blocks in the extent 690 * @extlen: the number of blocks in the extent
706 * 691 *
692 * returns: the first buffer in the extent
707 */ 693 */
708 694
709void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) 695struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
710{ 696{
711 struct gfs2_sbd *sdp = gl->gl_sbd; 697 struct gfs2_sbd *sdp = gl->gl_sbd;
712 struct inode *aspace = gl->gl_aspace; 698 struct inode *aspace = gl->gl_aspace;
713 struct buffer_head *first_bh, *bh; 699 struct buffer_head *first_bh, *bh;
714 u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >> 700 u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >>
715 sdp->sd_sb.sb_bsize_shift; 701 sdp->sd_sb.sb_bsize_shift;
716 int error;
717 702
718 if (!extlen || !max_ra) 703 BUG_ON(!extlen);
719 return; 704
705 if (max_ra < 1)
706 max_ra = 1;
720 if (extlen > max_ra) 707 if (extlen > max_ra)
721 extlen = max_ra; 708 extlen = max_ra;
722 709
@@ -724,11 +711,8 @@ void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
724 711
725 if (buffer_uptodate(first_bh)) 712 if (buffer_uptodate(first_bh))
726 goto out; 713 goto out;
727 if (!buffer_locked(first_bh)) { 714 if (!buffer_locked(first_bh))
728 error = gfs2_meta_reread(sdp, first_bh, DIO_START); 715 ll_rw_block(READ, 1, &first_bh);
729 if (error)
730 goto out;
731 }
732 716
733 dblock++; 717 dblock++;
734 extlen--; 718 extlen--;
@@ -736,23 +720,18 @@ void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
736 while (extlen) { 720 while (extlen) {
737 bh = getbuf(sdp, aspace, dblock, CREATE); 721 bh = getbuf(sdp, aspace, dblock, CREATE);
738 722
739 if (!buffer_uptodate(bh) && !buffer_locked(bh)) { 723 if (!buffer_uptodate(bh) && !buffer_locked(bh))
740 error = gfs2_meta_reread(sdp, bh, DIO_START); 724 ll_rw_block(READA, 1, &bh);
741 brelse(bh); 725 brelse(bh);
742 if (error)
743 goto out;
744 } else
745 brelse(bh);
746
747 dblock++; 726 dblock++;
748 extlen--; 727 extlen--;
749 728 if (!buffer_locked(first_bh) && buffer_uptodate(first_bh))
750 if (buffer_uptodate(first_bh)) 729 goto out;
751 break;
752 } 730 }
753 731
732 wait_on_buffer(first_bh);
754out: 733out:
755 brelse(first_bh); 734 return first_bh;
756} 735}
757 736
758/** 737/**
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index 086a472df3f1..3323e6d0ed8f 100644
--- a/fs/gfs2/meta_io.h
+++ b/fs/gfs2/meta_io.h
@@ -46,12 +46,12 @@ void gfs2_ail2_empty_one(struct gfs2_sbd *sdp, struct gfs2_ail *ai);
46void gfs2_ail_empty_gl(struct gfs2_glock *gl); 46void gfs2_ail_empty_gl(struct gfs2_glock *gl);
47 47
48void gfs2_meta_inval(struct gfs2_glock *gl); 48void gfs2_meta_inval(struct gfs2_glock *gl);
49void gfs2_meta_sync(struct gfs2_glock *gl, int flags); 49void gfs2_meta_sync(struct gfs2_glock *gl);
50 50
51struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno); 51struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
52int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, 52int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno,
53 int flags, struct buffer_head **bhp); 53 int flags, struct buffer_head **bhp);
54int gfs2_meta_reread(struct gfs2_sbd *sdp, struct buffer_head *bh, int flags); 54int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
55 55
56void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh, 56void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
57 int meta); 57 int meta);
@@ -71,7 +71,7 @@ static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
71 return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp); 71 return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp);
72} 72}
73 73
74void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen); 74struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
75void gfs2_meta_syncfs(struct gfs2_sbd *sdp); 75void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
76 76
77#endif /* __DIO_DOT_H__ */ 77#endif /* __DIO_DOT_H__ */
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 3f9da7ce5dd9..8b18e974fa4d 100644
--- a/fs/gfs2/ops_address.c
+++ b/fs/gfs2/ops_address.c
@@ -65,7 +65,7 @@ static void gfs2_page_add_databufs(struct gfs2_inode *ip, struct page *page,
65int gfs2_get_block(struct inode *inode, sector_t lblock, 65int gfs2_get_block(struct inode *inode, sector_t lblock,
66 struct buffer_head *bh_result, int create) 66 struct buffer_head *bh_result, int create)
67{ 67{
68 return gfs2_block_map(inode, lblock, create, bh_result, 4); 68 return gfs2_block_map(inode, lblock, create, bh_result, 32);
69} 69}
70 70
71/** 71/**
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c5eb6c646177..da46e14388f4 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -265,7 +265,7 @@ static int bh_get(struct gfs2_quota_data *qd)
265 error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map, 1); 265 error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map, 1);
266 if (error) 266 if (error)
267 goto fail; 267 goto fail;
268 error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_START | DIO_WAIT, &bh); 268 error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh);
269 if (error) 269 if (error)
270 goto fail; 270 goto fail;
271 error = -EIO; 271 error = -EIO;
@@ -1059,8 +1059,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
1059 u32 extlen = 0; 1059 u32 extlen = 0;
1060 int error; 1060 int error;
1061 1061
1062 if (!ip->i_di.di_size || 1062 if (!ip->i_di.di_size || ip->i_di.di_size > (64 << 20) ||
1063 ip->i_di.di_size > (64 << 20) ||
1064 ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1)) { 1063 ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1)) {
1065 gfs2_consist_inode(ip); 1064 gfs2_consist_inode(ip);
1066 return -EIO; 1065 return -EIO;
@@ -1091,19 +1090,16 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
1091 if (error) 1090 if (error)
1092 goto fail; 1091 goto fail;
1093 } 1092 }
1094 gfs2_meta_ra(ip->i_gl, dblock, extlen);
1095 error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT,
1096 &bh);
1097 if (error)
1098 goto fail;
1099 error = -EIO; 1093 error = -EIO;
1094 bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
1095 if (!bh)
1096 goto fail;
1100 if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_QC)) { 1097 if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_QC)) {
1101 brelse(bh); 1098 brelse(bh);
1102 goto fail; 1099 goto fail;
1103 } 1100 }
1104 1101
1105 for (y = 0; 1102 for (y = 0; y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots;
1106 y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots;
1107 y++, slot++) { 1103 y++, slot++) {
1108 struct gfs2_quota_change qc; 1104 struct gfs2_quota_change qc;
1109 struct gfs2_quota_data *qd; 1105 struct gfs2_quota_data *qd;
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 518f9128137e..4d4ea7e66edc 100644
--- a/fs/gfs2/recovery.c
+++ b/fs/gfs2/recovery.c
@@ -47,8 +47,7 @@ int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk,
47 return -EIO; 47 return -EIO;
48 } 48 }
49 49
50 gfs2_meta_ra(gl, dblock, extlen); 50 *bh = gfs2_meta_ra(gl, dblock, extlen);
51 error = gfs2_meta_read(gl, dblock, DIO_START | DIO_WAIT, bh);
52 51
53 return error; 52 return error;
54} 53}
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 113b4ace6893..5f8e225c5497 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -575,15 +575,14 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
575 575
576 for (x = 0; x < length; x++) { 576 for (x = 0; x < length; x++) {
577 bi = rgd->rd_bits + x; 577 bi = rgd->rd_bits + x;
578 error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, DIO_START, 578 error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh);
579 &bi->bi_bh);
580 if (error) 579 if (error)
581 goto fail; 580 goto fail;
582 } 581 }
583 582
584 for (y = length; y--;) { 583 for (y = length; y--;) {
585 bi = rgd->rd_bits + y; 584 bi = rgd->rd_bits + y;
586 error = gfs2_meta_reread(sdp, bi->bi_bh, DIO_WAIT); 585 error = gfs2_meta_wait(sdp, bi->bi_bh);
587 if (error) 586 if (error)
588 goto fail; 587 goto fail;
589 if (gfs2_metatype_check(sdp, bi->bi_bh, y ? GFS2_METATYPE_RB : 588 if (gfs2_metatype_check(sdp, bi->bi_bh, y ? GFS2_METATYPE_RB :