Commit 3704412b authored by Al Viro's avatar Al Viro

[readdir] convert ocfs2

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 2c6a2473
...@@ -1761,11 +1761,10 @@ int __ocfs2_add_entry(handle_t *handle, ...@@ -1761,11 +1761,10 @@ int __ocfs2_add_entry(handle_t *handle,
static int ocfs2_dir_foreach_blk_id(struct inode *inode, static int ocfs2_dir_foreach_blk_id(struct inode *inode,
u64 *f_version, u64 *f_version,
loff_t *f_pos, void *priv, struct dir_context *ctx)
filldir_t filldir, int *filldir_err)
{ {
int ret, i, filldir_ret; int ret, i;
unsigned long offset = *f_pos; unsigned long offset = ctx->pos;
struct buffer_head *di_bh = NULL; struct buffer_head *di_bh = NULL;
struct ocfs2_dinode *di; struct ocfs2_dinode *di;
struct ocfs2_inline_data *data; struct ocfs2_inline_data *data;
...@@ -1781,8 +1780,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode, ...@@ -1781,8 +1780,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
di = (struct ocfs2_dinode *)di_bh->b_data; di = (struct ocfs2_dinode *)di_bh->b_data;
data = &di->id2.i_data; data = &di->id2.i_data;
while (*f_pos < i_size_read(inode)) { while (ctx->pos < i_size_read(inode)) {
revalidate:
/* If the dir block has changed since the last call to /* If the dir block has changed since the last call to
* readdir(2), then we might be pointing to an invalid * readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the block * dirent right now. Scan from the start of the block
...@@ -1802,50 +1800,31 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode, ...@@ -1802,50 +1800,31 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
break; break;
i += le16_to_cpu(de->rec_len); i += le16_to_cpu(de->rec_len);
} }
*f_pos = offset = i; ctx->pos = offset = i;
*f_version = inode->i_version; *f_version = inode->i_version;
} }
de = (struct ocfs2_dir_entry *) (data->id_data + *f_pos); de = (struct ocfs2_dir_entry *) (data->id_data + ctx->pos);
if (!ocfs2_check_dir_entry(inode, de, di_bh, *f_pos)) { if (!ocfs2_check_dir_entry(inode, de, di_bh, ctx->pos)) {
/* On error, skip the f_pos to the end. */ /* On error, skip the f_pos to the end. */
*f_pos = i_size_read(inode); ctx->pos = i_size_read(inode);
goto out; break;
} }
offset += le16_to_cpu(de->rec_len); offset += le16_to_cpu(de->rec_len);
if (le64_to_cpu(de->inode)) { if (le64_to_cpu(de->inode)) {
/* We might block in the next section
* if the data destination is
* currently swapped out. So, use a
* version stamp to detect whether or
* not the directory has been modified
* during the copy operation.
*/
u64 version = *f_version;
unsigned char d_type = DT_UNKNOWN; unsigned char d_type = DT_UNKNOWN;
if (de->file_type < OCFS2_FT_MAX) if (de->file_type < OCFS2_FT_MAX)
d_type = ocfs2_filetype_table[de->file_type]; d_type = ocfs2_filetype_table[de->file_type];
filldir_ret = filldir(priv, de->name, if (!dir_emit(ctx, de->name, de->name_len,
de->name_len, le64_to_cpu(de->inode), d_type))
*f_pos, goto out;
le64_to_cpu(de->inode),
d_type);
if (filldir_ret) {
if (filldir_err)
*filldir_err = filldir_ret;
break;
}
if (version != *f_version)
goto revalidate;
} }
*f_pos += le16_to_cpu(de->rec_len); ctx->pos += le16_to_cpu(de->rec_len);
} }
out: out:
brelse(di_bh); brelse(di_bh);
return 0; return 0;
} }
...@@ -1855,27 +1834,26 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode, ...@@ -1855,27 +1834,26 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
*/ */
static int ocfs2_dir_foreach_blk_el(struct inode *inode, static int ocfs2_dir_foreach_blk_el(struct inode *inode,
u64 *f_version, u64 *f_version,
loff_t *f_pos, void *priv, struct dir_context *ctx,
filldir_t filldir, int *filldir_err) bool persist)
{ {
int error = 0;
unsigned long offset, blk, last_ra_blk = 0; unsigned long offset, blk, last_ra_blk = 0;
int i, stored; int i;
struct buffer_head * bh, * tmp; struct buffer_head * bh, * tmp;
struct ocfs2_dir_entry * de; struct ocfs2_dir_entry * de;
struct super_block * sb = inode->i_sb; struct super_block * sb = inode->i_sb;
unsigned int ra_sectors = 16; unsigned int ra_sectors = 16;
int stored = 0;
stored = 0;
bh = NULL; bh = NULL;
offset = (*f_pos) & (sb->s_blocksize - 1); offset = ctx->pos & (sb->s_blocksize - 1);
while (!error && !stored && *f_pos < i_size_read(inode)) { while (ctx->pos < i_size_read(inode)) {
blk = (*f_pos) >> sb->s_blocksize_bits; blk = ctx->pos >> sb->s_blocksize_bits;
if (ocfs2_read_dir_block(inode, blk, &bh, 0)) { if (ocfs2_read_dir_block(inode, blk, &bh, 0)) {
/* Skip the corrupt dirblock and keep trying */ /* Skip the corrupt dirblock and keep trying */
*f_pos += sb->s_blocksize - offset; ctx->pos += sb->s_blocksize - offset;
continue; continue;
} }
...@@ -1897,7 +1875,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, ...@@ -1897,7 +1875,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
ra_sectors = 8; ra_sectors = 8;
} }
revalidate:
/* If the dir block has changed since the last call to /* If the dir block has changed since the last call to
* readdir(2), then we might be pointing to an invalid * readdir(2), then we might be pointing to an invalid
* dirent right now. Scan from the start of the block * dirent right now. Scan from the start of the block
...@@ -1917,93 +1894,64 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode, ...@@ -1917,93 +1894,64 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
i += le16_to_cpu(de->rec_len); i += le16_to_cpu(de->rec_len);
} }
offset = i; offset = i;
*f_pos = ((*f_pos) & ~(sb->s_blocksize - 1)) ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1))
| offset; | offset;
*f_version = inode->i_version; *f_version = inode->i_version;
} }
while (!error && *f_pos < i_size_read(inode) while (ctx->pos < i_size_read(inode)
&& offset < sb->s_blocksize) { && offset < sb->s_blocksize) {
de = (struct ocfs2_dir_entry *) (bh->b_data + offset); de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
if (!ocfs2_check_dir_entry(inode, de, bh, offset)) { if (!ocfs2_check_dir_entry(inode, de, bh, offset)) {
/* On error, skip the f_pos to the /* On error, skip the f_pos to the
next block. */ next block. */
*f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1; ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1;
brelse(bh); brelse(bh);
goto out; continue;
} }
offset += le16_to_cpu(de->rec_len);
if (le64_to_cpu(de->inode)) { if (le64_to_cpu(de->inode)) {
/* We might block in the next section
* if the data destination is
* currently swapped out. So, use a
* version stamp to detect whether or
* not the directory has been modified
* during the copy operation.
*/
unsigned long version = *f_version;
unsigned char d_type = DT_UNKNOWN; unsigned char d_type = DT_UNKNOWN;
if (de->file_type < OCFS2_FT_MAX) if (de->file_type < OCFS2_FT_MAX)
d_type = ocfs2_filetype_table[de->file_type]; d_type = ocfs2_filetype_table[de->file_type];
error = filldir(priv, de->name, if (!dir_emit(ctx, de->name,
de->name_len, de->name_len,
*f_pos,
le64_to_cpu(de->inode), le64_to_cpu(de->inode),
d_type); d_type)) {
if (error) { brelse(bh);
if (filldir_err) return 0;
*filldir_err = error;
break;
} }
if (version != *f_version) stored++;
goto revalidate;
stored ++;
} }
*f_pos += le16_to_cpu(de->rec_len); offset += le16_to_cpu(de->rec_len);
ctx->pos += le16_to_cpu(de->rec_len);
} }
offset = 0; offset = 0;
brelse(bh); brelse(bh);
bh = NULL; bh = NULL;
if (!persist && stored)
break;
} }
return 0;
stored = 0;
out:
return stored;
} }
static int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version, static int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version,
loff_t *f_pos, void *priv, filldir_t filldir, struct dir_context *ctx,
int *filldir_err) bool persist)
{ {
if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
return ocfs2_dir_foreach_blk_id(inode, f_version, f_pos, priv, return ocfs2_dir_foreach_blk_id(inode, f_version, ctx);
filldir, filldir_err); return ocfs2_dir_foreach_blk_el(inode, f_version, ctx, persist);
return ocfs2_dir_foreach_blk_el(inode, f_version, f_pos, priv, filldir,
filldir_err);
} }
/* /*
* This is intended to be called from inside other kernel functions, * This is intended to be called from inside other kernel functions,
* so we fake some arguments. * so we fake some arguments.
*/ */
int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, int ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx)
filldir_t filldir)
{ {
int ret = 0, filldir_err = 0;
u64 version = inode->i_version; u64 version = inode->i_version;
ocfs2_dir_foreach_blk(inode, &version, ctx, true);
while (*f_pos < i_size_read(inode)) {
ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv,
filldir, &filldir_err);
if (ret || filldir_err)
break;
}
if (ret > 0)
ret = -EIO;
return 0; return 0;
} }
...@@ -2011,15 +1959,15 @@ int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, ...@@ -2011,15 +1959,15 @@ int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
* ocfs2_readdir() * ocfs2_readdir()
* *
*/ */
int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) int ocfs2_readdir(struct file *file, struct dir_context *ctx)
{ {
int error = 0; int error = 0;
struct inode *inode = file_inode(filp); struct inode *inode = file_inode(file);
int lock_level = 0; int lock_level = 0;
trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno); trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno);
error = ocfs2_inode_lock_atime(inode, filp->f_path.mnt, &lock_level); error = ocfs2_inode_lock_atime(inode, file->f_path.mnt, &lock_level);
if (lock_level && error >= 0) { if (lock_level && error >= 0) {
/* We release EX lock which used to update atime /* We release EX lock which used to update atime
* and get PR lock again to reduce contention * and get PR lock again to reduce contention
...@@ -2035,8 +1983,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir) ...@@ -2035,8 +1983,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
goto bail_nolock; goto bail_nolock;
} }
error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos, error = ocfs2_dir_foreach_blk(inode, &file->f_version, ctx, false);
dirent, filldir, NULL);
ocfs2_inode_unlock(inode, lock_level); ocfs2_inode_unlock(inode, lock_level);
if (error) if (error)
...@@ -2120,6 +2067,7 @@ int ocfs2_check_dir_for_entry(struct inode *dir, ...@@ -2120,6 +2067,7 @@ int ocfs2_check_dir_for_entry(struct inode *dir,
} }
struct ocfs2_empty_dir_priv { struct ocfs2_empty_dir_priv {
struct dir_context ctx;
unsigned seen_dot; unsigned seen_dot;
unsigned seen_dot_dot; unsigned seen_dot_dot;
unsigned seen_other; unsigned seen_other;
...@@ -2204,8 +2152,9 @@ static int ocfs2_empty_dir_dx(struct inode *inode, ...@@ -2204,8 +2152,9 @@ static int ocfs2_empty_dir_dx(struct inode *inode,
int ocfs2_empty_dir(struct inode *inode) int ocfs2_empty_dir(struct inode *inode)
{ {
int ret; int ret;
loff_t start = 0; struct ocfs2_empty_dir_priv priv = {
struct ocfs2_empty_dir_priv priv; .ctx.actor = ocfs2_empty_dir_filldir
};
memset(&priv, 0, sizeof(priv)); memset(&priv, 0, sizeof(priv));
...@@ -2219,7 +2168,7 @@ int ocfs2_empty_dir(struct inode *inode) ...@@ -2219,7 +2168,7 @@ int ocfs2_empty_dir(struct inode *inode)
*/ */
} }
ret = ocfs2_dir_foreach(inode, &start, &priv, ocfs2_empty_dir_filldir); ret = ocfs2_dir_foreach(inode, &priv.ctx);
if (ret) if (ret)
mlog_errno(ret); mlog_errno(ret);
......
...@@ -92,9 +92,8 @@ int ocfs2_find_files_on_disk(const char *name, ...@@ -92,9 +92,8 @@ int ocfs2_find_files_on_disk(const char *name,
struct ocfs2_dir_lookup_result *res); struct ocfs2_dir_lookup_result *res);
int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name, int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name,
int namelen, u64 *blkno); int namelen, u64 *blkno);
int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir); int ocfs2_readdir(struct file *file, struct dir_context *ctx);
int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv, int ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx);
filldir_t filldir);
int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb, int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
struct inode *dir, struct inode *dir,
struct buffer_head *parent_fe_bh, struct buffer_head *parent_fe_bh,
......
...@@ -2712,7 +2712,7 @@ const struct file_operations ocfs2_fops = { ...@@ -2712,7 +2712,7 @@ const struct file_operations ocfs2_fops = {
const struct file_operations ocfs2_dops = { const struct file_operations ocfs2_dops = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = ocfs2_readdir, .iterate = ocfs2_readdir,
.fsync = ocfs2_sync_file, .fsync = ocfs2_sync_file,
.release = ocfs2_dir_release, .release = ocfs2_dir_release,
.open = ocfs2_dir_open, .open = ocfs2_dir_open,
...@@ -2759,7 +2759,7 @@ const struct file_operations ocfs2_fops_no_plocks = { ...@@ -2759,7 +2759,7 @@ const struct file_operations ocfs2_fops_no_plocks = {
const struct file_operations ocfs2_dops_no_plocks = { const struct file_operations ocfs2_dops_no_plocks = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
.read = generic_read_dir, .read = generic_read_dir,
.readdir = ocfs2_readdir, .iterate = ocfs2_readdir,
.fsync = ocfs2_sync_file, .fsync = ocfs2_sync_file,
.release = ocfs2_dir_release, .release = ocfs2_dir_release,
.open = ocfs2_dir_open, .open = ocfs2_dir_open,
......
...@@ -1941,6 +1941,7 @@ void ocfs2_orphan_scan_start(struct ocfs2_super *osb) ...@@ -1941,6 +1941,7 @@ void ocfs2_orphan_scan_start(struct ocfs2_super *osb)
} }
struct ocfs2_orphan_filldir_priv { struct ocfs2_orphan_filldir_priv {
struct dir_context ctx;
struct inode *head; struct inode *head;
struct ocfs2_super *osb; struct ocfs2_super *osb;
}; };
...@@ -1977,11 +1978,11 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, ...@@ -1977,11 +1978,11 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
{ {
int status; int status;
struct inode *orphan_dir_inode = NULL; struct inode *orphan_dir_inode = NULL;
struct ocfs2_orphan_filldir_priv priv; struct ocfs2_orphan_filldir_priv priv = {
loff_t pos = 0; .ctx.actor = ocfs2_orphan_filldir,
.osb = osb,
priv.osb = osb; .head = *head
priv.head = *head; };
orphan_dir_inode = ocfs2_get_system_file_inode(osb, orphan_dir_inode = ocfs2_get_system_file_inode(osb,
ORPHAN_DIR_SYSTEM_INODE, ORPHAN_DIR_SYSTEM_INODE,
...@@ -1999,8 +2000,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, ...@@ -1999,8 +2000,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
goto out; goto out;
} }
status = ocfs2_dir_foreach(orphan_dir_inode, &pos, &priv, status = ocfs2_dir_foreach(orphan_dir_inode, &priv.ctx);
ocfs2_orphan_filldir);
if (status) { if (status) {
mlog_errno(status); mlog_errno(status);
goto out_cluster; goto out_cluster;
......
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