mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 19:56:18 +00:00
kill-the-bkl/reiserfs: always lock the ioctl path
Reiserfs uses the ioctl callback for its file operations, which means that its ioctl path is still locked by the bkl, this was synchronizing with the rest of the filsystem operations. We have changed that by locking it with the new reiserfs lock but we do that only from the compat_ioctl callback. Fix that by locking reiserfs_ioctl() everytime. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jeff Mahoney <jeffm@suse.com> Cc: Chris Mason <chris.mason@oracle.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Alexander Beregalov <a.beregalov@gmail.com> Cc: Laurent Riffard <laurent.riffard@free.fr> Cc: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
48f6ba5e69
commit
ac78a07893
1 changed files with 39 additions and 27 deletions
|
@ -13,44 +13,52 @@
|
||||||
#include <linux/compat.h>
|
#include <linux/compat.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** reiserfs_ioctl - handler for ioctl for inode
|
* reiserfs_ioctl - handler for ioctl for inode
|
||||||
** supported commands:
|
* supported commands:
|
||||||
** 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
|
* 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
|
||||||
** and prevent packing file (argument arg has to be non-zero)
|
* and prevent packing file (argument arg has to be non-zero)
|
||||||
** 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
|
* 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
|
||||||
** 3) That's all for a while ...
|
* 3) That's all for a while ...
|
||||||
*/
|
*/
|
||||||
int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|
int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
unsigned long arg)
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
reiserfs_write_lock(inode->i_sb);
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case REISERFS_IOC_UNPACK:
|
case REISERFS_IOC_UNPACK:
|
||||||
if (S_ISREG(inode->i_mode)) {
|
if (S_ISREG(inode->i_mode)) {
|
||||||
if (arg)
|
if (arg)
|
||||||
return reiserfs_unpack(inode, filp);
|
err = reiserfs_unpack(inode, filp);
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
} else
|
} else
|
||||||
return -ENOTTY;
|
err = -ENOTTY;
|
||||||
/* following two cases are taken from fs/ext2/ioctl.c by Remy
|
break;
|
||||||
Card (card@masi.ibp.fr) */
|
/*
|
||||||
|
* following two cases are taken from fs/ext2/ioctl.c by Remy
|
||||||
|
* Card (card@masi.ibp.fr)
|
||||||
|
*/
|
||||||
case REISERFS_IOC_GETFLAGS:
|
case REISERFS_IOC_GETFLAGS:
|
||||||
if (!reiserfs_attrs(inode->i_sb))
|
if (!reiserfs_attrs(inode->i_sb)) {
|
||||||
return -ENOTTY;
|
err = -ENOTTY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
flags = REISERFS_I(inode)->i_attrs;
|
flags = REISERFS_I(inode)->i_attrs;
|
||||||
i_attrs_to_sd_attrs(inode, (__u16 *) & flags);
|
i_attrs_to_sd_attrs(inode, (__u16 *) & flags);
|
||||||
return put_user(flags, (int __user *)arg);
|
err = put_user(flags, (int __user *)arg);
|
||||||
|
break;
|
||||||
case REISERFS_IOC_SETFLAGS:{
|
case REISERFS_IOC_SETFLAGS:{
|
||||||
if (!reiserfs_attrs(inode->i_sb))
|
if (!reiserfs_attrs(inode->i_sb)) {
|
||||||
return -ENOTTY;
|
err = -ENOTTY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
err = mnt_want_write(filp->f_path.mnt);
|
err = mnt_want_write(filp->f_path.mnt);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
break;
|
||||||
|
|
||||||
if (!is_owner_or_cap(inode)) {
|
if (!is_owner_or_cap(inode)) {
|
||||||
err = -EPERM;
|
err = -EPERM;
|
||||||
|
@ -90,16 +98,18 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
setflags_out:
|
setflags_out:
|
||||||
mnt_drop_write(filp->f_path.mnt);
|
mnt_drop_write(filp->f_path.mnt);
|
||||||
return err;
|
break;
|
||||||
}
|
}
|
||||||
case REISERFS_IOC_GETVERSION:
|
case REISERFS_IOC_GETVERSION:
|
||||||
return put_user(inode->i_generation, (int __user *)arg);
|
err = put_user(inode->i_generation, (int __user *)arg);
|
||||||
|
break;
|
||||||
case REISERFS_IOC_SETVERSION:
|
case REISERFS_IOC_SETVERSION:
|
||||||
if (!is_owner_or_cap(inode))
|
if (!is_owner_or_cap(inode))
|
||||||
return -EPERM;
|
err = -EPERM;
|
||||||
|
break;
|
||||||
err = mnt_want_write(filp->f_path.mnt);
|
err = mnt_want_write(filp->f_path.mnt);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
break;
|
||||||
if (get_user(inode->i_generation, (int __user *)arg)) {
|
if (get_user(inode->i_generation, (int __user *)arg)) {
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
goto setversion_out;
|
goto setversion_out;
|
||||||
|
@ -108,10 +118,14 @@ setflags_out:
|
||||||
mark_inode_dirty(inode);
|
mark_inode_dirty(inode);
|
||||||
setversion_out:
|
setversion_out:
|
||||||
mnt_drop_write(filp->f_path.mnt);
|
mnt_drop_write(filp->f_path.mnt);
|
||||||
return err;
|
break;
|
||||||
default:
|
default:
|
||||||
return -ENOTTY;
|
err = -ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reiserfs_write_unlock(inode->i_sb);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
|
@ -142,9 +156,7 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
|
|
||||||
reiserfs_write_lock(inode->i_sb);
|
|
||||||
ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
|
ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
|
||||||
reiserfs_write_unlock(inode->i_sb);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue