diff options
author | Nick Piggin <npiggin@kernel.dk> | 2010-08-17 14:37:35 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-08-18 08:35:47 -0400 |
commit | ee2ffa0dfdd2db19705f2ba1c6a4c0bfe8122dd8 (patch) | |
tree | e48400d1a33f8d2e68589ccfd61637aa64462f08 /drivers/char/tty_io.c | |
parent | b04f784e5d19ed58892833dae845738972cea260 (diff) |
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>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 0350c42375a2..cd5b829634ea 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -136,6 +136,9 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */ | |||
136 | DEFINE_MUTEX(tty_mutex); | 136 | DEFINE_MUTEX(tty_mutex); |
137 | EXPORT_SYMBOL(tty_mutex); | 137 | EXPORT_SYMBOL(tty_mutex); |
138 | 138 | ||
139 | /* Spinlock to protect the tty->tty_files list */ | ||
140 | DEFINE_SPINLOCK(tty_files_lock); | ||
141 | |||
139 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); | 142 | static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *); |
140 | static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); | 143 | static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *); |
141 | ssize_t redirected_tty_write(struct file *, const char __user *, | 144 | 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) | |||
235 | struct list_head *p; | 238 | struct list_head *p; |
236 | int count = 0; | 239 | int count = 0; |
237 | 240 | ||
238 | file_list_lock(); | 241 | spin_lock(&tty_files_lock); |
239 | list_for_each(p, &tty->tty_files) { | 242 | list_for_each(p, &tty->tty_files) { |
240 | count++; | 243 | count++; |
241 | } | 244 | } |
242 | file_list_unlock(); | 245 | spin_unlock(&tty_files_lock); |
243 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 246 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
244 | tty->driver->subtype == PTY_TYPE_SLAVE && | 247 | tty->driver->subtype == PTY_TYPE_SLAVE && |
245 | tty->link && tty->link->count) | 248 | tty->link && tty->link->count) |
@@ -519,7 +522,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
519 | workqueue with the lock held */ | 522 | workqueue with the lock held */ |
520 | check_tty_count(tty, "tty_hangup"); | 523 | check_tty_count(tty, "tty_hangup"); |
521 | 524 | ||
522 | file_list_lock(); | 525 | spin_lock(&tty_files_lock); |
523 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 526 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ |
524 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { | 527 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { |
525 | if (filp->f_op->write == redirected_tty_write) | 528 | if (filp->f_op->write == redirected_tty_write) |
@@ -530,7 +533,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
530 | __tty_fasync(-1, filp, 0); /* can't block */ | 533 | __tty_fasync(-1, filp, 0); /* can't block */ |
531 | filp->f_op = &hung_up_tty_fops; | 534 | filp->f_op = &hung_up_tty_fops; |
532 | } | 535 | } |
533 | file_list_unlock(); | 536 | spin_unlock(&tty_files_lock); |
534 | 537 | ||
535 | tty_ldisc_hangup(tty); | 538 | tty_ldisc_hangup(tty); |
536 | 539 | ||
@@ -1424,9 +1427,9 @@ static void release_one_tty(struct work_struct *work) | |||
1424 | tty_driver_kref_put(driver); | 1427 | tty_driver_kref_put(driver); |
1425 | module_put(driver->owner); | 1428 | module_put(driver->owner); |
1426 | 1429 | ||
1427 | file_list_lock(); | 1430 | spin_lock(&tty_files_lock); |
1428 | list_del_init(&tty->tty_files); | 1431 | list_del_init(&tty->tty_files); |
1429 | file_list_unlock(); | 1432 | spin_unlock(&tty_files_lock); |
1430 | 1433 | ||
1431 | put_pid(tty->pgrp); | 1434 | put_pid(tty->pgrp); |
1432 | put_pid(tty->session); | 1435 | put_pid(tty->session); |
@@ -1671,7 +1674,10 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1671 | * - do_tty_hangup no longer sees this file descriptor as | 1674 | * - do_tty_hangup no longer sees this file descriptor as |
1672 | * something that needs to be handled for hangups. | 1675 | * something that needs to be handled for hangups. |
1673 | */ | 1676 | */ |
1674 | file_kill(filp); | 1677 | spin_lock(&tty_files_lock); |
1678 | BUG_ON(list_empty(&filp->f_u.fu_list)); | ||
1679 | list_del_init(&filp->f_u.fu_list); | ||
1680 | spin_unlock(&tty_files_lock); | ||
1675 | filp->private_data = NULL; | 1681 | filp->private_data = NULL; |
1676 | 1682 | ||
1677 | /* | 1683 | /* |
@@ -1840,7 +1846,11 @@ got_driver: | |||
1840 | } | 1846 | } |
1841 | 1847 | ||
1842 | filp->private_data = tty; | 1848 | filp->private_data = tty; |
1843 | file_move(filp, &tty->tty_files); | 1849 | BUG_ON(list_empty(&filp->f_u.fu_list)); |
1850 | file_sb_list_del(filp); /* __dentry_open has put it on the sb list */ | ||
1851 | spin_lock(&tty_files_lock); | ||
1852 | list_add(&filp->f_u.fu_list, &tty->tty_files); | ||
1853 | spin_unlock(&tty_files_lock); | ||
1844 | check_tty_count(tty, "tty_open"); | 1854 | check_tty_count(tty, "tty_open"); |
1845 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1855 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
1846 | tty->driver->subtype == PTY_TYPE_MASTER) | 1856 | tty->driver->subtype == PTY_TYPE_MASTER) |