Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 67727
b: refs/heads/master
c: 5eae5b9
h: refs/heads/master
i:
  67725: 8a6e21c
  67723: 9122cba
  67719: 27013bf
  67711: 82b1251
v: v3
  • Loading branch information
Mark Fasheh committed Oct 12, 2007
1 parent 6e9e258 commit 762643b
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 84 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7e8536797d4508ddc790cc3af6a281db1582d485
refs/heads/master: 5eae5b96fc86e6c85f5f90e90fe9e6966f1fec63
28 changes: 24 additions & 4 deletions trunk/fs/ocfs2/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ static int ocfs2_do_extend_dir(struct super_block *sb,
struct ocfs2_alloc_context *meta_ac,
struct buffer_head **new_bh);

int ocfs2_check_dir_entry(struct inode * dir,
struct ocfs2_dir_entry * de,
struct buffer_head * bh,
unsigned long offset)
static int ocfs2_check_dir_entry(struct inode * dir,
struct ocfs2_dir_entry * de,
struct buffer_head * bh,
unsigned long offset)
{
const char *error_msg = NULL;
const int rlen = le16_to_cpu(de->rec_len);
Expand Down Expand Up @@ -531,6 +531,26 @@ static int ocfs2_dir_foreach_blk(struct inode *inode, unsigned long *f_version,
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()
*
Expand Down
7 changes: 2 additions & 5 deletions trunk/fs/ocfs2/dir.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ int ocfs2_find_files_on_disk(const char *name,
struct buffer_head **dirent_bh,
struct ocfs2_dir_entry **dirent);
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,
struct inode *dir,
struct buffer_head *parent_fe_bh,
Expand All @@ -76,9 +78,4 @@ int ocfs2_fill_new_dir(struct ocfs2_super *osb,
struct buffer_head *fe_bh,
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 */
118 changes: 44 additions & 74 deletions trunk/fs/ocfs2/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1213,17 +1213,49 @@ int ocfs2_mark_dead_nodes(struct ocfs2_super *osb)
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,
int slot,
struct inode **head)
{
int status;
struct inode *orphan_dir_inode = NULL;
struct inode *iter;
unsigned long offset, blk, local;
struct buffer_head *bh = NULL;
struct ocfs2_dir_entry *de;
struct super_block *sb = osb->sb;
struct ocfs2_orphan_filldir_priv priv;
loff_t pos = 0;

priv.osb = osb;
priv.head = *head;

orphan_dir_inode = ocfs2_get_system_file_inode(osb,
ORPHAN_DIR_SYSTEM_INODE,
Expand All @@ -1241,77 +1273,15 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
goto out;
}

offset = 0;
iter = NULL;
while(offset < i_size_read(orphan_dir_inode)) {
blk = offset >> sb->s_blocksize_bits;

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);
status = ocfs2_dir_foreach(orphan_dir_inode, &pos, &priv,
ocfs2_orphan_filldir);
if (status) {
mlog_errno(status);
goto out;
}

out_unlock:
*head = priv.head;

ocfs2_meta_unlock(orphan_dir_inode, 0);
out:
mutex_unlock(&orphan_dir_inode->i_mutex);
Expand Down

0 comments on commit 762643b

Please sign in to comment.