Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac78a078 authored by Frederic Weisbecker's avatar Frederic Weisbecker
Browse files

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: default avatarFrederic 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>
parent 48f6ba5e
Loading
Loading
Loading
Loading
+39 −27
Original line number Diff line number Diff line
@@ -13,12 +13,12 @@
#include <linux/compat.h>

/*
** reiserfs_ioctl - handler for ioctl for inode
** supported commands:
**  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
**                           and prevent packing file (argument arg has to be non-zero)
**  2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
**  3) That's all for a while ...
 * reiserfs_ioctl - handler for ioctl for inode
 * supported commands:
 *  1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
 *                           and prevent packing file (argument arg has to be non-zero)
 *  2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
 *  3) That's all for a while ...
 */
int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
		   unsigned long arg)
@@ -26,31 +26,39 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
	unsigned int flags;
	int err = 0;

	reiserfs_write_lock(inode->i_sb);

	switch (cmd) {
	case REISERFS_IOC_UNPACK:
		if (S_ISREG(inode->i_mode)) {
			if (arg)
				return reiserfs_unpack(inode, filp);
			else
				return 0;
				err = reiserfs_unpack(inode, filp);
		} else
			return -ENOTTY;
		/* following two cases are taken from fs/ext2/ioctl.c by Remy
		   Card (card@masi.ibp.fr) */
			err = -ENOTTY;
		break;
		/*
		 * following two cases are taken from fs/ext2/ioctl.c by Remy
		 * Card (card@masi.ibp.fr)
		 */
	case REISERFS_IOC_GETFLAGS:
		if (!reiserfs_attrs(inode->i_sb))
			return -ENOTTY;
		if (!reiserfs_attrs(inode->i_sb)) {
			err = -ENOTTY;
			break;
		}

		flags = REISERFS_I(inode)->i_attrs;
		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:{
			if (!reiserfs_attrs(inode->i_sb))
				return -ENOTTY;
			if (!reiserfs_attrs(inode->i_sb)) {
				err = -ENOTTY;
				break;
			}

			err = mnt_want_write(filp->f_path.mnt);
			if (err)
				return err;
				break;

			if (!is_owner_or_cap(inode)) {
				err = -EPERM;
@@ -90,16 +98,18 @@ int reiserfs_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
			mark_inode_dirty(inode);
setflags_out:
			mnt_drop_write(filp->f_path.mnt);
			return err;
			break;
		}
	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:
		if (!is_owner_or_cap(inode))
			return -EPERM;
			err = -EPERM;
			break;
		err = mnt_want_write(filp->f_path.mnt);
		if (err)
			return err;
			break;
		if (get_user(inode->i_generation, (int __user *)arg)) {
			err = -EFAULT;
			goto setversion_out;
@@ -108,10 +118,14 @@ setflags_out:
		mark_inode_dirty(inode);
setversion_out:
		mnt_drop_write(filp->f_path.mnt);
		return err;
		break;
	default:
		return -ENOTTY;
		err = -ENOTTY;
	}

	reiserfs_write_unlock(inode->i_sb);

	return err;
}

#ifdef CONFIG_COMPAT
@@ -142,9 +156,7 @@ long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
		return -ENOIOCTLCMD;
	}

	reiserfs_write_lock(inode->i_sb);
	ret = reiserfs_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg));
	reiserfs_write_unlock(inode->i_sb);

	return ret;
}