Skip to content

Commit

Permalink
[GFS2] Tidy up meta_io code
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
swhiteho committed Sep 21, 2006
1 parent 91fa479 commit 7276b3b
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 190 deletions.
4 changes: 3 additions & 1 deletion fs/gfs2/bmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
56 changes: 26 additions & 30 deletions fs/gfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down Expand Up @@ -246,7 +246,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf,
}

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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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);
}

Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
23 changes: 11 additions & 12 deletions fs/gfs2/eattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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);
Expand Down Expand Up @@ -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]);
Expand All @@ -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]);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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]);
Expand All @@ -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]);
Expand Down Expand Up @@ -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;

Expand Down
55 changes: 30 additions & 25 deletions fs/gfs2/glops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
1 change: 0 additions & 1 deletion fs/gfs2/incore.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

#include <linux/fs.h>

#define DIO_START 0x00000008
#define DIO_WAIT 0x00000010
#define DIO_METADATA 0x00000020
#define DIO_DATA 0x00000040
Expand Down
9 changes: 4 additions & 5 deletions fs/gfs2/lops.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
Loading

0 comments on commit 7276b3b

Please sign in to comment.