fs: cleanup files_lock locking

fs: cleanup files_lock locking

Lock tty_files with a new spinlock, tty_files_lock; provide helpers to
manipulate the per-sb files list; unexport the files_lock spinlock.

Cc: linux-kernel@vger.kernel.org
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Acked-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Nick Piggin <npiggin@kernel.dk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Nick Piggin
2010-08-18 04:37:35 +10:00
committed by Al Viro
parent b04f784e5d
commit ee2ffa0dfd
7 changed files with 48 additions and 42 deletions
+5 -1
View File
@@ -676,7 +676,11 @@ static int ptmx_open(struct inode *inode, struct file *filp)
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
filp->private_data = tty;
file_move(filp, &tty->tty_files);
file_sb_list_del(filp); /* __dentry_open has put it on the sb list */
spin_lock(&tty_files_lock);
list_add(&filp->f_u.fu_list, &tty->tty_files);
spin_unlock(&tty_files_lock);
retval = devpts_pty_new(inode, tty->link);
if (retval)
+18 -8
View File
@@ -136,6 +136,9 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */
DEFINE_MUTEX(tty_mutex);
EXPORT_SYMBOL(tty_mutex);
/* Spinlock to protect the tty->tty_files list */
DEFINE_SPINLOCK(tty_files_lock);
static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -235,11 +238,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
struct list_head *p;
int count = 0;
file_list_lock();
spin_lock(&tty_files_lock);
list_for_each(p, &tty->tty_files) {
count++;
}
file_list_unlock();
spin_unlock(&tty_files_lock);
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_SLAVE &&
tty->link && tty->link->count)
@@ -519,7 +522,7 @@ void __tty_hangup(struct tty_struct *tty)
workqueue with the lock held */
check_tty_count(tty, "tty_hangup");
file_list_lock();
spin_lock(&tty_files_lock);
/* This breaks for file handles being sent over AF_UNIX sockets ? */
list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
if (filp->f_op->write == redirected_tty_write)
@@ -530,7 +533,7 @@ void __tty_hangup(struct tty_struct *tty)
__tty_fasync(-1, filp, 0); /* can't block */
filp->f_op = &hung_up_tty_fops;
}
file_list_unlock();
spin_unlock(&tty_files_lock);
tty_ldisc_hangup(tty);
@@ -1424,9 +1427,9 @@ static void release_one_tty(struct work_struct *work)
tty_driver_kref_put(driver);
module_put(driver->owner);
file_list_lock();
spin_lock(&tty_files_lock);
list_del_init(&tty->tty_files);
file_list_unlock();
spin_unlock(&tty_files_lock);
put_pid(tty->pgrp);
put_pid(tty->session);
@@ -1671,7 +1674,10 @@ int tty_release(struct inode *inode, struct file *filp)
* - do_tty_hangup no longer sees this file descriptor as
* something that needs to be handled for hangups.
*/
file_kill(filp);
spin_lock(&tty_files_lock);
BUG_ON(list_empty(&filp->f_u.fu_list));
list_del_init(&filp->f_u.fu_list);
spin_unlock(&tty_files_lock);
filp->private_data = NULL;
/*
@@ -1840,7 +1846,11 @@ got_driver:
}
filp->private_data = tty;
file_move(filp, &tty->tty_files);
BUG_ON(list_empty(&filp->f_u.fu_list));
file_sb_list_del(filp); /* __dentry_open has put it on the sb list */
spin_lock(&tty_files_lock);
list_add(&filp->f_u.fu_list, &tty->tty_files);
spin_unlock(&tty_files_lock);
check_tty_count(tty, "tty_open");
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)