Commit 5eae5b96 authored by Mark Fasheh's avatar Mark Fasheh

ocfs2: Remove open coded readdir()

ocfs2_queue_orphans() has an open coded readdir loop which can easily just
use a directory accessor function.
Signed-off-by: default avatarMark Fasheh <mark.fasheh@oracle.com>
Reviewed-by: default avatarJoel Becker <joel.becker@oracle.com>
parent 7e853679
...@@ -81,10 +81,10 @@ static int ocfs2_do_extend_dir(struct super_block *sb, ...@@ -81,10 +81,10 @@ 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);
int ocfs2_check_dir_entry(struct inode * dir, static int ocfs2_check_dir_entry(struct inode * dir,
struct ocfs2_dir_entry * de, struct ocfs2_dir_entry * de,
struct buffer_head * bh, struct buffer_head * bh,
unsigned long offset) unsigned long offset)
{ {
const char *error_msg = NULL; const char *error_msg = NULL;
const int rlen = le16_to_cpu(de->rec_len); const int rlen = le16_to_cpu(de->rec_len);
...@@ -531,6 +531,26 @@ static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version, ...@@ -531,6 +531,26 @@ static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version,
return stored; return stored;
} }
/*
* This is intended to be called from inside other kernel functions,
* so we fake some arguments.
*/
int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
filldir_t filldir)
{
int ret = 0;
unsigned long version = inode->i_version;
while (*f_pos < i_size_read(inode)) {
ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv,
filldir);
if (ret)
break;
}
return 0;
}
/* /*
* ocfs2_readdir() * ocfs2_readdir()
* *
......
...@@ -62,6 +62,8 @@ int ocfs2_find_files_on_disk(const char *name, ...@@ -62,6 +62,8 @@ int ocfs2_find_files_on_disk(const char *name,
struct buffer_head **dirent_bh, struct buffer_head **dirent_bh,
struct ocfs2_dir_entry **dirent); struct ocfs2_dir_entry **dirent);
int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir); int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir);
int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
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,
...@@ -76,9 +78,4 @@ int ocfs2_fill_new_dir(struct ocfs2_super *osb, ...@@ -76,9 +78,4 @@ int ocfs2_fill_new_dir(struct ocfs2_super *osb,
struct buffer_head *fe_bh, struct buffer_head *fe_bh,
struct ocfs2_alloc_context *data_ac); struct ocfs2_alloc_context *data_ac);
int ocfs2_check_dir_entry(struct inode *dir,
struct ocfs2_dir_entry *de,
struct buffer_head *bh,
unsigned long offset);
#endif /* OCFS2_DIR_H */ #endif /* OCFS2_DIR_H */
...@@ -1213,17 +1213,49 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb) ...@@ -1213,17 +1213,49 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
return status; return status;
} }
struct ocfs2_orphan_filldir_priv {
struct inode *head;
struct ocfs2_super *osb;
};
static int ocfs2_orphan_filldir(void *priv, const char *name, int name_len,
loff_t pos, u64 ino, unsigned type)
{
struct ocfs2_orphan_filldir_priv *p = priv;
struct inode *iter;
if (name_len == 1 && !strncmp(".", name, 1))
return 0;
if (name_len == 2 && !strncmp("..", name, 2))
return 0;
/* Skip bad inodes so that recovery can continue */
iter = ocfs2_iget(p->osb, ino,
OCFS2_FI_FLAG_ORPHAN_RECOVERY);
if (IS_ERR(iter))
return 0;
mlog(0, "queue orphan %llu\n",
(unsigned long long)OCFS2_I(iter)->ip_blkno);
/* No locking is required for the next_orphan queue as there
* is only ever a single process doing orphan recovery. */
OCFS2_I(iter)->ip_next_orphan = p->head;
p->head = iter;
return 0;
}
static int ocfs2_queue_orphans(struct ocfs2_super *osb, static int ocfs2_queue_orphans(struct ocfs2_super *osb,
int slot, int slot,
struct inode **head) struct inode **head)
{ {
int status; int status;
struct inode *orphan_dir_inode = NULL; struct inode *orphan_dir_inode = NULL;
struct inode *iter; struct ocfs2_orphan_filldir_priv priv;
unsigned long offset, blk, local; loff_t pos = 0;
struct buffer_head *bh = NULL;
struct ocfs2_dir_entry *de; priv.osb = osb;
struct super_block *sb = osb->sb; 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,
...@@ -1241,77 +1273,15 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb, ...@@ -1241,77 +1273,15 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
goto out; goto out;
} }
offset = 0; status = ocfs2_dir_foreach(orphan_dir_inode, &pos, &priv,
iter = NULL; ocfs2_orphan_filldir);
while(offset < i_size_read(orphan_dir_inode)) { if (status) {
blk = offset >> sb->s_blocksize_bits; mlog_errno(status);
goto out;
bh = ocfs2_bread(orphan_dir_inode, blk, &status, 0);
if (!bh)
status = -EINVAL;
if (status < 0) {
if (bh)
brelse(bh);
mlog_errno(status);
goto out_unlock;
}
local = 0;
while(offset < i_size_read(orphan_dir_inode)
&& local < sb->s_blocksize) {
de = (struct ocfs2_dir_entry *) (bh->b_data + local);
if (!ocfs2_check_dir_entry(orphan_dir_inode,
de, bh, local)) {
status = -EINVAL;
mlog_errno(status);
brelse(bh);
goto out_unlock;
}
local += le16_to_cpu(de->rec_len);
offset += le16_to_cpu(de->rec_len);
/* I guess we silently fail on no inode? */
if (!le64_to_cpu(de->inode))
continue;
if (de->file_type > OCFS2_FT_MAX) {
mlog(ML_ERROR,
"block %llu contains invalid de: "
"inode = %llu, rec_len = %u, "
"name_len = %u, file_type = %u, "
"name='%.*s'\n",
(unsigned long long)bh->b_blocknr,
(unsigned long long)le64_to_cpu(de->inode),
le16_to_cpu(de->rec_len),
de->name_len,
de->file_type,
de->name_len,
de->name);
continue;
}
if (de->name_len == 1 && !strncmp(".", de->name, 1))
continue;
if (de->name_len == 2 && !strncmp("..", de->name, 2))
continue;
iter = ocfs2_iget(osb, le64_to_cpu(de->inode),
OCFS2_FI_FLAG_ORPHAN_RECOVERY);
if (IS_ERR(iter))
continue;
mlog(0, "queue orphan %llu\n",
(unsigned long long)OCFS2_I(iter)->ip_blkno);
/* No locking is required for the next_orphan
* queue as there is only ever a single
* process doing orphan recovery. */
OCFS2_I(iter)->ip_next_orphan = *head;
*head = iter;
}
brelse(bh);
} }
out_unlock: *head = priv.head;
ocfs2_meta_unlock(orphan_dir_inode, 0); ocfs2_meta_unlock(orphan_dir_inode, 0);
out: out:
mutex_unlock(&orphan_dir_inode->i_mutex); mutex_unlock(&orphan_dir_inode->i_mutex);
......
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