Commit d932805b authored by Al Viro's avatar Al Viro Committed by Bob Copeland

omfs: merge unlink() and rmdir(), close leak in rename()

In case of directory-overwriting rename(), omfs forgot to mark the
victim doomed, so omfs_evict_inode() didn't free it.

We could fix that by calling omfs_rmdir() for directory victims
instead of doing omfs_unlink(), but it's easier to merge omfs_unlink()
and omfs_rmdir() instead.  Note that we have no hardlinks here.

It also makes the checks in omfs_rename() go away - they fold into
what omfs_remove() does when it runs into a directory.
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarBob Copeland <me@bobcopeland.com>
parent cdb26496
......@@ -235,33 +235,22 @@ static int omfs_dir_is_empty(struct inode *inode)
return *ptr != ~0;
}
static int omfs_unlink(struct inode *dir, struct dentry *dentry)
static int omfs_remove(struct inode *dir, struct dentry *dentry)
{
int ret;
struct inode *inode = dentry->d_inode;
int ret;
if (S_ISDIR(inode->i_mode) && !omfs_dir_is_empty(inode))
return -ENOTEMPTY;
ret = omfs_delete_entry(dentry);
if (ret)
goto end_unlink;
inode_dec_link_count(inode);
return ret;
clear_nlink(inode);
mark_inode_dirty(inode);
mark_inode_dirty(dir);
end_unlink:
return ret;
}
static int omfs_rmdir(struct inode *dir, struct dentry *dentry)
{
int err = -ENOTEMPTY;
struct inode *inode = dentry->d_inode;
if (omfs_dir_is_empty(inode)) {
err = omfs_unlink(dir, dentry);
if (!err)
inode_dec_link_count(inode);
}
return err;
return 0;
}
static int omfs_add_node(struct inode *dir, struct dentry *dentry, int mode)
......@@ -385,33 +374,17 @@ static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
{
struct inode *new_inode = new_dentry->d_inode;
struct inode *old_inode = old_dentry->d_inode;
struct buffer_head *bh;
int is_dir;
int err;
is_dir = S_ISDIR(old_inode->i_mode);
if (new_inode) {
/* overwriting existing file/dir */
err = -ENOTEMPTY;
if (is_dir && !omfs_dir_is_empty(new_inode))
goto out;
err = -ENOENT;
bh = omfs_find_entry(new_dir, new_dentry->d_name.name,
new_dentry->d_name.len);
if (IS_ERR(bh))
goto out;
brelse(bh);
err = omfs_unlink(new_dir, new_dentry);
err = omfs_remove(new_dir, new_dentry);
if (err)
goto out;
}
/* since omfs locates files by name, we need to unlink _before_
* adding the new link or we won't find the old one */
inode_inc_link_count(old_inode);
err = omfs_delete_entry(old_dentry);
if (err)
goto out;
......@@ -488,8 +461,8 @@ const struct inode_operations omfs_dir_inops = {
.mkdir = omfs_mkdir,
.rename = omfs_rename,
.create = omfs_create,
.unlink = omfs_unlink,
.rmdir = omfs_rmdir,
.unlink = omfs_remove,
.rmdir = omfs_remove,
};
const struct file_operations omfs_dir_operations = {
......
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