mirror of
https://github.com/adulau/aha.git
synced 2024-12-30 12:46:17 +00:00
[S390] hypfs: inode corruption due to missing locking
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>
This commit is contained in:
parent
cee9e53f59
commit
9b5a03e198
1 changed files with 25 additions and 8 deletions
|
@ -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 (!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)
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue