Commit a22305cc authored by Joel Becker's avatar Joel Becker Committed by Mark Fasheh

ocfs2: Wrap dirblock reads in a dedicated function.

We have ocfs2_bread() as a vestige of the original ext-based dir code.
It's only used by directories, though.  Turn it into
ocfs2_read_dir_block(), with a prototype matching the other metadata
read functions.  It's set up to validate dirblocks when the time comes.
Signed-off-by: default avatarJoel Becker <joel.becker@oracle.com>
Signed-off-by: default avatarMark Fasheh <mfasheh@suse.com>
parent 5e96581a
...@@ -82,49 +82,6 @@ static int ocfs2_do_extend_dir(struct super_block *sb, ...@@ -82,49 +82,6 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
struct ocfs2_alloc_context *meta_ac, struct ocfs2_alloc_context *meta_ac,
struct buffer_head **new_bh); struct buffer_head **new_bh);
static struct buffer_head *ocfs2_bread(struct inode *inode,
int block, int *err, int reada)
{
struct buffer_head *bh = NULL;
int tmperr;
u64 p_blkno;
int readflags = 0;
if (reada)
readflags |= OCFS2_BH_READAHEAD;
if (((u64)block << inode->i_sb->s_blocksize_bits) >=
i_size_read(inode)) {
BUG_ON(!reada);
return NULL;
}
down_read(&OCFS2_I(inode)->ip_alloc_sem);
tmperr = ocfs2_extent_map_get_blocks(inode, block, &p_blkno, NULL,
NULL);
up_read(&OCFS2_I(inode)->ip_alloc_sem);
if (tmperr < 0) {
mlog_errno(tmperr);
goto fail;
}
tmperr = ocfs2_read_blocks(inode, p_blkno, 1, &bh, readflags);
if (tmperr < 0)
goto fail;
tmperr = 0;
*err = 0;
return bh;
fail:
brelse(bh);
bh = NULL;
*err = -EIO;
return NULL;
}
/* /*
* bh passed here can be an inode block or a dir data block, depending * bh passed here can be an inode block or a dir data block, depending
* on the inode inline data flag. * on the inode inline data flag.
...@@ -250,6 +207,76 @@ out: ...@@ -250,6 +207,76 @@ out:
return NULL; return NULL;
} }
static int ocfs2_validate_dir_block(struct super_block *sb,
struct buffer_head *bh)
{
/*
* Nothing yet. We don't validate dirents here, that's handled
* in-place when the code walks them.
*/
return 0;
}
/*
* This function forces all errors to -EIO for consistency with its
* predecessor, ocfs2_bread(). We haven't audited what returning the
* real error codes would do to callers. We log the real codes with
* mlog_errno() before we squash them.
*/
static int ocfs2_read_dir_block(struct inode *inode, u64 v_block,
struct buffer_head **bh, int flags)
{
int rc = 0;
struct buffer_head *tmp = *bh;
u64 p_blkno;
if (((u64)v_block << inode->i_sb->s_blocksize_bits) >=
i_size_read(inode)) {
BUG_ON(!(flags & OCFS2_BH_READAHEAD));
goto out;
}
down_read(&OCFS2_I(inode)->ip_alloc_sem);
rc = ocfs2_extent_map_get_blocks(inode, v_block, &p_blkno, NULL,
NULL);
up_read(&OCFS2_I(inode)->ip_alloc_sem);
if (rc) {
mlog_errno(rc);
goto out;
}
if (!p_blkno) {
rc = -EIO;
mlog(ML_ERROR,
"Directory #%llu contains a hole at offset %llu\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno,
(unsigned long long)v_block << inode->i_sb->s_blocksize_bits);
goto out;
}
rc = ocfs2_read_blocks(inode, p_blkno, 1, &tmp, flags);
if (rc) {
mlog_errno(rc);
goto out;
}
if (!(flags & OCFS2_BH_READAHEAD)) {
rc = ocfs2_validate_dir_block(inode->i_sb, tmp);
if (rc) {
brelse(tmp);
goto out;
}
}
/* If ocfs2_read_blocks() got us a new bh, pass it up. */
if (!*bh)
*bh = tmp;
out:
return rc ? -EIO : 0;
}
static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen, static struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
struct inode *dir, struct inode *dir,
struct ocfs2_dir_entry **res_dir) struct ocfs2_dir_entry **res_dir)
...@@ -296,15 +323,17 @@ restart: ...@@ -296,15 +323,17 @@ restart:
} }
num++; num++;
bh = ocfs2_bread(dir, b++, &err, 1); bh = NULL;
err = ocfs2_read_dir_block(dir, b++, &bh,
OCFS2_BH_READAHEAD);
bh_use[ra_max] = bh; bh_use[ra_max] = bh;
} }
} }
if ((bh = bh_use[ra_ptr++]) == NULL) if ((bh = bh_use[ra_ptr++]) == NULL)
goto next; goto next;
if (ocfs2_read_block(dir, block, &bh)) { if (ocfs2_read_dir_block(dir, block, &bh, 0)) {
/* read error, skip block & hope for the best. /* read error, skip block & hope for the best.
* ocfs2_read_block() has released the bh. */ * ocfs2_read_dir_block() has released the bh. */
ocfs2_error(dir->i_sb, "reading directory %llu, " ocfs2_error(dir->i_sb, "reading directory %llu, "
"offset %lu\n", "offset %lu\n",
(unsigned long long)OCFS2_I(dir)->ip_blkno, (unsigned long long)OCFS2_I(dir)->ip_blkno,
...@@ -724,7 +753,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, ...@@ -724,7 +753,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
int i, stored; int i, stored;
struct buffer_head * bh, * tmp; struct buffer_head * bh, * tmp;
struct ocfs2_dir_entry * de; struct ocfs2_dir_entry * de;
int err;
struct super_block * sb = inode->i_sb; struct super_block * sb = inode->i_sb;
unsigned int ra_sectors = 16; unsigned int ra_sectors = 16;
...@@ -735,12 +763,8 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, ...@@ -735,12 +763,8 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
while (!error && !stored && *f_pos < i_size_read(inode)) { while (!error && !stored && *f_pos < i_size_read(inode)) {
blk = (*f_pos) >> sb->s_blocksize_bits; blk = (*f_pos) >> sb->s_blocksize_bits;
bh = ocfs2_bread(inode, blk, &err, 0); if (ocfs2_read_dir_block(inode, blk, &bh, 0)) {
if (!bh) { /* Skip the corrupt dirblock and keep trying */
mlog(ML_ERROR,
"directory #%llu contains a hole at offset %lld\n",
(unsigned long long)OCFS2_I(inode)->ip_blkno,
*f_pos);
*f_pos += sb->s_blocksize - offset; *f_pos += sb->s_blocksize - offset;
continue; continue;
} }
...@@ -754,8 +778,10 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, ...@@ -754,8 +778,10 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
|| (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) { || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) {
for (i = ra_sectors >> (sb->s_blocksize_bits - 9); for (i = ra_sectors >> (sb->s_blocksize_bits - 9);
i > 0; i--) { i > 0; i--) {
tmp = ocfs2_bread(inode, ++blk, &err, 1); tmp = NULL;
brelse(tmp); if (!ocfs2_read_dir_block(inode, ++blk, &tmp,
OCFS2_BH_READAHEAD))
brelse(tmp);
} }
last_ra_blk = blk; last_ra_blk = blk;
ra_sectors = 8; ra_sectors = 8;
...@@ -828,6 +854,7 @@ revalidate: ...@@ -828,6 +854,7 @@ revalidate:
} }
offset = 0; offset = 0;
brelse(bh); brelse(bh);
bh = NULL;
} }
stored = 0; stored = 0;
...@@ -1680,8 +1707,8 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name, ...@@ -1680,8 +1707,8 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
int status; int status;
bh = ocfs2_bread(dir, 0, &status, 0); status = ocfs2_read_dir_block(dir, 0, &bh, 0);
if (!bh) { if (status) {
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
} }
...@@ -1702,11 +1729,10 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name, ...@@ -1702,11 +1729,10 @@ static int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
status = -ENOSPC; status = -ENOSPC;
goto bail; goto bail;
} }
bh = ocfs2_bread(dir, status = ocfs2_read_dir_block(dir,
offset >> sb->s_blocksize_bits, offset >> sb->s_blocksize_bits,
&status, &bh, 0);
0); if (status) {
if (!bh) {
mlog_errno(status); mlog_errno(status);
goto bail; goto bail;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment