diff options
author | John Stultz <johnstul@us.ibm.com> | 2010-03-22 20:18:36 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2010-04-27 11:32:26 -0400 |
commit | 6f91ea55dfbe1b571542723bf8423e897f68b2c1 (patch) | |
tree | 13dc3d9752f81af60c214a8d62ad26ab7fdd749b /drivers/char | |
parent | e48c15434b82de9a3f597f02ea2257ca22d44d9f (diff) |
fs-files_list-improve
Lock tty_files with a new spinlock, tty_files_lock; provide helpers to
manipulate the per-sb files list; unexport the files_lock spinlock.
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: John Stultz <johnstul@us.ibm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/pty.c | 6 | ||||
-rw-r--r-- | drivers/char/tty_io.c | 27 |
2 files changed, 23 insertions, 10 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 385c44b3034f..8fa273e76bb3 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -649,7 +649,11 @@ static int __ptmx_open(struct inode *inode, struct file *filp) | |||
649 | 649 | ||
650 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | 650 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
651 | filp->private_data = tty; | 651 | filp->private_data = tty; |
652 | file_move(filp, &tty->tty_files); | 652 | |
653 | file_sb_list_del(filp); /* __dentry_open has put it on the sb list */ | ||
654 | spin_lock(&tty_files_lock); | ||
655 | list_add(&filp->f_u.fu_list, &tty->tty_files); | ||
656 | spin_unlock(&tty_files_lock); | ||
653 | 657 | ||
654 | retval = devpts_pty_new(inode, tty->link); | 658 | retval = devpts_pty_new(inode, tty->link); |
655 | if (retval) | 659 | if (retval) |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 76253cf27028..38ddfa404fb1 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 *, |
@@ -234,11 +237,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine) | |||
234 | struct list_head *p; | 237 | struct list_head *p; |
235 | int count = 0; | 238 | int count = 0; |
236 | 239 | ||
237 | file_list_lock(); | 240 | spin_lock(&tty_files_lock); |
238 | list_for_each(p, &tty->tty_files) { | 241 | list_for_each(p, &tty->tty_files) { |
239 | count++; | 242 | count++; |
240 | } | 243 | } |
241 | file_list_unlock(); | 244 | spin_unlock(&tty_files_lock); |
242 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 245 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
243 | tty->driver->subtype == PTY_TYPE_SLAVE && | 246 | tty->driver->subtype == PTY_TYPE_SLAVE && |
244 | tty->link && tty->link->count) | 247 | tty->link && tty->link->count) |
@@ -516,8 +519,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
516 | /* inuse_filps is protected by the single kernel lock */ | 519 | /* inuse_filps is protected by the single kernel lock */ |
517 | lock_kernel(); | 520 | lock_kernel(); |
518 | check_tty_count(tty, "do_tty_hangup"); | 521 | check_tty_count(tty, "do_tty_hangup"); |
519 | 522 | spin_lock(&tty_files_lock); | |
520 | file_list_lock(); | ||
521 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ | 523 | /* This breaks for file handles being sent over AF_UNIX sockets ? */ |
522 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { | 524 | list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) { |
523 | if (filp->f_op->write == redirected_tty_write) | 525 | if (filp->f_op->write == redirected_tty_write) |
@@ -528,7 +530,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
528 | tty_fasync(-1, filp, 0); /* can't block */ | 530 | tty_fasync(-1, filp, 0); /* can't block */ |
529 | filp->f_op = &hung_up_tty_fops; | 531 | filp->f_op = &hung_up_tty_fops; |
530 | } | 532 | } |
531 | file_list_unlock(); | 533 | spin_unlock(&tty_files_lock); |
532 | 534 | ||
533 | tty_ldisc_hangup(tty); | 535 | tty_ldisc_hangup(tty); |
534 | 536 | ||
@@ -1419,9 +1421,9 @@ static void release_one_tty(struct work_struct *work) | |||
1419 | tty_driver_kref_put(driver); | 1421 | tty_driver_kref_put(driver); |
1420 | module_put(driver->owner); | 1422 | module_put(driver->owner); |
1421 | 1423 | ||
1422 | file_list_lock(); | 1424 | spin_lock(&tty_files_lock); |
1423 | list_del_init(&tty->tty_files); | 1425 | list_del_init(&tty->tty_files); |
1424 | file_list_unlock(); | 1426 | spin_unlock(&tty_files_lock); |
1425 | 1427 | ||
1426 | put_pid(tty->pgrp); | 1428 | put_pid(tty->pgrp); |
1427 | put_pid(tty->session); | 1429 | put_pid(tty->session); |
@@ -1666,7 +1668,10 @@ int tty_release(struct inode *inode, struct file *filp) | |||
1666 | * - do_tty_hangup no longer sees this file descriptor as | 1668 | * - do_tty_hangup no longer sees this file descriptor as |
1667 | * something that needs to be handled for hangups. | 1669 | * something that needs to be handled for hangups. |
1668 | */ | 1670 | */ |
1669 | file_kill(filp); | 1671 | spin_lock(&tty_files_lock); |
1672 | BUG_ON(list_empty(&filp->f_u.fu_list)); | ||
1673 | list_del_init(&filp->f_u.fu_list); | ||
1674 | spin_unlock(&tty_files_lock); | ||
1670 | filp->private_data = NULL; | 1675 | filp->private_data = NULL; |
1671 | 1676 | ||
1672 | /* | 1677 | /* |
@@ -1835,7 +1840,11 @@ got_driver: | |||
1835 | } | 1840 | } |
1836 | 1841 | ||
1837 | filp->private_data = tty; | 1842 | filp->private_data = tty; |
1838 | file_move(filp, &tty->tty_files); | 1843 | BUG_ON(list_empty(&filp->f_u.fu_list)); |
1844 | file_sb_list_del(filp); /* __dentry_open has put it on the sb list */ | ||
1845 | spin_lock(&tty_files_lock); | ||
1846 | list_add(&filp->f_u.fu_list, &tty->tty_files); | ||
1847 | spin_unlock(&tty_files_lock); | ||
1839 | check_tty_count(tty, "tty_open"); | 1848 | check_tty_count(tty, "tty_open"); |
1840 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1849 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
1841 | tty->driver->subtype == PTY_TYPE_MASTER) | 1850 | tty->driver->subtype == PTY_TYPE_MASTER) |