summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-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 19b9bfc1034..3fb9a26b6f5 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,
u64 dblock = 0;
int boundary;
+ BUG_ON(maxlen == 0);
+
if (gfs2_assert_warn(sdp, !gfs2_is_stuffed(ip)))
return 0;
@@ -561,7 +563,7 @@ int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, u64 *dblock, unsi
BUG_ON(!new);
bmap_lock(inode, create);
- ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp, *extlen);
+ ret = gfs2_block_pointers(inode, lblock, create, &bh, &mp, 32);
bmap_unlock(inode, create);
*extlen = bh.b_size >> inode->i_blkbits;
*dblock = bh.b_blocknr;
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index 73902868827..40e94ac0b93 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,
struct buffer_head *bh;
int error;
- error = gfs2_meta_read(ip->i_gl, block, DIO_START | DIO_WAIT, &bh);
+ error = gfs2_meta_read(ip->i_gl, block, DIO_WAIT, &bh);
if (error)
return error;
if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) {
@@ -246,7 +246,7 @@ fail:
}
static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, char *buf,
- unsigned int offset, unsigned int size)
+ u64 offset, unsigned int size)
{
struct buffer_head *dibh;
int error;
@@ -271,8 +271,8 @@ static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, char *buf,
*
* Returns: The amount of data actually copied or the error
*/
-static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
- u64 offset, unsigned int size)
+static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf, u64 offset,
+ unsigned int size, unsigned ra)
{
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
u64 lblock, dblock;
@@ -291,8 +291,7 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
return 0;
if (gfs2_is_stuffed(ip))
- return gfs2_dir_read_stuffed(ip, buf, (unsigned int)offset,
- size);
+ return gfs2_dir_read_stuffed(ip, buf, offset, size);
if (gfs2_assert_warn(sdp, gfs2_is_jdata(ip)))
return -EINVAL;
@@ -313,34 +312,31 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, char *buf,
new = 0;
error = gfs2_extent_map(&ip->i_inode, lblock, &new,
&dblock, &extlen);
- if (error)
+ if (error || !dblock)
goto fail;
+ BUG_ON(extlen < 1);
+ if (!ra)
+ extlen = 1;
+ bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
}
-
- if (extlen > 1)
- gfs2_meta_ra(ip->i_gl, dblock, extlen);
-
- if (dblock) {
- if (new)
- error = gfs2_dir_get_new_buffer(ip, dblock, &bh);
- else
- error = gfs2_dir_get_existing_buffer(ip, dblock, &bh);
+ if (!bh) {
+ error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, &bh);
if (error)
goto fail;
- dblock++;
- extlen--;
- } else
- bh = NULL;
-
+ }
+ error = gfs2_metatype_check(sdp, bh, GFS2_METATYPE_JD);
+ if (error) {
+ brelse(bh);
+ goto fail;
+ }
+ dblock++;
+ extlen--;
memcpy(buf, bh->b_data + o, amount);
brelse(bh);
- if (error)
- goto fail;
-
+ bh = NULL;
buf += amount;
copied += amount;
lblock++;
-
o = sizeof(struct gfs2_meta_header);
}
@@ -701,7 +697,7 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no,
{
int error;
- error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_START | DIO_WAIT, bhp);
+ error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, bhp);
if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) {
/* printk(KERN_INFO "block num=%llu\n", leaf_no); */
error = -EIO;
@@ -727,7 +723,7 @@ static int get_leaf_nr(struct gfs2_inode *dip, u32 index,
error = gfs2_dir_read_data(dip, (char *)&leaf_no,
index * sizeof(u64),
- sizeof(u64));
+ sizeof(u64), 0);
if (error != sizeof(u64))
return (error < 0) ? error : -EIO;
@@ -1095,7 +1091,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
for (block = dip->i_di.di_size >> sdp->sd_hash_bsize_shift; block--;) {
error = gfs2_dir_read_data(dip, (char *)buf,
block * sdp->sd_hash_bsize,
- sdp->sd_hash_bsize);
+ sdp->sd_hash_bsize, 1);
if (error != sdp->sd_hash_bsize) {
if (error >= 0)
error = -EIO;
@@ -1375,7 +1371,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
if (ht_offset_cur != ht_offset) {
error = gfs2_dir_read_data(dip, (char *)lp,
ht_offset * sizeof(u64),
- sdp->sd_hash_bsize);
+ sdp->sd_hash_bsize, 1);
if (error != sdp->sd_hash_bsize) {
if (error >= 0)
error = -EIO;
@@ -1745,7 +1741,7 @@ static int foreach_leaf(struct gfs2_inode *dip, leaf_call_t lc, void *data)
if (ht_offset_cur != ht_offset) {
error = gfs2_dir_read_data(dip, (char *)lp,
ht_offset * sizeof(u64),
- sdp->sd_hash_bsize);
+ sdp->sd_hash_bsize, 1);
if (error != sdp->sd_hash_bsize) {
if (error >= 0)
error = -EIO;
diff --git a/fs/gfs2/eattr.c b/fs/gfs2/eattr.c
index 698942ec7c9..bd5ca602f9f 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)
u64 *eablk, *end;
int error;
- error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_START | DIO_WAIT, &bh);
+ error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &bh);
if (error)
return error;
@@ -139,7 +139,7 @@ static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data)
break;
bn = be64_to_cpu(*eablk);
- error = gfs2_meta_read(ip->i_gl, bn, DIO_START | DIO_WAIT, &eabh);
+ error = gfs2_meta_read(ip->i_gl, bn, DIO_WAIT, &eabh);
if (error)
break;
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,
return -ENOMEM;
for (x = 0; x < nptrs; x++) {
- error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs),
- DIO_START, bh + x);
+ error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0,
+ bh + x);
if (error) {
while (x--)
brelse(bh[x]);
@@ -464,7 +464,7 @@ static int ea_get_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea,
}
for (x = 0; x < nptrs; x++) {
- error = gfs2_meta_reread(sdp, bh[x], DIO_WAIT);
+ error = gfs2_meta_wait(sdp, bh[x]);
if (error) {
for (; x < nptrs; x++)
brelse(bh[x]);
@@ -938,8 +938,8 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er,
if (ip->i_di.di_flags & GFS2_DIF_EA_INDIRECT) {
u64 *end;
- error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr,
- DIO_START | DIO_WAIT, &indbh);
+ error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT,
+ &indbh);
if (error)
return error;
@@ -1215,8 +1215,8 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
goto out;
for (x = 0; x < nptrs; x++) {
- error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs),
- DIO_START, bh + x);
+ error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0,
+ bh + x);
if (error) {
while (x--)
brelse(bh[x]);
@@ -1226,7 +1226,7 @@ static int ea_acl_chmod_unstuffed(struct gfs2_inode *ip,
}
for (x = 0; x < nptrs; x++) {
- error = gfs2_meta_reread(sdp, bh[x], DIO_WAIT);
+ error = gfs2_meta_wait(sdp, bh[x]);
if (error) {
for (; x < nptrs; x++)
brelse(bh[x]);
@@ -1310,8 +1310,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip)
memset(&rlist, 0, sizeof(struct gfs2_rgrp_list));
- error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr,
- DIO_START | DIO_WAIT, &indbh);
+ error = gfs2_meta_read(ip->i_gl, ip->i_di.di_eattr, DIO_WAIT, &indbh);
if (error)
return error;
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index 9c046dbf472..ef1492e2d44 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -77,32 +77,24 @@ static void gfs2_page_inval(struct gfs2_glock *gl)
}
/**
- * gfs2_page_sync - Sync the data pages (not metadata) associated with a glock
+ * gfs2_page_wait - Wait for writeback of data
* @gl: the glock
- * @flags: DIO_START | DIO_WAIT
*
* Syncs data (not metadata) for a regular file.
* No-op for all other types.
*/
-static void gfs2_page_sync(struct gfs2_glock *gl, int flags)
+static void gfs2_page_wait(struct gfs2_glock *gl)
{
- struct gfs2_inode *ip;
- struct inode *inode;
- struct address_space *mapping;
- int error = 0;
+ struct gfs2_inode *ip = gl->gl_object;
+ struct inode *inode = &ip->i_inode;
+ struct address_space *mapping = inode->i_mapping;
+ int error;
- ip = gl->gl_object;
- inode = &ip->i_inode;
- if (!ip || !S_ISREG(ip->i_di.di_mode))
+ if (!S_ISREG(ip->i_di.di_mode))
return;
- mapping = inode->i_mapping;
-
- if (flags & DIO_START)
- filemap_fdatawrite(mapping);
- if (!error && (flags & DIO_WAIT))
- error = filemap_fdatawait(mapping);
+ error = filemap_fdatawait(mapping);
/* Put back any errors cleared by filemap_fdatawait()
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)
}
+static void gfs2_page_writeback(struct gfs2_glock *gl)
+{
+ struct gfs2_inode *ip = gl->gl_object;
+ struct inode *inode = &ip->i_inode;
+ struct address_space *mapping = inode->i_mapping;
+
+ if (!S_ISREG(ip->i_di.di_mode))
+ return;
+
+ filemap_fdatawrite(mapping);
+}
+
/**
* meta_go_sync - sync out the metadata for this glock
* @gl: the glock
@@ -132,7 +136,7 @@ static void meta_go_sync(struct gfs2_glock *gl, int flags)
if (test_and_clear_bit(GLF_DIRTY, &gl->gl_flags)) {
gfs2_log_flush(gl->gl_sbd, gl);
- gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT);
+ gfs2_meta_sync(gl);
if (flags & DIO_RELEASE)
gfs2_ail_empty_gl(gl);
}
@@ -185,8 +189,7 @@ static void inode_go_xmote_bh(struct gfs2_glock *gl)
if (gl->gl_state != LM_ST_UNLOCKED &&
(!gh || !(gh->gh_flags & GL_SKIP))) {
- error = gfs2_meta_read(gl, gl->gl_name.ln_number, DIO_START,
- &bh);
+ error = gfs2_meta_read(gl, gl->gl_name.ln_number, 0, &bh);
if (!error)
brelse(bh);
}
@@ -221,16 +224,18 @@ static void inode_go_sync(struct gfs2_glock *gl, int flags)
if (test_bit(GLF_DIRTY, &gl->gl_flags)) {
if (meta && data) {
- gfs2_page_sync(gl, flags | DIO_START);
+ gfs2_page_writeback(gl);
gfs2_log_flush(gl->gl_sbd, gl);
- gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT);
- gfs2_page_sync(gl, flags | DIO_WAIT);
+ gfs2_meta_sync(gl);
+ gfs2_page_wait(gl);
clear_bit(GLF_DIRTY, &gl->gl_flags);
} else if (meta) {
gfs2_log_flush(gl->gl_sbd, gl);
- gfs2_meta_sync(gl, flags | DIO_START | DIO_WAIT);
- } else if (data)
- gfs2_page_sync(gl, flags | DIO_START | DIO_WAIT);
+ gfs2_meta_sync(gl);
+ } else if (data) {
+ gfs2_page_writeback(gl);
+ gfs2_page_wait(gl);
+ }
if (flags & DIO_RELEASE)
gfs2_ail_empty_gl(gl);
}
diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h
index 7183dcf0356..118dc693d11 100644
--- a/fs/gfs2/incore.h
+++ b/fs/gfs2/incore.h
@@ -12,7 +12,6 @@
#include <linux/fs.h>
-#define DIO_START 0x00000008
#define DIO_WAIT 0x00000010
#define DIO_METADATA 0x00000020
#define DIO_DATA 0x00000040
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c
index e44d245d51d..2a98cbe3290 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)
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (error) {
- gfs2_meta_sync(ip->i_gl, DIO_START | DIO_WAIT);
+ gfs2_meta_sync(ip->i_gl);
return;
}
if (pass != 1)
return;
- gfs2_meta_sync(ip->i_gl, DIO_START | DIO_WAIT);
+ gfs2_meta_sync(ip->i_gl);
fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n",
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)
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
if (error) {
- gfs2_meta_sync(ip->i_gl,
- DIO_START | DIO_WAIT);
+ gfs2_meta_sync(ip->i_gl);
return;
}
if (pass != 1)
return;
/* data sync? */
- gfs2_meta_sync(ip->i_gl, DIO_START | DIO_WAIT);
+ gfs2_meta_sync(ip->i_gl);
fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n",
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 6b52aacb073..d3708af0a4d 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)
/**
* gfs2_meta_sync - Sync all buffers associated with a glock
* @gl: The glock
- * @flags: DIO_START | DIO_WAIT
*
*/
-void gfs2_meta_sync(struct gfs2_glock *gl, int flags)
+void gfs2_meta_sync(struct gfs2_glock *gl)
{
struct address_space *mapping = gl->gl_aspace->i_mapping;
- int error = 0;
+ int error;
- if (flags & DIO_START)
- filemap_fdatawrite(mapping);
- if (!error && (flags & DIO_WAIT))
- error = filemap_fdatawait(mapping);
+ filemap_fdatawrite(mapping);
+ error = filemap_fdatawait(mapping);
if (error)
gfs2_io_error(gl->gl_sbd);
@@ -377,7 +374,7 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
* gfs2_meta_read - Read a block from disk
* @gl: The glock covering the block
* @blkno: The block number
- * @flags: flags to gfs2_dreread()
+ * @flags: flags
* @bhp: the place where the buffer is returned (NULL on failure)
*
* Returns: errno
@@ -386,45 +383,43 @@ struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno)
int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags,
struct buffer_head **bhp)
{
- int error;
-
*bhp = getbuf(gl->gl_sbd, gl->gl_aspace, blkno, CREATE);
- error = gfs2_meta_reread(gl->gl_sbd, *bhp, flags);
- if (error)
- brelse(*bhp);
+ if (!buffer_uptodate(*bhp))
+ ll_rw_block(READ, 1, bhp);
+ if (flags & DIO_WAIT) {
+ int error = gfs2_meta_wait(gl->gl_sbd, *bhp);
+ if (error) {
+ brelse(*bhp);
+ return error;
+ }
+ }
- return error;
+ return 0;
}
/**
- * gfs2_meta_reread - Reread a block from disk
+ * gfs2_meta_wait - Reread a block from disk
* @sdp: the filesystem
- * @bh: The block to read
- * @flags: Flags that control the read
+ * @bh: The block to wait for
*
* Returns: errno
*/
-int gfs2_meta_reread(struct gfs2_sbd *sdp, struct buffer_head *bh, int flags)
+int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh)
{
if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
return -EIO;
- if ((flags & DIO_START) && !buffer_uptodate(bh))
- ll_rw_block(READ, 1, &bh);
-
- if (flags & DIO_WAIT) {
- wait_on_buffer(bh);
+ wait_on_buffer(bh);
- if (!buffer_uptodate(bh)) {
- struct gfs2_trans *tr = current->journal_info;
- if (tr && tr->tr_touched)
- gfs2_io_error_bh(sdp, bh);
- return -EIO;
- }
- if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
- return -EIO;
+ if (!buffer_uptodate(bh)) {
+ struct gfs2_trans *tr = current->journal_info;
+ if (tr && tr->tr_touched)
+ gfs2_io_error_bh(sdp, bh);
+ return -EIO;
}
+ if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+ return -EIO;
return 0;
}
@@ -635,67 +630,57 @@ void gfs2_meta_cache_flush(struct gfs2_inode *ip)
int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
int new, struct buffer_head **bhp)
{
- struct buffer_head *bh, **bh_slot = ip->i_cache + height;
- int error;
+ struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
+ struct gfs2_glock *gl = ip->i_gl;
+ struct buffer_head *bh = NULL, **bh_slot = ip->i_cache + height;
+ int in_cache = 0;
spin_lock(&ip->i_spin);
- bh = *bh_slot;
- if (bh) {
- if (bh->b_blocknr == num)
- get_bh(bh);
- else
- bh = NULL;
+ if (*bh_slot && (*bh_slot)->b_blocknr == num) {
+ bh = *bh_slot;
+ get_bh(bh);
+ in_cache = 1;
}
spin_unlock(&ip->i_spin);
- if (bh) {
- if (new)
- meta_prep_new(bh);
- else {
- error = gfs2_meta_reread(GFS2_SB(&ip->i_inode), bh,
- DIO_START | DIO_WAIT);
- if (error) {
- brelse(bh);
- return error;
- }
- }
- } else {
- if (new)
- bh = gfs2_meta_new(ip->i_gl, num);
- else {
- error = gfs2_meta_read(ip->i_gl, num,
- DIO_START | DIO_WAIT, &bh);
- if (error)
- return error;
- }
+ if (!bh)
+ bh = getbuf(gl->gl_sbd, gl->gl_aspace, num, CREATE);
- spin_lock(&ip->i_spin);
- if (*bh_slot != bh) {
- brelse(*bh_slot);
- *bh_slot = bh;
- get_bh(bh);
- }
- spin_unlock(&ip->i_spin);
- }
+ if (!bh)
+ return -ENOBUFS;
if (new) {
- if (gfs2_assert_warn(GFS2_SB(&ip->i_inode), height)) {
- brelse(bh);
- return -EIO;
- }
+ if (gfs2_assert_warn(sdp, height))
+ goto err;
+ meta_prep_new(bh);
gfs2_trans_add_bh(ip->i_gl, bh, 1);
gfs2_metatype_set(bh, GFS2_METATYPE_IN, GFS2_FORMAT_IN);
gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header));
+ } else {
+ u32 mtype = height ? GFS2_METATYPE_IN : GFS2_METATYPE_DI;
+ if (!buffer_uptodate(bh)) {
+ ll_rw_block(READ, 1, &bh);
+ if (gfs2_meta_wait(sdp, bh))
+ goto err;
+ }
+ if (gfs2_metatype_check(sdp, bh, mtype))
+ goto err;
+ }
- } else if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh,
- (height) ? GFS2_METATYPE_IN : GFS2_METATYPE_DI)) {
- brelse(bh);
- return -EIO;
+ if (!in_cache) {
+ spin_lock(&ip->i_spin);
+ if (*bh_slot)
+ brelse(*bh_slot);
+ *bh_slot = bh;
+ get_bh(bh);
+ spin_unlock(&ip->i_spin);
}
*bhp = bh;
-
return 0;
+err:
+ brelse(bh);
+ return -EIO;
}
/**
@@ -704,19 +689,21 @@ int gfs2_meta_indirect_buffer(struct gfs2_inode *ip, int height, u64 num,
* @dblock: the starting disk block
* @extlen: the number of blocks in the extent
*
+ * returns: the first buffer in the extent
*/
-void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
+struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
{
struct gfs2_sbd *sdp = gl->gl_sbd;
struct inode *aspace = gl->gl_aspace;
struct buffer_head *first_bh, *bh;
u32 max_ra = gfs2_tune_get(sdp, gt_max_readahead) >>
sdp->sd_sb.sb_bsize_shift;
- int error;
- if (!extlen || !max_ra)
- return;
+ BUG_ON(!extlen);
+
+ if (max_ra < 1)
+ max_ra = 1;
if (extlen > max_ra)
extlen = max_ra;
@@ -724,11 +711,8 @@ void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
if (buffer_uptodate(first_bh))
goto out;
- if (!buffer_locked(first_bh)) {
- error = gfs2_meta_reread(sdp, first_bh, DIO_START);
- if (error)
- goto out;
- }
+ if (!buffer_locked(first_bh))
+ ll_rw_block(READ, 1, &first_bh);
dblock++;
extlen--;
@@ -736,23 +720,18 @@ void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen)
while (extlen) {
bh = getbuf(sdp, aspace, dblock, CREATE);
- if (!buffer_uptodate(bh) && !buffer_locked(bh)) {
- error = gfs2_meta_reread(sdp, bh, DIO_START);
- brelse(bh);
- if (error)
- goto out;
- } else
- brelse(bh);
-
+ if (!buffer_uptodate(bh) && !buffer_locked(bh))
+ ll_rw_block(READA, 1, &bh);
+ brelse(bh);
dblock++;
extlen--;
-
- if (buffer_uptodate(first_bh))
- break;
+ if (!buffer_locked(first_bh) && buffer_uptodate(first_bh))
+ goto out;
}
+ wait_on_buffer(first_bh);
out:
- brelse(first_bh);
+ return first_bh;
}
/**
diff --git a/fs/gfs2/meta_io.h b/fs/gfs2/meta_io.h
index 086a472df3f..3323e6d0ed8 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);
void gfs2_ail_empty_gl(struct gfs2_glock *gl);
void gfs2_meta_inval(struct gfs2_glock *gl);
-void gfs2_meta_sync(struct gfs2_glock *gl, int flags);
+void gfs2_meta_sync(struct gfs2_glock *gl);
struct buffer_head *gfs2_meta_new(struct gfs2_glock *gl, u64 blkno);
int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno,
int flags, struct buffer_head **bhp);
-int gfs2_meta_reread(struct gfs2_sbd *sdp, struct buffer_head *bh, int flags);
+int gfs2_meta_wait(struct gfs2_sbd *sdp, struct buffer_head *bh);
void gfs2_attach_bufdata(struct gfs2_glock *gl, struct buffer_head *bh,
int meta);
@@ -71,7 +71,7 @@ static inline int gfs2_meta_inode_buffer(struct gfs2_inode *ip,
return gfs2_meta_indirect_buffer(ip, 0, ip->i_num.no_addr, 0, bhp);
}
-void gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
+struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen);
void gfs2_meta_syncfs(struct gfs2_sbd *sdp);
#endif /* __DIO_DOT_H__ */
diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c
index 3f9da7ce5dd..8b18e974fa4 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,
int gfs2_get_block(struct inode *inode, sector_t lblock,
struct buffer_head *bh_result, int create)
{
- return gfs2_block_map(inode, lblock, create, bh_result, 4);
+ return gfs2_block_map(inode, lblock, create, bh_result, 32);
}
/**
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c5eb6c64617..da46e14388f 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -265,7 +265,7 @@ static int bh_get(struct gfs2_quota_data *qd)
error = gfs2_block_map(&ip->i_inode, block, 0, &bh_map, 1);
if (error)
goto fail;
- error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_START | DIO_WAIT, &bh);
+ error = gfs2_meta_read(ip->i_gl, bh_map.b_blocknr, DIO_WAIT, &bh);
if (error)
goto fail;
error = -EIO;
@@ -1059,8 +1059,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
u32 extlen = 0;
int error;
- if (!ip->i_di.di_size ||
- ip->i_di.di_size > (64 << 20) ||
+ if (!ip->i_di.di_size || ip->i_di.di_size > (64 << 20) ||
ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1)) {
gfs2_consist_inode(ip);
return -EIO;
@@ -1091,19 +1090,16 @@ int gfs2_quota_init(struct gfs2_sbd *sdp)
if (error)
goto fail;
}
- gfs2_meta_ra(ip->i_gl, dblock, extlen);
- error = gfs2_meta_read(ip->i_gl, dblock, DIO_START | DIO_WAIT,
- &bh);
- if (error)
- goto fail;
error = -EIO;
+ bh = gfs2_meta_ra(ip->i_gl, dblock, extlen);
+ if (!bh)
+ goto fail;
if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_QC)) {
brelse(bh);
goto fail;
}
- for (y = 0;
- y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots;
+ for (y = 0; y < sdp->sd_qc_per_block && slot < sdp->sd_quota_slots;
y++, slot++) {
struct gfs2_quota_change qc;
struct gfs2_quota_data *qd;
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c
index 518f9128137..4d4ea7e66ed 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,
return -EIO;
}
- gfs2_meta_ra(gl, dblock, extlen);
- error = gfs2_meta_read(gl, dblock, DIO_START | DIO_WAIT, bh);
+ *bh = gfs2_meta_ra(gl, dblock, extlen);
return error;
}
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 113b4ace689..5f8e225c549 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -575,15 +575,14 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd)
for (x = 0; x < length; x++) {
bi = rgd->rd_bits + x;
- error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, DIO_START,
- &bi->bi_bh);
+ error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh);
if (error)
goto fail;
}
for (y = length; y--;) {
bi = rgd->rd_bits + y;
- error = gfs2_meta_reread(sdp, bi->bi_bh, DIO_WAIT);
+ error = gfs2_meta_wait(sdp, bi->bi_bh);
if (error)
goto fail;
if (gfs2_metatype_check(sdp, bi->bi_bh, y ? GFS2_METATYPE_RB :