Commit b50989dc444599c8b21edc23536fc305f4e9b7d5

Authored by Alan Cox
Committed by Live-CD User
1 parent e936ffd5cb

tty: make the kref destructor occur asynchronously

We want to be able to sleep in the destructor for USB at least. It isn't a
hot path so just pushing it to a work queue doesn't really cause any
difficulty.

Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 1 changed file with 16 additions and 3 deletions Side-by-side Diff

drivers/char/tty_io.c
... ... @@ -1386,10 +1386,14 @@
1386 1386 * tty_mutex - sometimes only
1387 1387 * takes the file list lock internally when working on the list
1388 1388 * of ttys that the driver keeps.
  1389 + *
  1390 + * This method gets called from a work queue so that the driver private
  1391 + * shutdown ops can sleep (needed for USB at least)
1389 1392 */
1390   -static void release_one_tty(struct kref *kref)
  1393 +static void release_one_tty(struct work_struct *work)
1391 1394 {
1392   - struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
  1395 + struct tty_struct *tty =
  1396 + container_of(work, struct tty_struct, hangup_work);
1393 1397 struct tty_driver *driver = tty->driver;
1394 1398  
1395 1399 if (tty->ops->shutdown)
... ... @@ -1407,6 +1411,15 @@
1407 1411 free_tty_struct(tty);
1408 1412 }
1409 1413  
  1414 +static void queue_release_one_tty(struct kref *kref)
  1415 +{
  1416 + struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
  1417 + /* The hangup queue is now free so we can reuse it rather than
  1418 + waste a chunk of memory for each port */
  1419 + INIT_WORK(&tty->hangup_work, release_one_tty);
  1420 + schedule_work(&tty->hangup_work);
  1421 +}
  1422 +
1410 1423 /**
1411 1424 * tty_kref_put - release a tty kref
1412 1425 * @tty: tty device
... ... @@ -1418,7 +1431,7 @@
1418 1431 void tty_kref_put(struct tty_struct *tty)
1419 1432 {
1420 1433 if (tty)
1421   - kref_put(&tty->kref, release_one_tty);
  1434 + kref_put(&tty->kref, queue_release_one_tty);
1422 1435 }
1423 1436 EXPORT_SYMBOL(tty_kref_put);
1424 1437