Skip to content

Commit

Permalink
[S390] hypfs: inode corruption due to missing locking
Browse files Browse the repository at this point in the history
hypfs removes the whole hypfs directory tree and creates a new one, when a
process triggers an update by writing to the "update" attribute. When removing
and creating files, it is necessary to lock the inode of the parent directory
where the files live. Currently hypfs does not lock the parent inode, which
can lead to inode corruption. This patch:
 * Introduces correct locking
 * Fixes i_nlink reference counting for inodes, when creating directories
 * Adds info printk, when hypfs filesystem has been mounted

Signed-off-by: Michael Holzheu <holzheu@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
  • Loading branch information
Michael Holzheu authored and Martin Schwidefsky committed Aug 22, 2007
1 parent cee9e53 commit 9b5a03e
Showing 1 changed file with 25 additions and 8 deletions.
33 changes: 25 additions & 8 deletions arch/s390/hypfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,28 @@ static void hypfs_add_dentry(struct dentry *dentry)
hypfs_last_dentry = dentry;
}

static inline int hypfs_positive(struct dentry *dentry)
{
return dentry->d_inode && !d_unhashed(dentry);
}

static void hypfs_remove(struct dentry *dentry)
{
struct dentry *parent;

parent = dentry->d_parent;
if (S_ISDIR(dentry->d_inode->i_mode))
simple_rmdir(parent->d_inode, dentry);
else
simple_unlink(parent->d_inode, dentry);
if (!parent || !parent->d_inode)
return;
mutex_lock(&parent->d_inode->i_mutex);
if (hypfs_positive(dentry)) {
if (S_ISDIR(dentry->d_inode->i_mode))
simple_rmdir(parent->d_inode, dentry);
else
simple_unlink(parent->d_inode, dentry);
}
d_delete(dentry);
dput(dentry);
mutex_unlock(&parent->d_inode->i_mutex);
}

static void hypfs_delete_tree(struct dentry *root)
Expand Down Expand Up @@ -315,6 +326,7 @@ static int hypfs_fill_super(struct super_block *sb, void *data, int silent)
}
hypfs_update_update(sb);
sb->s_root = root_dentry;
printk(KERN_INFO "hypfs: Hypervisor filesystem mounted\n");
return 0;

err_tree:
Expand Down Expand Up @@ -356,13 +368,17 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
qname.name = name;
qname.len = strlen(name);
qname.hash = full_name_hash(name, qname.len);
mutex_lock(&parent->d_inode->i_mutex);
dentry = lookup_one_len(name, parent, strlen(name));
if (IS_ERR(dentry))
return ERR_PTR(-ENOMEM);
if (IS_ERR(dentry)) {
dentry = ERR_PTR(-ENOMEM);
goto fail;
}
inode = hypfs_make_inode(sb, mode);
if (!inode) {
dput(dentry);
return ERR_PTR(-ENOMEM);
dentry = ERR_PTR(-ENOMEM);
goto fail;
}
if (mode & S_IFREG) {
inode->i_fop = &hypfs_file_ops;
Expand All @@ -379,6 +395,8 @@ static struct dentry *hypfs_create_file(struct super_block *sb,
inode->i_private = data;
d_instantiate(dentry, inode);
dget(dentry);
fail:
mutex_unlock(&parent->d_inode->i_mutex);
return dentry;
}

Expand All @@ -391,7 +409,6 @@ struct dentry *hypfs_mkdir(struct super_block *sb, struct dentry *parent,
if (IS_ERR(dentry))
return dentry;
hypfs_add_dentry(dentry);
parent->d_inode->i_nlink++;
return dentry;
}

Expand Down

0 comments on commit 9b5a03e

Please sign in to comment.