diff options
author | Alan Cox <alan@redhat.com> | 2008-10-13 05:41:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-13 12:51:42 -0400 |
commit | feebed6515a113eeb33919e9557a8b9710ea627c (patch) | |
tree | 0461178ee0c5e16ea90023e4b6386cb5c57d3391 /drivers/char/tty_io.c | |
parent | bf7a06bcce205705ea5c7675cbb8ea9239ea30a0 (diff) |
tty: shutdown method
Right now there are various drivers that try to use tty->count to know when
they get the final close. Aristeau Rozanski showed while debugging the vt
sysfs race that this isn't entirely safe.
Instead of driver side tricks to work around this introduce a shutdown which
is called when the tty is being destructed. This also means that the shutdown
method is tied into the refcounting.
Use this to rework the console close/sysfs logic.
Remove lots of special case code from the tty core code. The pty code can now
have a shutdown() method that replaces the special case hackery in the tree
free up paths.
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 2e96ce0fddc5..f91704d57a4e 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -1482,6 +1482,31 @@ release_mem_out: | |||
1482 | goto end_init; | 1482 | goto end_init; |
1483 | } | 1483 | } |
1484 | 1484 | ||
1485 | void tty_free_termios(struct tty_struct *tty) | ||
1486 | { | ||
1487 | struct ktermios *tp; | ||
1488 | int idx = tty->index; | ||
1489 | /* Kill this flag and push into drivers for locking etc */ | ||
1490 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | ||
1491 | /* FIXME: Locking on ->termios array */ | ||
1492 | tp = tty->termios; | ||
1493 | tty->driver->termios[idx] = NULL; | ||
1494 | kfree(tp); | ||
1495 | |||
1496 | tp = tty->termios_locked; | ||
1497 | tty->driver->termios_locked[idx] = NULL; | ||
1498 | kfree(tp); | ||
1499 | } | ||
1500 | } | ||
1501 | EXPORT_SYMBOL(tty_free_termios); | ||
1502 | |||
1503 | void tty_shutdown(struct tty_struct *tty) | ||
1504 | { | ||
1505 | tty->driver->ttys[tty->index] = NULL; | ||
1506 | tty_free_termios(tty); | ||
1507 | } | ||
1508 | EXPORT_SYMBOL(tty_shutdown); | ||
1509 | |||
1485 | /** | 1510 | /** |
1486 | * release_one_tty - release tty structure memory | 1511 | * release_one_tty - release tty structure memory |
1487 | * @kref: kref of tty we are obliterating | 1512 | * @kref: kref of tty we are obliterating |
@@ -1499,27 +1524,11 @@ static void release_one_tty(struct kref *kref) | |||
1499 | { | 1524 | { |
1500 | struct tty_struct *tty = container_of(kref, struct tty_struct, kref); | 1525 | struct tty_struct *tty = container_of(kref, struct tty_struct, kref); |
1501 | struct tty_driver *driver = tty->driver; | 1526 | struct tty_driver *driver = tty->driver; |
1502 | int devpts = tty->driver->flags & TTY_DRIVER_DEVPTS_MEM; | ||
1503 | struct ktermios *tp; | ||
1504 | int idx = tty->index; | ||
1505 | |||
1506 | if (!devpts) | ||
1507 | tty->driver->ttys[idx] = NULL; | ||
1508 | |||
1509 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | ||
1510 | /* FIXME: Locking on ->termios array */ | ||
1511 | tp = tty->termios; | ||
1512 | if (!devpts) | ||
1513 | tty->driver->termios[idx] = NULL; | ||
1514 | kfree(tp); | ||
1515 | |||
1516 | tp = tty->termios_locked; | ||
1517 | if (!devpts) | ||
1518 | tty->driver->termios_locked[idx] = NULL; | ||
1519 | kfree(tp); | ||
1520 | } | ||
1521 | |||
1522 | 1527 | ||
1528 | if (tty->ops->shutdown) | ||
1529 | tty->ops->shutdown(tty); | ||
1530 | else | ||
1531 | tty_shutdown(tty); | ||
1523 | tty->magic = 0; | 1532 | tty->magic = 0; |
1524 | /* FIXME: locking on tty->driver->refcount */ | 1533 | /* FIXME: locking on tty->driver->refcount */ |
1525 | tty->driver->refcount--; | 1534 | tty->driver->refcount--; |