* [RFC 0/9] BKL conversion in TTY drivers
@ 2010-03-30 20:56 Arnd Bergmann
2010-03-30 20:56 ` [RFC 1/9] tty: replace BKL with a new tty_lock Arnd Bergmann
` (9 more replies)
0 siblings, 10 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann
This is one of the tricker bits in the BKL removal series,
so let's discuss it here. In order to build a kernel without
the BKL, it's obviously necessary to do something about
the TTY code. This series introduces a new Big TTY Mutex
that is based on the earlier implementation of the
Big Kernel Semaphore, but comes with a number of changes:
- based on the mutex code instead of a semaphore,
so we can use all the mutex debugging.
- no autorelease on sleep, which is what most of the
series is about.
- limited to one subsystem only.
- ability to annotate nested locking so we can eventually
turn it into a non-recursive mutex, once all the
recursive users stay around.
The first eight patches convert all the code using the BKL
in the TTY layer and related drivers to the new interface,
while the final patch adds the real mutex implementation
as an experimental configuration option.
When that option is disabled, the behaviour should be
basically unchanged regarding serialization against
other subsystems using the BKL.
Together with the patches removing the BKL from block,
procfs, init, usb and VFS, it then becomes realistic to
build a kernel that does not contain the BKL at all,
while disabling all code that still uses it.
This means we are still safe, because there is no code
left that the new BTM fails to serialize with.
This smaller series is taken from my bkl-removal tree,
ported to 2.6.34-rc3 and with the last patch changed to
make the new implementation optional.
Arnd
---
Arnd Bergmann (9):
tty: replace BKL with a new tty_lock
tty: make atomic_write_lock release tty_lock
tty: make tty_port->mutex nest under tty_lock
tty: make termios mutex nest under tty_lock
tty: make ldisc_mutex nest under tty_lock
tty: never hold tty_lock() while getting tty_mutex
ppp: use big tty mutex
tty: release tty lock when blocking
tty: implement BTM as mutex instead of BKL
drivers/char/Makefile | 1 +
drivers/char/amiserial.c | 16 ++--
drivers/char/briq_panel.c | 6 +-
drivers/char/cyclades.c | 20 ++--
drivers/char/epca.c | 4 +-
drivers/char/isicom.c | 10 +-
drivers/char/istallion.c | 20 ++--
drivers/char/mxser.c | 10 +-
drivers/char/n_hdlc.c | 16 ++--
drivers/char/n_r3964.c | 10 +-
drivers/char/pty.c | 8 +-
drivers/char/riscom8.c | 8 +-
drivers/char/rocket.c | 8 +-
drivers/char/serial167.c | 4 +-
drivers/char/specialix.c | 10 +-
drivers/char/stallion.c | 12 ++--
drivers/char/sx.c | 12 ++--
drivers/char/synclink.c | 10 ++-
drivers/char/synclink_gt.c | 8 +-
drivers/char/synclinkmp.c | 12 ++--
drivers/char/tty_buffer.c | 2 +-
drivers/char/tty_io.c | 123 ++++++++++++++-----------
drivers/char/tty_ioctl.c | 36 ++++----
drivers/char/tty_ldisc.c | 53 +++++++-----
drivers/char/tty_port.c | 6 +-
drivers/char/vc_screen.c | 4 +-
drivers/char/vt.c | 4 +-
drivers/char/vt_ioctl.c | 12 ++--
drivers/isdn/i4l/isdn_common.c | 20 ++--
drivers/isdn/i4l/isdn_tty.c | 8 +-
drivers/net/irda/irtty-sir.c | 5 +-
drivers/net/ppp_generic.c | 29 +++---
drivers/serial/68360serial.c | 4 +-
drivers/serial/crisv10.c | 8 +-
drivers/serial/serial_core.c | 42 +++++-----
drivers/staging/strip/strip.c | 2 +-
drivers/usb/class/cdc-acm.c | 2 +-
drivers/usb/serial/usb-serial.c | 18 ++--
drivers/video/console/vgacon.c | 4 +-
include/linux/init_task.h | 1 +
include/linux/sched.h | 1 +
include/linux/tty.h | 188 +++++++++++++++++++++++++++++++++++++++
kernel/fork.c | 1 +
lib/Kconfig.debug | 10 ++
44 files changed, 510 insertions(+), 278 deletions(-)
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC 1/9] tty: replace BKL with a new tty_lock
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-30 22:23 ` Frederic Weisbecker
2010-03-30 20:56 ` [RFC 2/9] tty: make atomic_write_lock release tty_lock Arnd Bergmann
` (8 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann,
Arnd Bergmann
From: Arnd Bergmann <arnd@relay.de.ibm.com>
As a preparation for replacing the big kernel lock
in the TTY layer, wrap all the callers in new
macros tty_lock, tty_lock_nested and tty_unlock.
Code that has been verified to never be called with
the tty_lock held should use tty_lock, other code
should use tty_lock_nested.
We also need to deal with lock order problems that
are currently solved by the BKL autorelease semantics.
For this, we get new macros that can be used to
replace sleeping calls like mutex_lock() or wait_event().
We start using these in the next patches.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/char/amiserial.c | 16 ++--
drivers/char/briq_panel.c | 6 +-
drivers/char/cyclades.c | 16 ++--
drivers/char/epca.c | 4 +-
drivers/char/isicom.c | 10 +-
drivers/char/istallion.c | 8 +-
drivers/char/n_hdlc.c | 16 ++--
drivers/char/n_r3964.c | 8 +-
drivers/char/pty.c | 4 +-
drivers/char/riscom8.c | 8 +-
drivers/char/rocket.c | 8 +-
drivers/char/serial167.c | 4 +-
drivers/char/specialix.c | 10 +-
drivers/char/stallion.c | 12 ++--
drivers/char/sx.c | 12 ++--
drivers/char/synclink.c | 8 +-
drivers/char/synclink_gt.c | 8 +-
drivers/char/synclinkmp.c | 12 ++--
drivers/char/tty_io.c | 113 +++++++++++++++------------
drivers/char/tty_ldisc.c | 22 +++---
drivers/char/vc_screen.c | 4 +-
drivers/char/vt.c | 4 +-
drivers/char/vt_ioctl.c | 10 +-
drivers/isdn/i4l/isdn_common.c | 20 +++---
drivers/isdn/i4l/isdn_tty.c | 8 +-
drivers/serial/68360serial.c | 4 +-
drivers/serial/crisv10.c | 4 +-
drivers/serial/serial_core.c | 10 +-
drivers/usb/serial/usb-serial.c | 18 ++--
drivers/video/console/vgacon.c | 4 +-
include/linux/tty.h | 169 +++++++++++++++++++++++++++++++++++++++
31 files changed, 371 insertions(+), 189 deletions(-)
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 6c32fbf..d3bee1f 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1071,7 +1071,7 @@ static int get_serial_info(struct async_struct * info,
if (!retinfo)
return -EFAULT;
memset(&tmp, 0, sizeof(tmp));
- lock_kernel();
+ tty_lock();
tmp.type = state->type;
tmp.line = state->line;
tmp.port = state->port;
@@ -1082,7 +1082,7 @@ static int get_serial_info(struct async_struct * info,
tmp.close_delay = state->close_delay;
tmp.closing_wait = state->closing_wait;
tmp.custom_divisor = state->custom_divisor;
- unlock_kernel();
+ tty_unlock();
if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
return -EFAULT;
return 0;
@@ -1099,14 +1099,14 @@ static int set_serial_info(struct async_struct * info,
if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
return -EFAULT;
- lock_kernel();
+ tty_lock();
state = info->state;
old_state = *state;
change_irq = new_serial.irq != state->irq;
change_port = (new_serial.port != state->port);
if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
- unlock_kernel();
+ tty_unlock();
return -EINVAL;
}
@@ -1126,7 +1126,7 @@ static int set_serial_info(struct async_struct * info,
}
if (new_serial.baud_base < 9600) {
- unlock_kernel();
+ tty_unlock();
return -EINVAL;
}
@@ -1162,7 +1162,7 @@ check_and_exit:
}
} else
retval = startup(info);
- unlock_kernel();
+ tty_unlock();
return retval;
}
@@ -1537,7 +1537,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
orig_jiffies = jiffies;
- lock_kernel();
+ tty_lock_nested();
/*
* Set the check interval to be 1/5 of the estimated time to
* send a single character, and make it at least 1. The check
@@ -1578,7 +1578,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
__set_current_state(TASK_RUNNING);
- unlock_kernel();
+ tty_unlock();
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
#endif
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index d8cff90..bf19527 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -68,15 +68,15 @@ static void set_led(char state)
static int briq_panel_open(struct inode *ino, struct file *filep)
{
- lock_kernel();
+ tty_lock();
/* enforce single access, vfd_is_open is protected by BKL */
if (vfd_is_open) {
- unlock_kernel();
+ tty_unlock();
return -EBUSY;
}
vfd_is_open = 1;
- unlock_kernel();
+ tty_unlock();
return 0;
}
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index b861c08..350595e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1654,7 +1654,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
return; /* Just in case.... */
orig_jiffies = jiffies;
- lock_kernel();
+ tty_lock_nested();
/*
* Set the check interval to be 1/5 of the estimated time to
* send a single character, and make it at least 1. The check
@@ -1701,7 +1701,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
}
/* Run one more char cycle */
msleep_interruptible(jiffies_to_msecs(char_time * 5));
- unlock_kernel();
+ tty_unlock();
#ifdef CY_DEBUG_WAIT_UNTIL_SENT
printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
#endif
@@ -1958,7 +1958,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
int char_count;
__u32 tx_put, tx_get, tx_bufsize;
- lock_kernel();
+ tty_lock_nested();
tx_get = readl(&buf_ctrl->tx_get);
tx_put = readl(&buf_ctrl->tx_put);
tx_bufsize = readl(&buf_ctrl->tx_bufsize);
@@ -1970,7 +1970,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
info->line, info->xmit_cnt + char_count);
#endif
- unlock_kernel();
+ tty_unlock();
return info->xmit_cnt + char_count;
}
#endif /* Z_EXT_CHARS_IN_BUFFER */
@@ -2437,7 +2437,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
card = info->card;
- lock_kernel();
+ tty_lock();
if (!cy_is_Z(card)) {
unsigned long flags;
int channel = info->line - card->first_line;
@@ -2477,7 +2477,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file)
((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
}
end:
- unlock_kernel();
+ tty_unlock();
return result;
} /* cy_tiomget */
@@ -2695,7 +2695,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
info->line, cmd, arg);
#endif
- lock_kernel();
+ tty_lock();
switch (cmd) {
case CYGETMON:
@@ -2816,7 +2816,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
default:
ret_val = -ENOIOCTLCMD;
}
- unlock_kernel();
+ tty_unlock();
#ifdef CY_DEBUG_OTHER
printk(KERN_DEBUG "cyc:cy_ioctl done\n");
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index 17b044a..50699df 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -2106,7 +2106,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
break;
case DIGI_SETAW:
case DIGI_SETAF:
- lock_kernel();
+ tty_lock();
if (cmd == DIGI_SETAW) {
/* Setup an event to indicate when the transmit
buffer empties */
@@ -2119,7 +2119,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file,
if (tty->ldisc->ops->flush_buffer)
tty->ldisc->ops->flush_buffer(tty);
}
- unlock_kernel();
+ tty_unlock();
/* Fall Thru */
case DIGI_SETA:
if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index be2e8f9..04b6fe0 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1112,7 +1112,7 @@ static int isicom_set_serial_info(struct tty_struct *tty,
if (copy_from_user(&newinfo, info, sizeof(newinfo)))
return -EFAULT;
- lock_kernel();
+ tty_lock();
reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
(newinfo.flags & ASYNC_SPD_MASK));
@@ -1122,7 +1122,7 @@ static int isicom_set_serial_info(struct tty_struct *tty,
(newinfo.closing_wait != port->port.closing_wait) ||
((newinfo.flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK))) {
- unlock_kernel();
+ tty_unlock();
return -EPERM;
}
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
@@ -1139,7 +1139,7 @@ static int isicom_set_serial_info(struct tty_struct *tty,
isicom_config_port(tty);
spin_unlock_irqrestore(&port->card->card_lock, flags);
}
- unlock_kernel();
+ tty_unlock();
return 0;
}
@@ -1148,7 +1148,7 @@ static int isicom_get_serial_info(struct isi_port *port,
{
struct serial_struct out_info;
- lock_kernel();
+ tty_lock();
memset(&out_info, 0, sizeof(out_info));
/* out_info.type = ? */
out_info.line = port - isi_ports;
@@ -1158,7 +1158,7 @@ static int isicom_get_serial_info(struct isi_port *port,
/* out_info.baud_base = ? */
out_info.close_delay = port->port.close_delay;
out_info.closing_wait = port->port.closing_wait;
- unlock_kernel();
+ tty_unlock();
if (copy_to_user(info, &out_info, sizeof(out_info)))
return -EFAULT;
return 0;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 4cd6c52..39853b4 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -4264,7 +4264,7 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
done = 0;
rc = 0;
- lock_kernel();
+ tty_lock();
switch (cmd) {
case COM_GETPORTSTATS:
@@ -4288,7 +4288,7 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
done++;
break;
}
- unlock_kernel();
+ tty_unlock();
if (done)
return rc;
@@ -4306,7 +4306,7 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
if (brdp->state == 0)
return -ENODEV;
- lock_kernel();
+ tty_lock();
switch (cmd) {
case STL_BINTR:
@@ -4330,7 +4330,7 @@ static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
+ tty_unlock();
return rc;
}
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index c68118e..fed2ef1 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
return -EFAULT;
}
- lock_kernel();
+ tty_lock_nested();
for (;;) {
if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
- unlock_kernel();
+ tty_unlock();
return -EIO;
}
n_hdlc = tty2n_hdlc (tty);
if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC ||
tty != n_hdlc->tty) {
- unlock_kernel();
+ tty_unlock();
return 0;
}
@@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
/* no data */
if (file->f_flags & O_NONBLOCK) {
- unlock_kernel();
+ tty_unlock();
return -EAGAIN;
}
interruptible_sleep_on (&tty->read_wait);
if (signal_pending(current)) {
- unlock_kernel();
+ tty_unlock();
return -EINTR;
}
}
@@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
kfree(rbuf);
else
n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf);
- unlock_kernel();
+ tty_unlock();
return ret;
} /* end of n_hdlc_tty_read() */
@@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
count = maxframe;
}
- lock_kernel();
+ tty_lock_nested();
add_wait_queue(&tty->write_wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
@@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file,
n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf);
n_hdlc_send_frames(n_hdlc,tty);
}
- unlock_kernel();
+ tty_unlock();
return error;
} /* end of n_hdlc_tty_write() */
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index c1d8b54..2bd0e22 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
TRACE_L("read()");
- lock_kernel();
+ tty_lock_nested();
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
}
ret = -EPERM;
unlock:
- unlock_kernel();
+ tty_unlock();
return ret;
}
@@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
pHeader->locks = 0;
pHeader->owner = NULL;
- lock_kernel();
+ tty_lock_nested();
pClient = findClient(pInfo, task_pid(current));
if (pClient) {
@@ -1177,7 +1177,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file,
add_tx_queue(pInfo, pHeader);
trigger_transmit(pInfo);
- unlock_kernel();
+ tty_unlock();
return 0;
}
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 5ee4248..f02ff21 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -670,9 +670,9 @@ static int ptmx_open(struct inode *inode, struct file *filp)
{
int ret;
- lock_kernel();
+ tty_lock();
ret = __ptmx_open(inode, filp);
- unlock_kernel();
+ tty_unlock();
return ret;
}
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c
index 0a8d1e5..9c94103 100644
--- a/drivers/char/riscom8.c
+++ b/drivers/char/riscom8.c
@@ -1241,14 +1241,14 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp,
switch (cmd) {
case TIOCGSERIAL:
- lock_kernel();
+ tty_lock();
retval = rc_get_serial_info(port, argp);
- unlock_kernel();
+ tty_unlock();
break;
case TIOCSSERIAL:
- lock_kernel();
+ tty_lock();
retval = rc_set_serial_info(tty, port, argp);
- unlock_kernel();
+ tty_unlock();
break;
default:
retval = -ENOIOCTLCMD;
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 0e29a23..0992a50 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1325,7 +1325,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
return -ENXIO;
- lock_kernel();
+ tty_lock();
switch (cmd) {
case RCKP_GET_STRUCT:
@@ -1350,7 +1350,7 @@ static int rp_ioctl(struct tty_struct *tty, struct file *file,
default:
ret = -ENOIOCTLCMD;
}
- unlock_kernel();
+ tty_unlock();
return ret;
}
@@ -1471,7 +1471,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
jiffies);
printk(KERN_INFO "cps=%d...\n", info->cps);
#endif
- lock_kernel();
+ tty_lock_nested();
while (1) {
txcnt = sGetTxCnt(cp);
if (!txcnt) {
@@ -1499,7 +1499,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
__set_current_state(TASK_RUNNING);
- unlock_kernel();
+ tty_unlock();
#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
#endif
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 1ec3d5c..809cf86 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -1536,7 +1536,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
#endif
- lock_kernel();
+ tty_lock();
switch (cmd) {
case CYGETMON:
@@ -1592,7 +1592,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
default:
ret_val = -ENOIOCTLCMD;
}
- unlock_kernel();
+ tty_unlock();
#ifdef SERIAL_DEBUG_OTHER
printk("cy_ioctl done\n");
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c
index 07ac14d..35a739c 100644
--- a/drivers/char/specialix.c
+++ b/drivers/char/specialix.c
@@ -1862,7 +1862,7 @@ static int sx_set_serial_info(struct specialix_port *port,
return -EFAULT;
}
- lock_kernel();
+ tty_lock();
change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
(tmp.flags & ASYNC_SPD_MASK));
@@ -1874,7 +1874,7 @@ static int sx_set_serial_info(struct specialix_port *port,
((tmp.flags & ~ASYNC_USR_MASK) !=
(port->port.flags & ~ASYNC_USR_MASK))) {
func_exit();
- unlock_kernel();
+ tty_unlock();
return -EPERM;
}
port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
@@ -1891,7 +1891,7 @@ static int sx_set_serial_info(struct specialix_port *port,
sx_change_speed(bp, port);
func_exit();
- unlock_kernel();
+ tty_unlock();
return 0;
}
@@ -1905,7 +1905,7 @@ static int sx_get_serial_info(struct specialix_port *port,
func_enter();
memset(&tmp, 0, sizeof(tmp));
- lock_kernel();
+ tty_lock();
tmp.type = PORT_CIRRUS;
tmp.line = port - sx_port;
tmp.port = bp->base;
@@ -1916,7 +1916,7 @@ static int sx_get_serial_info(struct specialix_port *port,
tmp.closing_wait = port->port.closing_wait * HZ/100;
tmp.custom_divisor = port->custom_divisor;
tmp.xmit_fifo_size = CD186x_NFIFO;
- unlock_kernel();
+ tty_unlock();
if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
func_exit();
return -EFAULT;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index 0e511d6..0637b79 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -807,7 +807,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
timeout = HZ;
tend = jiffies + timeout;
- lock_kernel();
+ tty_lock_nested();
while (stl_datastate(portp)) {
if (signal_pending(current))
break;
@@ -815,7 +815,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
if (time_after_eq(jiffies, tend))
break;
}
- unlock_kernel();
+ tty_unlock();
}
/*****************************************************************************/
@@ -1146,7 +1146,7 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
rc = 0;
- lock_kernel();
+ tty_lock();
switch (cmd) {
case TIOCGSERIAL:
@@ -1172,7 +1172,7 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
rc = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
+ tty_unlock();
return rc;
}
@@ -2450,7 +2450,7 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
return -ENODEV;
rc = 0;
- lock_kernel();
+ tty_lock();
switch (cmd) {
case COM_GETPORTSTATS:
rc = stl_getportstats(NULL, NULL, argp);
@@ -2471,7 +2471,7 @@ static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
+ tty_unlock();
return rc;
}
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index a81ec4f..5b24db4 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
if (!capable(CAP_SYS_RAWIO))
return -EPERM;
- lock_kernel();
+ tty_lock();
sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
@@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
break;
}
out:
- unlock_kernel();
+ tty_unlock();
func_exit();
return rc;
}
@@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag)
int rv;
func_enter();
- lock_kernel();
+ tty_lock();
if (flag)
rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
@@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag)
if (rv != 1)
printk(KERN_ERR "sx: couldn't send break (%x).\n",
read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
- unlock_kernel();
+ tty_unlock();
func_exit();
return 0;
}
@@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
/* func_enter2(); */
rc = 0;
- lock_kernel();
+ tty_lock();
switch (cmd) {
case TIOCGSERIAL:
rc = gs_getserial(&port->gs, argp);
@@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp,
rc = -ENOIOCTLCMD;
break;
}
- unlock_kernel();
+ tty_unlock();
/* func_exit(); */
return rc;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 0658fc5..c7af06b 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2950,9 +2950,9 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
return -EIO;
}
- lock_kernel();
+ tty_lock();
ret = mgsl_ioctl_common(info, cmd, arg);
- unlock_kernel();
+ tty_unlock();
return ret;
}
@@ -3162,7 +3162,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
* Note: use tight timings here to satisfy the NIST-PCTS.
*/
- lock_kernel();
+ tty_lock_nested();
if ( info->params.data_rate ) {
char_time = info->timeout/(32 * 5);
if (!char_time)
@@ -3192,7 +3192,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
}
- unlock_kernel();
+ tty_unlock();
exit:
if (debug_level >= DEBUG_LEVEL_INFO)
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 4561ce2..d75de68 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -901,7 +901,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
* Note: use tight timings here to satisfy the NIST-PCTS.
*/
- lock_kernel();
+ tty_lock_nested();
if (info->params.data_rate) {
char_time = info->timeout/(32 * 5);
@@ -920,7 +920,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
- unlock_kernel();
+ tty_unlock();
exit:
DBGINFO(("%s wait_until_sent exit\n", info->device_name));
@@ -1041,7 +1041,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return -EIO;
}
- lock_kernel();
+ tty_lock();
switch (cmd) {
case MGSL_IOCGPARAMS:
@@ -1111,7 +1111,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
default:
ret = -ENOIOCTLCMD;
}
- unlock_kernel();
+ tty_unlock();
return ret;
}
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 2b18adc..7b7c108 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1062,7 +1062,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
if (sanity_check(info, tty->name, "wait_until_sent"))
return;
- lock_kernel();
+ tty_lock_nested();
if (!(info->port.flags & ASYNC_INITIALIZED))
goto exit;
@@ -1106,7 +1106,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
}
exit:
- unlock_kernel();
+ tty_unlock();
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s wait_until_sent() exit\n",
__FILE__,__LINE__, info->device_name );
@@ -1122,7 +1122,7 @@ static int write_room(struct tty_struct *tty)
if (sanity_check(info, tty->name, "write_room"))
return 0;
- lock_kernel();
+ tty_lock_nested();
if (info->params.mode == MGSL_MODE_HDLC) {
ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
} else {
@@ -1130,7 +1130,7 @@ static int write_room(struct tty_struct *tty)
if (ret < 0)
ret = 0;
}
- unlock_kernel();
+ tty_unlock();
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s write_room()=%d\n",
@@ -1345,9 +1345,9 @@ static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
int ret;
- lock_kernel();
+ tty_lock();
ret = do_ioctl(tty, file, cmd, arg);
- unlock_kernel();
+ tty_unlock();
return ret;
}
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index a42c466..25b82eb 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -149,6 +149,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
#else
#define tty_compat_ioctl NULL
#endif
+static int __tty_fasync(int fd, struct file *filp, int on);
static int tty_fasync(int fd, struct file *filp, int on);
static void release_tty(struct tty_struct *tty, int idx);
static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty);
@@ -483,7 +484,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup);
* remains intact.
*
* Locking:
- * BKL
+ * BTM
* redirect lock for undoing redirection
* file list lock for manipulating list of ttys
* tty_ldisc_lock from called functions
@@ -513,8 +514,11 @@ static void do_tty_hangup(struct work_struct *work)
}
spin_unlock(&redirect_lock);
- /* inuse_filps is protected by the single kernel lock */
- lock_kernel();
+ /* inuse_filps is protected by the single tty lock,
+ this really needs to change if we want to flush the
+ workqueue with the lock held */
+ tty_lock_nested(); /* called with BTM held from pty_close and
+ others */
check_tty_count(tty, "do_tty_hangup");
file_list_lock();
@@ -525,7 +529,7 @@ static void do_tty_hangup(struct work_struct *work)
if (filp->f_op->write != tty_write)
continue;
closecount++;
- tty_fasync(-1, filp, 0); /* can't block */
+ __tty_fasync(-1, filp, 0); /* can't block */
filp->f_op = &hung_up_tty_fops;
}
file_list_unlock();
@@ -594,7 +598,7 @@ static void do_tty_hangup(struct work_struct *work)
*/
set_bit(TTY_HUPPED, &tty->flags);
tty_ldisc_enable(tty);
- unlock_kernel();
+ tty_unlock();
if (f)
fput(f);
}
@@ -696,7 +700,8 @@ static void session_clear_tty(struct pid *session)
* exiting; it is 0 if called by the ioctl TIOCNOTTY.
*
* Locking:
- * BKL is taken for hysterical raisins
+ * BTM is taken for hysterical raisins, and held when
+ * called from no_tty().
* tty_mutex is taken to protect tty
* ->siglock is taken to protect ->signal/->sighand
* tasklist_lock is taken to walk process list for sessions
@@ -714,10 +719,10 @@ void disassociate_ctty(int on_exit)
tty = get_current_tty();
if (tty) {
tty_pgrp = get_pid(tty->pgrp);
- lock_kernel();
+ tty_lock_nested();
if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
tty_vhangup(tty);
- unlock_kernel();
+ tty_unlock();
tty_kref_put(tty);
} else if (on_exit) {
struct pid *old_pgrp;
@@ -774,9 +779,9 @@ void disassociate_ctty(int on_exit)
void no_tty(void)
{
struct task_struct *tsk = current;
- lock_kernel();
+ tty_lock();
disassociate_ctty(0);
- unlock_kernel();
+ tty_unlock();
proc_clear_tty(tsk);
}
@@ -1013,19 +1018,19 @@ out:
* We don't put it into the syslog queue right now maybe in the future if
* really needed.
*
- * We must still hold the BKL and test the CLOSING flag for the moment.
+ * We must still hold the BTM and test the CLOSING flag for the moment.
*/
void tty_write_message(struct tty_struct *tty, char *msg)
{
if (tty) {
mutex_lock(&tty->atomic_write_lock);
- lock_kernel();
+ tty_lock();
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
- unlock_kernel();
+ tty_unlock();
tty->ops->write(tty, msg, strlen(msg));
} else
- unlock_kernel();
+ tty_unlock();
tty_write_unlock(tty);
}
return;
@@ -1208,18 +1213,18 @@ static int tty_driver_install_tty(struct tty_driver *driver,
int ret;
if (driver->ops->install) {
- lock_kernel();
+ tty_lock_nested(); /* already called with BTM held */
ret = driver->ops->install(driver, tty);
- unlock_kernel();
+ tty_unlock();
return ret;
}
if (tty_init_termios(tty) == 0) {
- lock_kernel();
+ tty_lock_nested();
tty_driver_kref_get(driver);
tty->count++;
driver->ttys[idx] = tty;
- unlock_kernel();
+ tty_unlock();
return 0;
}
return -ENOMEM;
@@ -1312,14 +1317,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
struct tty_struct *tty;
int retval;
- lock_kernel();
+ tty_lock_nested(); /* always called with tty lock held already */
+
/* Check if pty master is being opened multiple times */
if (driver->subtype == PTY_TYPE_MASTER &&
(driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
- unlock_kernel();
+ tty_unlock();
return ERR_PTR(-EIO);
}
- unlock_kernel();
+ tty_unlock();
/*
* First time open is complex, especially for PTY devices.
@@ -1363,9 +1369,9 @@ release_mem_out:
if (printk_ratelimit())
printk(KERN_INFO "tty_init_dev: ldisc open failed, "
"clearing slot %d\n", idx);
- lock_kernel();
+ tty_lock_nested();
release_tty(tty, idx);
- unlock_kernel();
+ tty_unlock();
return ERR_PTR(retval);
}
@@ -1510,10 +1516,10 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty_paranoia_check(tty, inode, "tty_release_dev"))
return 0;
- lock_kernel();
+ tty_lock();
check_tty_count(tty, "tty_release_dev");
- tty_fasync(-1, filp, 0);
+ __tty_fasync(-1, filp, 0);
idx = tty->index;
pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -1525,18 +1531,18 @@ int tty_release(struct inode *inode, struct file *filp)
if (idx < 0 || idx >= tty->driver->num) {
printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
"free (%s)\n", tty->name);
- unlock_kernel();
+ tty_unlock();
return 0;
}
if (!devpts) {
if (tty != tty->driver->ttys[idx]) {
- unlock_kernel();
+ tty_unlock();
printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
"for (%s)\n", idx, tty->name);
return 0;
}
if (tty->termios != tty->driver->termios[idx]) {
- unlock_kernel();
+ tty_unlock();
printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
"for (%s)\n",
idx, tty->name);
@@ -1554,21 +1560,21 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->driver->other &&
!(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
if (o_tty != tty->driver->other->ttys[idx]) {
- unlock_kernel();
+ tty_unlock();
printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
"not o_tty for (%s)\n",
idx, tty->name);
return 0 ;
}
if (o_tty->termios != tty->driver->other->termios[idx]) {
- unlock_kernel();
+ tty_unlock();
printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
"not o_termios for (%s)\n",
idx, tty->name);
return 0;
}
if (o_tty->link != tty) {
- unlock_kernel();
+ tty_unlock();
printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
return 0;
}
@@ -1577,7 +1583,7 @@ int tty_release(struct inode *inode, struct file *filp)
if (tty->ops->close)
tty->ops->close(tty, filp);
- unlock_kernel();
+ tty_unlock();
/*
* Sanity check: if tty->count is going to zero, there shouldn't be
* any waiters on tty->read_wait or tty->write_wait. We test the
@@ -1600,7 +1606,7 @@ int tty_release(struct inode *inode, struct file *filp)
opens on /dev/tty */
mutex_lock(&tty_mutex);
- lock_kernel();
+ tty_lock();
tty_closing = tty->count <= 1;
o_tty_closing = o_tty &&
(o_tty->count <= (pty_master ? 1 : 0));
@@ -1631,7 +1637,7 @@ int tty_release(struct inode *inode, struct file *filp)
printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
"active!\n", tty_name(tty, buf));
- unlock_kernel();
+ tty_unlock();
mutex_unlock(&tty_mutex);
schedule();
}
@@ -1696,7 +1702,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* check whether both sides are closing ... */
if (!tty_closing || (o_tty && !o_tty_closing)) {
- unlock_kernel();
+ tty_unlock();
return 0;
}
@@ -1716,7 +1722,7 @@ int tty_release(struct inode *inode, struct file *filp)
/* Make this pty number available for reallocation */
if (devpts)
devpts_kill_index(inode, idx);
- unlock_kernel();
+ tty_unlock();
return 0;
}
@@ -1758,12 +1764,12 @@ retry_open:
retval = 0;
mutex_lock(&tty_mutex);
- lock_kernel();
+ tty_lock();
if (device == MKDEV(TTYAUX_MAJOR, 0)) {
tty = get_current_tty();
if (!tty) {
- unlock_kernel();
+ tty_unlock();
mutex_unlock(&tty_mutex);
return -ENXIO;
}
@@ -1795,14 +1801,14 @@ retry_open:
goto got_driver;
}
}
- unlock_kernel();
+ tty_unlock();
mutex_unlock(&tty_mutex);
return -ENODEV;
}
driver = get_tty_driver(device, &index);
if (!driver) {
- unlock_kernel();
+ tty_unlock();
mutex_unlock(&tty_mutex);
return -ENODEV;
}
@@ -1812,7 +1818,7 @@ got_driver:
tty = tty_driver_lookup_tty(driver, inode, index);
if (IS_ERR(tty)) {
- unlock_kernel();
+ tty_unlock();
mutex_unlock(&tty_mutex);
return PTR_ERR(tty);
}
@@ -1828,7 +1834,7 @@ got_driver:
mutex_unlock(&tty_mutex);
tty_driver_kref_put(driver);
if (IS_ERR(tty)) {
- unlock_kernel();
+ tty_unlock();
return PTR_ERR(tty);
}
@@ -1860,11 +1866,11 @@ got_driver:
#endif
tty_release(inode, filp);
if (retval != -ERESTARTSYS) {
- unlock_kernel();
+ tty_unlock();
return retval;
}
if (signal_pending(current)) {
- unlock_kernel();
+ tty_unlock();
return retval;
}
schedule();
@@ -1875,11 +1881,11 @@ got_driver:
filp->f_op = &tty_fops;
goto retry_open;
}
- unlock_kernel();
+ tty_unlock();
mutex_lock(&tty_mutex);
- lock_kernel();
+ tty_lock();
spin_lock_irq(¤t->sighand->siglock);
if (!noctty &&
current->signal->leader &&
@@ -1887,7 +1893,7 @@ got_driver:
tty->session == NULL)
__proc_set_tty(current, tty);
spin_unlock_irq(¤t->sighand->siglock);
- unlock_kernel();
+ tty_unlock();
mutex_unlock(&tty_mutex);
return 0;
}
@@ -1923,13 +1929,12 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)
return ret;
}
-static int tty_fasync(int fd, struct file *filp, int on)
+static int __tty_fasync(int fd, struct file *filp, int on)
{
struct tty_struct *tty;
unsigned long flags;
int retval = 0;
- lock_kernel();
tty = (struct tty_struct *)filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
goto out;
@@ -1963,7 +1968,15 @@ static int tty_fasync(int fd, struct file *filp, int on)
}
retval = 0;
out:
- unlock_kernel();
+ return retval;
+}
+
+static int tty_fasync(int fd, struct file *filp, int on)
+{
+ int retval;
+ tty_lock();
+ retval = __tty_fasync(fd, filp, on);
+ tty_unlock();
return retval;
}
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index 500e740..bddbe62 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -447,10 +447,10 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
if (ld->ops->open) {
int ret;
- /* BKL here locks verus a hangup event */
- lock_kernel();
+ /* BTM here locks versus a hangup event */
+ tty_lock_nested();
ret = ld->ops->open(tty);
- unlock_kernel();
+ tty_unlock();
return ret;
}
return 0;
@@ -553,7 +553,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (IS_ERR(new_ldisc))
return PTR_ERR(new_ldisc);
- lock_kernel();
+ tty_lock();
/*
* We need to look at the tty locking here for pty/tty pairs
* when both sides try to change in parallel.
@@ -567,12 +567,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
*/
if (tty->ldisc->ops->num == ldisc) {
- unlock_kernel();
+ tty_unlock();
tty_ldisc_put(new_ldisc);
return 0;
}
- unlock_kernel();
+ tty_unlock();
/*
* Problem: What do we do if this blocks ?
* We could deadlock here
@@ -594,7 +594,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
mutex_lock(&tty->ldisc_mutex);
}
- lock_kernel();
+ tty_lock();
set_bit(TTY_LDISC_CHANGING, &tty->flags);
@@ -607,7 +607,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
o_ldisc = tty->ldisc;
- unlock_kernel();
+ tty_unlock();
/*
* Make sure we don't change while someone holds a
* reference to the line discipline. The TTY_LDISC bit
@@ -633,14 +633,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
flush_scheduled_work();
mutex_lock(&tty->ldisc_mutex);
- lock_kernel();
+ tty_lock();
if (test_bit(TTY_HUPPED, &tty->flags)) {
/* We were raced by the hangup method. It will have stomped
the ldisc data and closed the ldisc down */
clear_bit(TTY_LDISC_CHANGING, &tty->flags);
mutex_unlock(&tty->ldisc_mutex);
tty_ldisc_put(new_ldisc);
- unlock_kernel();
+ tty_unlock();
return -EIO;
}
@@ -682,7 +682,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
if (o_work)
schedule_delayed_work(&o_tty->buf.work, 1);
mutex_unlock(&tty->ldisc_mutex);
- unlock_kernel();
+ tty_unlock();
return retval;
}
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index c1791a6..bcce46c 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp)
unsigned int currcons = iminor(inode) & 127;
int ret = 0;
- lock_kernel();
+ tty_lock();
if(currcons && !vc_cons_allocated(currcons-1))
ret = -ENXIO;
- unlock_kernel();
+ tty_unlock();
return ret;
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index bd1d116..47e029c 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2604,7 +2604,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
return -EFAULT;
ret = 0;
- lock_kernel();
+ tty_lock_nested(); /* already held, always */
switch (type)
{
@@ -2680,7 +2680,7 @@ int tioclinux(struct tty_struct *tty, unsigned long arg)
ret = -EINVAL;
break;
}
- unlock_kernel();
+ tty_unlock();
return ret;
}
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 6aa1028..0ebda0e 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
console = vc->vc_num;
- lock_kernel();
+ tty_lock();
if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD;
@@ -1334,7 +1334,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
ret = -ENOIOCTLCMD;
}
out:
- unlock_kernel();
+ tty_unlock();
return ret;
eperm:
ret = -EPERM;
@@ -1501,7 +1501,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
console = vc->vc_num;
- lock_kernel();
+ tty_lock();
if (!vc_cons_allocated(console)) { /* impossible? */
ret = -ENOIOCTLCMD;
@@ -1569,11 +1569,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
goto fallback;
}
out:
- unlock_kernel();
+ tty_unlock();
return ret;
fallback:
- unlock_kernel();
+ tty_unlock();
return vt_ioctl(tty, file, cmd, arg);
}
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 00c60e2..94f7727 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1069,7 +1069,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
int retval;
char *p;
- lock_kernel();
+ tty_lock();
if (minor == ISDN_MINOR_STATUS) {
if (!file->private_data) {
if (file->f_flags & O_NONBLOCK) {
@@ -1162,7 +1162,7 @@ isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
#endif
retval = -ENODEV;
out:
- unlock_kernel();
+ tty_unlock();
return retval;
}
@@ -1179,7 +1179,7 @@ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off
if (!dev->drivers)
return -ENODEV;
- lock_kernel();
+ tty_lock();
if (minor <= ISDN_MINOR_BMAX) {
printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
drvidx = isdn_minor2drv(minor);
@@ -1224,7 +1224,7 @@ isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off
#endif
retval = -ENODEV;
out:
- unlock_kernel();
+ tty_unlock();
return retval;
}
@@ -1235,7 +1235,7 @@ isdn_poll(struct file *file, poll_table * wait)
unsigned int minor = iminor(file->f_path.dentry->d_inode);
int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
- lock_kernel();
+ tty_lock();
if (minor == ISDN_MINOR_STATUS) {
poll_wait(file, &(dev->info_waitq), wait);
/* mask = POLLOUT | POLLWRNORM; */
@@ -1265,7 +1265,7 @@ isdn_poll(struct file *file, poll_table * wait)
#endif
mask = POLLERR;
out:
- unlock_kernel();
+ tty_unlock();
return mask;
}
@@ -1732,7 +1732,7 @@ isdn_open(struct inode *ino, struct file *filep)
int chidx;
int retval = -ENODEV;
- lock_kernel();
+ tty_lock();
if (minor == ISDN_MINOR_STATUS) {
infostruct *p;
@@ -1783,7 +1783,7 @@ isdn_open(struct inode *ino, struct file *filep)
#endif
out:
nonseekable_open(ino, filep);
- unlock_kernel();
+ tty_unlock();
return retval;
}
@@ -1792,7 +1792,7 @@ isdn_close(struct inode *ino, struct file *filep)
{
uint minor = iminor(ino);
- lock_kernel();
+ tty_lock();
if (minor == ISDN_MINOR_STATUS) {
infostruct *p = dev->infochain;
infostruct *q = NULL;
@@ -1826,7 +1826,7 @@ isdn_close(struct inode *ino, struct file *filep)
#endif
out:
- unlock_kernel();
+ tty_unlock();
return 0;
}
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
index 2881a66..279277e 100644
--- a/drivers/isdn/i4l/isdn_tty.c
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -1353,14 +1353,14 @@ isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
- lock_kernel();
+ tty_lock();
#ifdef ISDN_DEBUG_MODEM_IOCTL
printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
#endif
control = info->mcr;
status = info->msr;
- unlock_kernel();
+ tty_unlock();
return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
| ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1384,7 +1384,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
#endif
- lock_kernel();
+ tty_lock();
if (set & TIOCM_RTS)
info->mcr |= UART_MCR_RTS;
if (set & TIOCM_DTR) {
@@ -1406,7 +1406,7 @@ isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
isdn_tty_modem_hup(info, 1);
}
}
- unlock_kernel();
+ tty_unlock();
return 0;
}
diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c
index 24661cd..5a2fc1b 100644
--- a/drivers/serial/68360serial.c
+++ b/drivers/serial/68360serial.c
@@ -1705,7 +1705,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
printk("jiff=%lu...", jiffies);
#endif
- lock_kernel();
+ tty_lock_nested();
/* We go through the loop at least once because we can't tell
* exactly when the last character exits the shifter. There can
* be at least two characters waiting to be sent after the buffers
@@ -1734,7 +1734,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
bdp--;
} while (bdp->status & BD_SC_READY);
current->state = TASK_RUNNING;
- unlock_kernel();
+ tty_unlock();
#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
#endif
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 31f1723..0facf63 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -3924,7 +3924,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
* Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
* R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
*/
- lock_kernel();
+ tty_lock_nested();
orig_jiffies = jiffies;
while (info->xmit.head != info->xmit.tail || /* More in send queue */
(*info->ostatusadr & 0x007f) || /* more in FIFO */
@@ -3941,7 +3941,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
curr_time_usec - info->last_tx_active_usec;
}
set_current_state(TASK_RUNNING);
- unlock_kernel();
+ tty_unlock();
}
/*
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 7f28307..1bc580b 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1273,7 +1273,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
struct tty_port *port;
struct uart_port *uport;
- BUG_ON(!kernel_locked());
+ BUG_ON(!tty_locked());
if (!state)
return;
@@ -1369,7 +1369,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
if (port->type == PORT_UNKNOWN || port->fifosize == 0)
return;
- lock_kernel();
+ tty_lock_nested();
/*
* Set the check interval to be 1/5 of the estimated time to
@@ -1416,7 +1416,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
break;
}
set_current_state(TASK_RUNNING); /* might not be needed */
- unlock_kernel();
+ tty_unlock();
}
/*
@@ -1430,7 +1430,7 @@ static void uart_hangup(struct tty_struct *tty)
struct uart_state *state = tty->driver_data;
struct tty_port *port = &state->port;
- BUG_ON(!kernel_locked());
+ BUG_ON(!tty_locked());
pr_debug("uart_hangup(%d)\n", state->uart_port->line);
mutex_lock(&port->mutex);
@@ -1611,7 +1611,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp)
struct tty_port *port;
int retval, line = tty->index;
- BUG_ON(!kernel_locked());
+ BUG_ON(!tty_locked());
pr_debug("uart_open(%d) called\n", line);
/*
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 3873660..3138a29 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -709,17 +709,17 @@ int usb_serial_probe(struct usb_interface *interface,
int num_ports = 0;
int max_endpoints;
- lock_kernel(); /* guard against unloading a serial driver module */
+ tty_lock(); /* guard against unloading a serial driver module */
type = search_serial_device(interface);
if (!type) {
- unlock_kernel();
+ tty_unlock();
dbg("none matched");
return -ENODEV;
}
serial = create_serial(dev, interface, type);
if (!serial) {
- unlock_kernel();
+ tty_unlock();
dev_err(&interface->dev, "%s - out of memory\n", __func__);
return -ENOMEM;
}
@@ -729,7 +729,7 @@ int usb_serial_probe(struct usb_interface *interface,
const struct usb_device_id *id;
if (!try_module_get(type->driver.owner)) {
- unlock_kernel();
+ tty_unlock();
dev_err(&interface->dev,
"module get failed, exiting\n");
kfree(serial);
@@ -741,7 +741,7 @@ int usb_serial_probe(struct usb_interface *interface,
module_put(type->driver.owner);
if (retval) {
- unlock_kernel();
+ tty_unlock();
dbg("sub driver rejected device");
kfree(serial);
return retval;
@@ -813,7 +813,7 @@ int usb_serial_probe(struct usb_interface *interface,
* properly during a later invocation of usb_serial_probe
*/
if (num_bulk_in == 0 || num_bulk_out == 0) {
- unlock_kernel();
+ tty_unlock();
dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n");
kfree(serial);
return -ENODEV;
@@ -826,7 +826,7 @@ int usb_serial_probe(struct usb_interface *interface,
if (type == &usb_serial_generic_device) {
num_ports = num_bulk_out;
if (num_ports == 0) {
- unlock_kernel();
+ tty_unlock();
dev_err(&interface->dev,
"Generic device with no bulk out, not allowed.\n");
kfree(serial);
@@ -838,7 +838,7 @@ int usb_serial_probe(struct usb_interface *interface,
/* if this device type has a calc_num_ports function, call it */
if (type->calc_num_ports) {
if (!try_module_get(type->driver.owner)) {
- unlock_kernel();
+ tty_unlock();
dev_err(&interface->dev,
"module get failed, exiting\n");
kfree(serial);
@@ -869,7 +869,7 @@ int usb_serial_probe(struct usb_interface *interface,
max_endpoints = max(max_endpoints, num_interrupt_out);
max_endpoints = max(max_endpoints, (int)serial->num_ports);
serial->num_port_pointers = max_endpoints;
- unlock_kernel();
+ tty_unlock();
dbg("%s - setting up %d port structures for this device",
__func__, max_endpoints);
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index 182dd6f..6eef126 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -1108,7 +1108,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
charmap += 4 * cmapsz;
#endif
- unlock_kernel();
+ tty_unlock();
spin_lock_irq(&vga_lock);
/* First, the Sequencer */
vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1);
@@ -1192,7 +1192,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512)
vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0);
}
spin_unlock_irq(&vga_lock);
- lock_kernel();
+ tty_lock_nested();
return 0;
}
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 4409967..60b3d69 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -13,6 +13,7 @@
#include <linux/tty_driver.h>
#include <linux/tty_ldisc.h>
#include <linux/mutex.h>
+#include <linux/smp_lock.h>
#include <asm/system.h>
@@ -571,5 +572,173 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file,
extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
+/* functions for preparation of BKL removal */
+
+/*
+ * tty_lock_nested get the tty_lock while potentially holding it
+ *
+ * The Big TTY Mutex is a recursive lock, meaning you can take it
+ * from a thread that is already holding it.
+ * This is bad for a number of reasons, so tty_lock_nested should
+ * really be used as rarely as possible. If a code location can
+ * be shown to never get called with this held already, it should
+ * use tty_lock() instead.
+ */
+static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock)
+{
+ lock_kernel();
+}
+static inline void tty_lock(void) __acquires(kernel_lock)
+{
+ WARN_ON(kernel_locked());
+ lock_kernel();
+}
+static inline void tty_unlock(void) __releases(kernel_lock)
+{
+ unlock_kernel();
+}
+#define tty_locked() (kernel_locked())
+static inline int __reacquire_tty_lock(void)
+{
+ return 0;
+}
+static inline void __release_tty_lock(void)
+{
+}
+
+#define release_tty_lock(tsk) do { } while (0)
+#define reacquire_tty_lock(tsk) do { } while (0)
+
+/*
+ * mutex_lock_tty - lock a mutex without holding the BTM
+ *
+ * These three functions replace calls to mutex_lock
+ * in the tty layer, when locking on of the following
+ * mutexes:
+ * tty->ldisc_mutex
+ * tty->termios_mutex
+ * tty->atomic_write_lock
+ * port->mutex
+ * pn->all_ppp_mutex
+ *
+ * The reason we need these is to avoid an AB-BA deadlock
+ * with tty_lock(). When it can be shown that one of the
+ * above mutexes is either never acquired with the tty_lock()
+ * held, or is never held when tty_lock() is acquired, that
+ * mutex should be converted back to the regular mutex_lock
+ * function.
+ *
+ * In order to annotate the lock order, the mutex_lock_tty_on
+ * and mutex_lock_tty_off versions should be used whereever
+ * possible, to show if the mutex is used with or without
+ * tty_lock already held.
+ */
+#define mutex_lock_tty(mutex) \
+({ \
+ if (!mutex_trylock(mutex)) { \
+ if (tty_locked()) { \
+ __release_tty_lock(); \
+ mutex_lock(mutex); \
+ __reacquire_tty_lock(); \
+ } else \
+ mutex_lock(mutex); \
+ } \
+})
+
+#define mutex_lock_tty_on(mutex) \
+({ \
+ if (!mutex_trylock(mutex)) { \
+ if (!WARN_ON(!tty_locked())) { \
+ __release_tty_lock(); \
+ mutex_lock(mutex); \
+ __reacquire_tty_lock(); \
+ } else \
+ mutex_lock(mutex); \
+ } \
+})
+
+#define mutex_lock_tty_off(mutex) \
+({ \
+ if (!mutex_trylock(mutex)) { \
+ if (WARN_ON(tty_locked())) { \
+ __release_tty_lock(); \
+ mutex_lock(mutex); \
+ __reacquire_tty_lock(); \
+ } else \
+ mutex_lock(mutex); \
+ } \
+})
+
+#define mutex_lock_interruptible_tty(mutex) \
+({ \
+ int __ret = 0; \
+ if (!mutex_trylock(mutex)) { \
+ if (tty_locked()) { \
+ __release_tty_lock(); \
+ __ret = mutex_lock_interruptible(mutex); \
+ __reacquire_tty_lock(); \
+ } else \
+ __ret = mutex_lock_interruptible(mutex); \
+ } \
+ __ret; \
+})
+
+/*
+ * wait_event*_tty -- wait for a condition with the tty lock held
+ *
+ * similar to the mutex_lock_tty family, these should be used when
+ * waiting for an event in a code location that may get called
+ * while tty_lock is held.
+ *
+ * The problem is that the condition we are waiting for might
+ * only become true if another thread runs that needs the tty_lock
+ * in order to get there.
+ *
+ * None of these should be needed and all callers should be removed
+ * when either the caller or the condition it waits for can be show
+ * to not rely on the tty_lock.
+ */
+#define wait_event_tty(wq, condition) \
+do { \
+ if (condition) \
+ break; \
+ release_tty_lock(current); \
+ __wait_event(wq, condition); \
+ reacquire_tty_lock(current); \
+} while (0)
+
+#define wait_event_timeout_tty(wq, condition, timeout) \
+({ \
+ long __ret = timeout; \
+ if (!(condition)) { \
+ release_tty_lock(current); \
+ __wait_event_timeout(wq, condition, __ret); \
+ reacquire_tty_lock(current); \
+ } \
+ __ret; \
+})
+
+#define wait_event_interruptible_tty(wq, condition) \
+({ \
+ int __ret = 0; \
+ if (!(condition)) { \
+ release_tty_lock(current); \
+ __wait_event_interruptible(wq, condition, __ret); \
+ reacquire_tty_lock(current); \
+ } \
+ __ret; \
+})
+
+#define wait_event_interruptible_timeout_tty(wq, condition, timeout) \
+({ \
+ long __ret = timeout; \
+ if (!(condition)) { \
+ release_tty_lock(current); \
+ __wait_event_interruptible_timeout(wq, condition, __ret); \
+ reacquire_tty_lock(current); \
+ } \
+ __ret; \
+})
+
#endif /* __KERNEL__ */
#endif
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [RFC 2/9] tty: make atomic_write_lock release tty_lock
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
2010-03-30 20:56 ` [RFC 1/9] tty: replace BKL with a new tty_lock Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-30 20:56 ` [RFC 3/9] tty: make tty_port->mutex nest under tty_lock Arnd Bergmann
` (7 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/char/tty_io.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 25b82eb..ef21e1d 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -915,7 +915,7 @@ int tty_write_lock(struct tty_struct *tty, int ndelay)
if (!mutex_trylock(&tty->atomic_write_lock)) {
if (ndelay)
return -EAGAIN;
- if (mutex_lock_interruptible(&tty->atomic_write_lock))
+ if (mutex_lock_interruptible_tty(&tty->atomic_write_lock))
return -ERESTARTSYS;
}
return 0;
@@ -1024,7 +1024,7 @@ out:
void tty_write_message(struct tty_struct *tty, char *msg)
{
if (tty) {
- mutex_lock(&tty->atomic_write_lock);
+ mutex_lock_tty_off(&tty->atomic_write_lock);
tty_lock();
if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
tty_unlock();
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [RFC 3/9] tty: make tty_port->mutex nest under tty_lock
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
2010-03-30 20:56 ` [RFC 1/9] tty: replace BKL with a new tty_lock Arnd Bergmann
2010-03-30 20:56 ` [RFC 2/9] tty: make atomic_write_lock release tty_lock Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-30 20:56 ` [RFC 4/9] tty: make termios mutex " Arnd Bergmann
` (6 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/char/mxser.c | 10 +++++-----
drivers/char/tty_port.c | 4 ++--
drivers/serial/serial_core.c | 32 ++++++++++++++++----------------
3 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index e0c5d2a..25ff7e6 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1078,7 +1078,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
return;
if (tty_port_close_start(port, tty, filp) == 0)
return;
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
mxser_close_port(port);
mxser_flush_buffer(tty);
mxser_shutdown_port(port);
@@ -1512,7 +1512,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
port = &ip->port;
memset(&ms, 0, sizeof(ms));
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
if (!ip->ioaddr)
goto copy;
@@ -1558,7 +1558,7 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
ip = &mxser_boards[i].ports[j];
port = &ip->port;
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
if (!ip->ioaddr) {
mutex_unlock(&port->mutex);
continue;
@@ -1705,12 +1705,12 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
switch (cmd) {
case TIOCGSERIAL:
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
retval = mxser_get_serial_info(tty, argp);
mutex_unlock(&port->mutex);
return retval;
case TIOCSSERIAL:
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
retval = mxser_set_serial_info(tty, argp);
mutex_unlock(&port->mutex);
return retval;
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index a3bd1d0..5ad1446 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -118,7 +118,7 @@ EXPORT_SYMBOL(tty_port_tty_set);
static void tty_port_shutdown(struct tty_port *port)
{
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
if (port->ops->shutdown && !port->console &&
test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
port->ops->shutdown(port);
@@ -424,7 +424,7 @@ int tty_port_open(struct tty_port *port, struct tty_struct *tty,
* port mutex.
*/
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
clear_bit(TTY_IO_ERROR, &tty->flags);
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 1bc580b..81be0c9 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -647,7 +647,7 @@ static int uart_get_info(struct uart_state *state,
/* Ensure the state we copy is consistent and no hardware changes
occur as we go */
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
tmp.type = uport->type;
tmp.line = uport->line;
@@ -706,7 +706,7 @@ static int uart_set_info(struct uart_state *state,
* module insertion/removal doesn't change anything
* under us.
*/
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
change_irq = !(uport->flags & UPF_FIXED_PORT)
&& new_serial.irq != uport->irq;
@@ -913,7 +913,7 @@ static int uart_tiocmget(struct tty_struct *tty, struct file *file)
struct uart_port *uport = state->uart_port;
int result = -EIO;
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
if ((!file || !tty_hung_up_p(file)) &&
!(tty->flags & (1 << TTY_IO_ERROR))) {
result = uport->mctrl;
@@ -936,7 +936,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
struct tty_port *port = &state->port;
int ret = -EIO;
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
if ((!file || !tty_hung_up_p(file)) &&
!(tty->flags & (1 << TTY_IO_ERROR))) {
uart_update_mctrl(uport, set, clear);
@@ -952,7 +952,7 @@ static int uart_break_ctl(struct tty_struct *tty, int break_state)
struct tty_port *port = &state->port;
struct uart_port *uport = state->uart_port;
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
if (uport->type != PORT_UNKNOWN)
uport->ops->break_ctl(uport, break_state);
@@ -975,7 +975,7 @@ static int uart_do_autoconfig(struct uart_state *state)
* changing, and hence any extra opens of the port while
* we're auto-configuring.
*/
- if (mutex_lock_interruptible(&port->mutex))
+ if (mutex_lock_interruptible_tty(&port->mutex))
return -ERESTARTSYS;
ret = -EBUSY;
@@ -1159,7 +1159,7 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
if (ret != -ENOIOCTLCMD)
goto out;
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
if (tty_hung_up_p(filp)) {
ret = -EIO;
@@ -1283,7 +1283,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
pr_debug("uart_close(%d) called\n", uport->line);
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
if (tty_hung_up_p(filp))
goto done;
@@ -1433,7 +1433,7 @@ static void uart_hangup(struct tty_struct *tty)
BUG_ON(!tty_locked());
pr_debug("uart_hangup(%d)\n", state->uart_port->line);
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
if (port->flags & ASYNC_NORMAL_ACTIVE) {
uart_flush_buffer(tty);
uart_shutdown(state);
@@ -1547,7 +1547,7 @@ uart_block_til_ready(struct file *filp, struct uart_state *state)
mutex_unlock(&port->mutex);
schedule();
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
if (signal_pending(current))
break;
@@ -1575,7 +1575,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line)
state = drv->state + line;
port = &state->port;
- if (mutex_lock_interruptible(&port->mutex)) {
+ if (mutex_lock_interruptible_tty(&port->mutex)) {
ret = -ERESTARTSYS;
goto err;
}
@@ -1732,7 +1732,7 @@ static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
}
if (capable(CAP_SYS_ADMIN)) {
- mutex_lock(&port->mutex);
+ mutex_lock_tty_off(&port->mutex);
pm_state = state->pm_state;
if (pm_state)
uart_change_pm(state, 0);
@@ -2011,7 +2011,7 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
struct device *tty_dev;
struct uart_match match = {uport, drv};
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
if (device_may_wakeup(tty_dev)) {
@@ -2077,7 +2077,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
struct uart_match match = {uport, drv};
struct ktermios termios;
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
tty_dev = device_find_child(uport->dev, &match, serial_match_port);
if (!uport->suspended && device_may_wakeup(tty_dev)) {
@@ -2436,7 +2436,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
port = &state->port;
mutex_lock(&port_mutex);
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
if (state->uart_port) {
ret = -EINVAL;
goto out;
@@ -2509,7 +2509,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
* Mark the port "dead" - this prevents any opens from
* succeeding while we shut down the port.
*/
- mutex_lock(&port->mutex);
+ mutex_lock_tty(&port->mutex);
uport->flags |= UPF_DEAD;
mutex_unlock(&port->mutex);
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [RFC 4/9] tty: make termios mutex nest under tty_lock
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
` (2 preceding siblings ...)
2010-03-30 20:56 ` [RFC 3/9] tty: make tty_port->mutex nest under tty_lock Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-30 20:56 ` [RFC 5/9] tty: make ldisc_mutex " Arnd Bergmann
` (5 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/char/pty.c | 2 +-
drivers/char/tty_io.c | 4 ++--
drivers/char/tty_ioctl.c | 34 +++++++++++++++++-----------------
drivers/char/tty_ldisc.c | 4 ++--
drivers/net/irda/irtty-sir.c | 5 +++--
drivers/staging/strip/strip.c | 2 +-
6 files changed, 26 insertions(+), 25 deletions(-)
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index f02ff21..72fb501 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -231,7 +231,7 @@ int pty_resize(struct tty_struct *tty, struct winsize *ws)
struct tty_struct *pty = tty->link;
/* For a PTY we need to lock the tty side */
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty_off(&tty->termios_mutex);
if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
goto done;
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index ef21e1d..91cc978 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2028,7 +2028,7 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg)
{
int err;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty_off(&tty->termios_mutex);
err = copy_to_user(arg, &tty->winsize, sizeof(*arg));
mutex_unlock(&tty->termios_mutex);
@@ -2051,7 +2051,7 @@ int tty_do_resize(struct tty_struct *tty, struct winsize *ws)
unsigned long flags;
/* Lock the tty */
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty_off(&tty->termios_mutex);
if (!memcmp(ws, &tty->winsize, sizeof(*ws)))
goto done;
/* Get the PID values and reference them so we can
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 6bd5f88..c9b385e 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -103,7 +103,7 @@ EXPORT_SYMBOL(tty_driver_flush_buffer);
void tty_throttle(struct tty_struct *tty)
{
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
/* check TTY_THROTTLED first so it indicates our state */
if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
tty->ops->throttle)
@@ -127,7 +127,7 @@ EXPORT_SYMBOL(tty_throttle);
void tty_unthrottle(struct tty_struct *tty)
{
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->ops->unthrottle)
tty->ops->unthrottle(tty);
@@ -510,7 +510,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
/* FIXME: we need to decide on some locking/ordering semantics
for the set_termios notification eventually */
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
old_termios = *tty->termios;
*tty->termios = *new_termios;
unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
@@ -571,7 +571,7 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
if (retval)
return retval;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
mutex_unlock(&tty->termios_mutex);
@@ -625,14 +625,14 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
static void copy_termios(struct tty_struct *tty, struct ktermios *kterm)
{
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
memcpy(kterm, tty->termios, sizeof(struct ktermios));
mutex_unlock(&tty->termios_mutex);
}
static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm)
{
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
memcpy(kterm, tty->termios_locked, sizeof(struct ktermios));
mutex_unlock(&tty->termios_mutex);
}
@@ -681,7 +681,7 @@ static int set_termiox(struct tty_struct *tty, void __user *arg, int opt)
return -EINTR;
}
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
if (tty->ops->set_termiox)
tty->ops->set_termiox(tty, &tnew);
mutex_unlock(&tty->termios_mutex);
@@ -719,7 +719,7 @@ static int get_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
{
struct sgttyb tmp;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
tmp.sg_ispeed = tty->termios->c_ispeed;
tmp.sg_ospeed = tty->termios->c_ospeed;
tmp.sg_erase = tty->termios->c_cc[VERASE];
@@ -780,7 +780,7 @@ static int set_sgttyb(struct tty_struct *tty, struct sgttyb __user *sgttyb)
if (copy_from_user(&tmp, sgttyb, sizeof(tmp)))
return -EFAULT;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
termios = *tty->termios;
termios.c_cc[VERASE] = tmp.sg_erase;
termios.c_cc[VKILL] = tmp.sg_kill;
@@ -801,7 +801,7 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
{
struct tchars tmp;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
tmp.t_intrc = tty->termios->c_cc[VINTR];
tmp.t_quitc = tty->termios->c_cc[VQUIT];
tmp.t_startc = tty->termios->c_cc[VSTART];
@@ -818,7 +818,7 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
if (copy_from_user(&tmp, tchars, sizeof(tmp)))
return -EFAULT;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
tty->termios->c_cc[VINTR] = tmp.t_intrc;
tty->termios->c_cc[VQUIT] = tmp.t_quitc;
tty->termios->c_cc[VSTART] = tmp.t_startc;
@@ -835,7 +835,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
{
struct ltchars tmp;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
tmp.t_suspc = tty->termios->c_cc[VSUSP];
/* what is dsuspc anyway? */
tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
@@ -855,7 +855,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
return -EFAULT;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
tty->termios->c_cc[VSUSP] = tmp.t_suspc;
/* what is dsuspc anyway? */
tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
@@ -913,7 +913,7 @@ static int tty_change_softcar(struct tty_struct *tty, int arg)
int bit = arg ? CLOCAL : 0;
struct ktermios old;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
old = *tty->termios;
tty->termios->c_cflag &= ~CLOCAL;
tty->termios->c_cflag |= bit;
@@ -1022,7 +1022,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
if (user_termios_to_kernel_termios(&kterm,
(struct termios __user *) arg))
return -EFAULT;
- mutex_lock(&real_tty->termios_mutex);
+ mutex_lock_tty(&real_tty->termios_mutex);
memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
mutex_unlock(&real_tty->termios_mutex);
return 0;
@@ -1039,7 +1039,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
if (user_termios_to_kernel_termios_1(&kterm,
(struct termios __user *) arg))
return -EFAULT;
- mutex_lock(&real_tty->termios_mutex);
+ mutex_lock_tty(&real_tty->termios_mutex);
memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios));
mutex_unlock(&real_tty->termios_mutex);
return ret;
@@ -1049,7 +1049,7 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
struct termiox ktermx;
if (real_tty->termiox == NULL)
return -EINVAL;
- mutex_lock(&real_tty->termios_mutex);
+ mutex_lock_tty(&real_tty->termios_mutex);
memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox));
mutex_unlock(&real_tty->termios_mutex);
if (copy_to_user(p, &ktermx, sizeof(struct termiox)))
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index bddbe62..af5b4a7 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -428,7 +428,7 @@ EXPORT_SYMBOL_GPL(tty_ldisc_flush);
static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
{
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
tty->termios->c_line = num;
mutex_unlock(&tty->termios_mutex);
}
@@ -695,7 +695,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
static void tty_reset_termios(struct tty_struct *tty)
{
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
*tty->termios = tty->driver->init_termios;
tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios);
tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 20f9bc6..8938193 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -33,6 +33,7 @@
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/mutex.h>
+#include <linux/sched.h>
#include <net/irda/irda.h>
#include <net/irda/irda_device.h>
@@ -122,7 +123,7 @@ static int irtty_change_speed(struct sir_dev *dev, unsigned speed)
tty = priv->tty;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
old_termios = *(tty->termios);
cflag = tty->termios->c_cflag;
tty_encode_baud_rate(tty, speed, speed);
@@ -279,7 +280,7 @@ static inline void irtty_stop_receiver(struct tty_struct *tty, int stop)
struct ktermios old_termios;
int cflag;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty(&tty->termios_mutex);
old_termios = *(tty->termios);
cflag = tty->termios->c_cflag;
diff --git a/drivers/staging/strip/strip.c b/drivers/staging/strip/strip.c
index 698aade..f7a90bc 100644
--- a/drivers/staging/strip/strip.c
+++ b/drivers/staging/strip/strip.c
@@ -775,7 +775,7 @@ static void set_baud(struct tty_struct *tty, speed_t baudrate)
{
struct ktermios old_termios;
- mutex_lock(&tty->termios_mutex);
+ mutex_lock_tty_off(&tty->termios_mutex);
old_termios =*(tty->termios);
tty_encode_baud_rate(tty, baudrate, baudrate);
tty->ops->set_termios(tty, &old_termios);
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [RFC 5/9] tty: make ldisc_mutex nest under tty_lock
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
` (3 preceding siblings ...)
2010-03-30 20:56 ` [RFC 4/9] tty: make termios mutex " Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-30 20:56 ` [RFC 6/9] tty: never hold tty_lock() while getting tty_mutex Arnd Bergmann
` (4 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/char/tty_io.c | 2 +-
drivers/char/tty_ldisc.c | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 91cc978..aeab6cb 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -1279,7 +1279,7 @@ static int tty_reopen(struct tty_struct *tty)
tty->count++;
tty->driver = driver; /* N.B. why do this every time?? */
- mutex_lock(&tty->ldisc_mutex);
+ mutex_lock_tty_on(&tty->ldisc_mutex);
WARN_ON(!test_bit(TTY_LDISC, &tty->flags));
mutex_unlock(&tty->ldisc_mutex);
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index af5b4a7..946ac05 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -580,7 +580,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
tty_wait_until_sent(tty, 0);
- mutex_lock(&tty->ldisc_mutex);
+ mutex_lock_tty_off(&tty->ldisc_mutex);
/*
* We could be midstream of another ldisc change which has
@@ -591,7 +591,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
mutex_unlock(&tty->ldisc_mutex);
wait_event(tty_ldisc_wait,
test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
- mutex_lock(&tty->ldisc_mutex);
+ mutex_lock_tty_off(&tty->ldisc_mutex);
}
tty_lock();
@@ -632,7 +632,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
flush_scheduled_work();
- mutex_lock(&tty->ldisc_mutex);
+ mutex_lock_tty_off(&tty->ldisc_mutex);
tty_lock();
if (test_bit(TTY_HUPPED, &tty->flags)) {
/* We were raced by the hangup method. It will have stomped
@@ -779,7 +779,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
*
* Avoid racing set_ldisc or tty_ldisc_release
*/
- mutex_lock(&tty->ldisc_mutex);
+ mutex_lock_tty_on(&tty->ldisc_mutex);
tty_ldisc_halt(tty);
/* At this point we have a closed ldisc and we want to
reopen it. We could defer this to the next open but
@@ -854,7 +854,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
tty_ldisc_halt(tty);
flush_scheduled_work();
- mutex_lock(&tty->ldisc_mutex);
+ mutex_lock_tty_on(&tty->ldisc_mutex);
/*
* Now kill off the ldisc
*/
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [RFC 6/9] tty: never hold tty_lock() while getting tty_mutex
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
` (4 preceding siblings ...)
2010-03-30 20:56 ` [RFC 5/9] tty: make ldisc_mutex " Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-30 20:56 ` [RFC 7/9] ppp: use big tty mutex Arnd Bergmann
` (3 subsequent siblings)
9 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann,
Arnd Bergmann
From: Arnd Bergmann <arnd@relay.de.ibm.com>
This avoids having to annotate every mutex_lock(&tty_mutex)
as mutex_lock_tty.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/char/pty.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index 72fb501..0a87b52 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -638,9 +638,11 @@ static int __ptmx_open(struct inode *inode, struct file *filp)
if (index < 0)
return index;
+ tty_unlock();
mutex_lock(&tty_mutex);
tty = tty_init_dev(ptm_driver, index, 1);
mutex_unlock(&tty_mutex);
+ tty_lock();
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [RFC 7/9] ppp: use big tty mutex
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
` (5 preceding siblings ...)
2010-03-30 20:56 ` [RFC 6/9] tty: never hold tty_lock() while getting tty_mutex Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-31 4:37 ` Américo Wang
2010-03-30 20:56 ` [RFC 8/9] tty: release tty lock when blocking Arnd Bergmann
` (2 subsequent siblings)
9 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann
ppp interacts with the tty layer, so it should
take the BTM instead of the BKL.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/net/ppp_generic.c | 29 +++++++++++++++--------------
1 files changed, 15 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 6d61602..bc89a1b 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -40,7 +40,7 @@
#include <linux/if_arp.h>
#include <linux/ip.h>
#include <linux/tcp.h>
-#include <linux/smp_lock.h>
+#include <linux/tty.h>
#include <linux/spinlock.h>
#include <linux/rwsem.h>
#include <linux/stddef.h>
@@ -362,7 +362,8 @@ static const int npindex_to_ethertype[NUM_NP] = {
*/
static int ppp_open(struct inode *inode, struct file *file)
{
- cycle_kernel_lock();
+ tty_lock();
+ tty_unlock();
/*
* This could (should?) be enforced by the permissions on /dev/ppp.
*/
@@ -584,7 +585,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
* this fd and reopening /dev/ppp.
*/
err = -EINVAL;
- lock_kernel();
+ tty_lock();
if (pf->kind == INTERFACE) {
ppp = PF_TO_PPP(pf);
if (file == ppp->owner)
@@ -596,7 +597,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} else
printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%ld\n",
atomic_long_read(&file->f_count));
- unlock_kernel();
+ tty_unlock();
return err;
}
@@ -604,7 +605,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct channel *pch;
struct ppp_channel *chan;
- lock_kernel();
+ tty_lock();
pch = PF_TO_CHANNEL(pf);
switch (cmd) {
@@ -626,7 +627,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
err = chan->ops->ioctl(chan, cmd, arg);
up_read(&pch->chan_sem);
}
- unlock_kernel();
+ tty_unlock();
return err;
}
@@ -636,7 +637,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
return -EINVAL;
}
- lock_kernel();
+ tty_lock();
ppp = PF_TO_PPP(pf);
switch (cmd) {
case PPPIOCSMRU:
@@ -784,7 +785,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
default:
err = -ENOTTY;
}
- unlock_kernel();
+ tty_unlock();
return err;
}
@@ -797,7 +798,7 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
struct ppp_net *pn;
int __user *p = (int __user *)arg;
- lock_kernel();
+ tty_lock();
switch (cmd) {
case PPPIOCNEWUNIT:
/* Create a new ppp unit */
@@ -820,7 +821,7 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
break;
err = -ENXIO;
pn = ppp_pernet(net);
- mutex_lock(&pn->all_ppp_mutex);
+ mutex_lock_tty_on(&pn->all_ppp_mutex);
ppp = ppp_find_unit(pn, unit);
if (ppp) {
atomic_inc(&ppp->file.refcnt);
@@ -848,7 +849,7 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf,
default:
err = -ENOTTY;
}
- unlock_kernel();
+ tty_unlock();
return err;
}
@@ -2553,7 +2554,7 @@ ppp_create_interface(struct net *net, int unit, int *retp)
dev_net_set(dev, net);
ret = -EEXIST;
- mutex_lock(&pn->all_ppp_mutex);
+ mutex_lock_tty_on(&pn->all_ppp_mutex);
if (unit < 0) {
unit = unit_get(&pn->units_idr, ppp);
@@ -2628,7 +2629,7 @@ static void ppp_shutdown_interface(struct ppp *ppp)
struct ppp_net *pn;
pn = ppp_pernet(ppp->ppp_net);
- mutex_lock(&pn->all_ppp_mutex);
+ mutex_lock_tty(&pn->all_ppp_mutex);
/* This will call dev_close() for us. */
ppp_lock(ppp);
@@ -2737,7 +2738,7 @@ ppp_connect_channel(struct channel *pch, int unit)
pn = ppp_pernet(pch->chan_net);
- mutex_lock(&pn->all_ppp_mutex);
+ mutex_lock_tty_on(&pn->all_ppp_mutex);
ppp = ppp_find_unit(pn, unit);
if (!ppp)
goto out;
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [RFC 8/9] tty: release tty lock when blocking
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
` (6 preceding siblings ...)
2010-03-30 20:56 ` [RFC 7/9] ppp: use big tty mutex Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-30 20:56 ` [RFC 9/9] tty: implement BTM as mutex instead of BKL Arnd Bergmann
2010-03-30 22:37 ` [RFC 0/9] BKL conversion in TTY drivers Alan Cox
9 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann,
Arnd Bergmann
From: Arnd Bergmann <arnd@relay.de.ibm.com>
All wait_event variants and work queue functions
that block on another thread need to release the
tty lock if the thread they are waiting on might
take it.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/char/cyclades.c | 4 ++--
drivers/char/istallion.c | 12 ++++++------
drivers/char/n_r3964.c | 2 +-
drivers/char/synclink.c | 2 ++
drivers/char/tty_buffer.c | 2 +-
drivers/char/tty_ioctl.c | 2 +-
drivers/char/tty_ldisc.c | 17 ++++++++++++++---
drivers/char/tty_port.c | 2 +-
drivers/char/vt_ioctl.c | 2 +-
drivers/serial/crisv10.c | 4 ++--
drivers/usb/class/cdc-acm.c | 2 +-
11 files changed, 32 insertions(+), 19 deletions(-)
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 350595e..6dedc0c 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -1607,7 +1607,7 @@ static int cy_open(struct tty_struct *tty, struct file *filp)
* If the port is the middle of closing, bail out now
*/
if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
- wait_event_interruptible(info->port.close_wait,
+ wait_event_interruptible_tty(info->port.close_wait,
!(info->port.flags & ASYNC_CLOSING));
return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
}
@@ -2780,7 +2780,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
/* note the counters on entry */
cnow = info->icount;
spin_unlock_irqrestore(&info->card->card_lock, flags);
- ret_val = wait_event_interruptible(info->port.delta_msr_wait,
+ ret_val = wait_event_interruptible_tty(info->port.delta_msr_wait,
cy_cflags_changed(info, arg, &cnow));
break;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 39853b4..7c6728b 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -952,7 +952,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l
* order of opens and closes may not be preserved across shared
* memory, so we must wait until it is complete.
*/
- wait_event_interruptible(portp->raw_wait,
+ wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_CLOSING, &portp->state));
if (signal_pending(current)) {
return -ERESTARTSYS;
@@ -987,7 +987,7 @@ static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned l
set_bit(ST_OPENING, &portp->state);
spin_unlock_irqrestore(&brd_lock, flags);
- wait_event_interruptible(portp->raw_wait,
+ wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_OPENING, &portp->state));
if (signal_pending(current))
rc = -ERESTARTSYS;
@@ -1018,7 +1018,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
* occurs on this port.
*/
if (wait) {
- wait_event_interruptible(portp->raw_wait,
+ wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_CLOSING, &portp->state));
if (signal_pending(current)) {
return -ERESTARTSYS;
@@ -1050,7 +1050,7 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
* to come back.
*/
rc = 0;
- wait_event_interruptible(portp->raw_wait,
+ wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_CLOSING, &portp->state));
if (signal_pending(current))
rc = -ERESTARTSYS;
@@ -1071,14 +1071,14 @@ static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned
static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
{
- wait_event_interruptible(portp->raw_wait,
+ wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_CMDING, &portp->state));
if (signal_pending(current))
return -ERESTARTSYS;
stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
- wait_event_interruptible(portp->raw_wait,
+ wait_event_interruptible_tty(portp->raw_wait,
!test_bit(ST_CMDING, &portp->state));
if (signal_pending(current))
return -ERESTARTSYS;
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 2bd0e22..f771414 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -1079,7 +1079,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file,
goto unlock;
}
/* block until there is a message: */
- wait_event_interruptible(pInfo->read_wait,
+ wait_event_interruptible_tty(pInfo->read_wait,
(pMsg = remove_msg(pInfo, pClient)));
}
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index c7af06b..c2252bd 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2723,7 +2723,9 @@ static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr)
for(;;) {
+ release_tty_lock(current);
schedule();
+ reacquire_tty_lock(current);
if (signal_pending(current)) {
rc = -ERESTARTSYS;
break;
diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
index 7ee5216..b532adc 100644
--- a/drivers/char/tty_buffer.c
+++ b/drivers/char/tty_buffer.c
@@ -143,7 +143,7 @@ void tty_buffer_flush(struct tty_struct *tty)
if (test_bit(TTY_FLUSHING, &tty->flags)) {
set_bit(TTY_FLUSHPENDING, &tty->flags);
spin_unlock_irqrestore(&tty->buf.lock, flags);
- wait_event(tty->read_wait,
+ wait_event_tty(tty->read_wait,
test_bit(TTY_FLUSHPENDING, &tty->flags) == 0);
return;
} else
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index c9b385e..06255bc 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -155,7 +155,7 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
#endif
if (!timeout)
timeout = MAX_SCHEDULE_TIMEOUT;
- if (wait_event_interruptible_timeout(tty->write_wait,
+ if (wait_event_interruptible_timeout_tty(tty->write_wait,
!tty_chars_in_buffer(tty), timeout) >= 0) {
if (tty->ops->wait_until_sent)
tty->ops->wait_until_sent(tty, timeout);
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index 946ac05..759478d 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -331,8 +331,8 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
{
struct tty_ldisc *ld;
- /* wait_event is a macro */
- wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL);
+ /* need to give up BTM when coming from paste_selection */
+ wait_event_tty(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL);
return ld;
}
EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
@@ -525,8 +525,17 @@ static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
static int tty_ldisc_halt(struct tty_struct *tty)
{
+ int ret;
clear_bit(TTY_LDISC, &tty->flags);
- return cancel_delayed_work_sync(&tty->buf.work);
+ if (tty_locked()) {
+ __release_tty_lock();
+ ret = cancel_delayed_work_sync(&tty->buf.work);
+ __reacquire_tty_lock();
+ } else {
+ ret = cancel_delayed_work_sync(&tty->buf.work);
+
+ }
+ return ret;
}
/**
@@ -852,7 +861,9 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
*/
tty_ldisc_halt(tty);
+ release_tty_lock(current);
flush_scheduled_work();
+ reacquire_tty_lock(current);
mutex_lock_tty_on(&tty->ldisc_mutex);
/*
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c
index 5ad1446..d78ef81 100644
--- a/drivers/char/tty_port.c
+++ b/drivers/char/tty_port.c
@@ -231,7 +231,7 @@ int tty_port_block_til_ready(struct tty_port *port,
/* block if port is in the process of being closed */
if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
- wait_event_interruptible(port->close_wait,
+ wait_event_interruptible_tty(port->close_wait,
!(port->flags & ASYNC_CLOSING));
if (port->flags & ASYNC_HUP_NOTIFY)
return -EAGAIN;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 0ebda0e..d54f73f 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -133,7 +133,7 @@ static void vt_event_wait(struct vt_event_wait *vw)
list_add(&vw->list, &vt_events);
spin_unlock_irqrestore(&vt_event_lock, flags);
/* Wait for it to pass */
- wait_event_interruptible(vt_event_waitqueue, vw->done);
+ wait_event_interruptible_tty(vt_event_waitqueue, vw->done);
/* Dequeue it */
spin_lock_irqsave(&vt_event_lock, flags);
list_del(&vw->list);
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c
index 0facf63..639d0ab 100644
--- a/drivers/serial/crisv10.c
+++ b/drivers/serial/crisv10.c
@@ -3981,7 +3981,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible(info->close_wait,
+ wait_event_interruptible_tty(info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
if (info->flags & ASYNC_HUP_NOTIFY)
@@ -4139,7 +4139,7 @@ rs_open(struct tty_struct *tty, struct file * filp)
*/
if (tty_hung_up_p(filp) ||
(info->flags & ASYNC_CLOSING)) {
- wait_event_interruptible(info->close_wait,
+ wait_event_interruptible_tty(info->close_wait,
!(info->flags & ASYNC_CLOSING));
#ifdef SERIAL_DO_RESTART
return ((info->flags & ASYNC_HUP_NOTIFY) ?
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index be6331e..a4abe2b 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -645,7 +645,7 @@ static void acm_port_down(struct acm *acm, int drain)
acm_set_control(acm, acm->ctrlout = 0);
/* try letting the last writes drain naturally */
if (drain) {
- wait_event_interruptible_timeout(acm->drain_wait,
+ wait_event_interruptible_timeout_tty(acm->drain_wait,
(ACM_NW == acm_wb_is_avail(acm)) || !acm->dev,
ACM_CLOSE_TIMEOUT * HZ);
}
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [RFC 9/9] tty: implement BTM as mutex instead of BKL
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
` (7 preceding siblings ...)
2010-03-30 20:56 ` [RFC 8/9] tty: release tty lock when blocking Arnd Bergmann
@ 2010-03-30 20:56 ` Arnd Bergmann
2010-03-30 22:50 ` Frederic Weisbecker
2010-03-30 22:37 ` [RFC 0/9] BKL conversion in TTY drivers Alan Cox
9 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-30 20:56 UTC (permalink / raw)
To: LKML
Cc: Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann
The TTY layer now has its own ways to deal with recursive
locking and release-on-sleep for the tty_lock() calls,
meaning that it's safe to replace the Big Kernel Lock
with a subsystem specific Big TTY Mutex (BTM).
This patch for now makes the new behaviour an optional
experimental feature that can be enabled for testing
purposes.
Using a regular mutex here will change the behaviour
when blocked on the BTM from spinning to sleeping,
but that should be visible to the user.
Using the mutex also means that all the BTM is now
covered by lockdep.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/char/Makefile | 1 +
include/linux/init_task.h | 1 +
include/linux/sched.h | 1 +
include/linux/tty.h | 19 +++++++++++++++++++
kernel/fork.c | 1 +
lib/Kconfig.debug | 10 ++++++++++
6 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index f957edf..74ee3fa 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni
obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o tty_port.o
+obj-$(CONFIG_TTY_MUTEX) += tty_mutex.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
obj-y += misc.o
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index b1ed1cd..3c0b4ab 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -114,6 +114,7 @@ extern struct cred init_cred;
.usage = ATOMIC_INIT(2), \
.flags = PF_KTHREAD, \
.lock_depth = -1, \
+ .tty_lock_depth = -1, \
.prio = MAX_PRIO-20, \
.static_prio = MAX_PRIO-20, \
.normal_prio = MAX_PRIO-20, \
diff --git a/include/linux/sched.h b/include/linux/sched.h
index dad7f66..5f03259 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1175,6 +1175,7 @@ struct task_struct {
unsigned int ptrace;
int lock_depth; /* BKL lock depth */
+ int tty_lock_depth; /* TTY lock depth */
#ifdef CONFIG_SMP
#ifdef __ARCH_WANT_UNLOCKED_CTXSW
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 60b3d69..1659ba8 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -572,6 +572,7 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file,
extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg);
+/* tty_mutex.c */
/* functions for preparation of BKL removal */
/*
@@ -584,6 +585,22 @@ extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file,
* be shown to never get called with this held already, it should
* use tty_lock() instead.
*/
+#ifdef CONFIG_TTY_MUTEX
+extern void __lockfunc tty_lock_nested(void) __acquires(tty_lock);
+extern void __lockfunc tty_lock(void) __acquires(tty_lock);
+extern void __lockfunc tty_unlock(void) __releases(tty_lock);
+#define tty_locked() (current->tty_lock_depth >= 0)
+int __lockfunc __reacquire_tty_lock(void);
+void __lockfunc __release_tty_lock(void);
+#define release_tty_lock(tsk) do { \
+ if (unlikely((tsk)->tty_lock_depth >= 0)) \
+ __release_tty_lock(); \
+} while (0)
+#define reacquire_tty_lock(tsk) \
+ ((tsk->tty_lock_depth >= 0) ? \
+ __reacquire_tty_lock() : 0 )
+
+#else
static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock)
{
lock_kernel();
@@ -609,6 +626,8 @@ static inline void __release_tty_lock(void)
#define release_tty_lock(tsk) do { } while (0)
#define reacquire_tty_lock(tsk) do { } while (0)
+#endif
+
/*
* mutex_lock_tty - lock a mutex without holding the BTM
*
diff --git a/kernel/fork.c b/kernel/fork.c
index 4799c5f..b66376a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1061,6 +1061,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
posix_cpu_timers_init(p);
p->lock_depth = -1; /* -1 = no lock */
+ p->tty_lock_depth = -1; /* -1 = no lock */
do_posix_clock_monotonic_gettime(&p->start_time);
p->real_start_time = p->start_time;
monotonic_to_bootbased(&p->real_start_time);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 1fafb4b..32ff32c 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -428,6 +428,16 @@ config RT_MUTEX_TESTER
help
This option enables a rt-mutex tester.
+config TTY_MUTEX
+ bool "Use a mutex instead of BKL for TTY locking"
+ depends on EXPERIMENTAL && SMP
+ help
+ The TTY subsystem traditionally depends on the big kernel lock
+ for serialization. Saying Y here replaces the BKL with the Big
+ TTY Mutex (BTM).
+ Building a kernel without the BKL is only possible with TTY_MUTEX
+ enabled.
+
config DEBUG_SPINLOCK
bool "Spinlock and rw-lock debugging: basic checks"
depends on DEBUG_KERNEL
--
1.7.0
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [RFC 1/9] tty: replace BKL with a new tty_lock
2010-03-30 20:56 ` [RFC 1/9] tty: replace BKL with a new tty_lock Arnd Bergmann
@ 2010-03-30 22:23 ` Frederic Weisbecker
0 siblings, 0 replies; 21+ messages in thread
From: Frederic Weisbecker @ 2010-03-30 22:23 UTC (permalink / raw)
To: Arnd Bergmann
Cc: LKML, Alan Cox, Greg KH, Thomas Gleixner, Andrew Morton,
John Kacur, Al Viro, Ingo Molnar, Arnd Bergmann
On Tue, Mar 30, 2010 at 10:56:12PM +0200, Arnd Bergmann wrote:
> +/* functions for preparation of BKL removal */
> +
> +/*
> + * tty_lock_nested get the tty_lock while potentially holding it
> + *
> + * The Big TTY Mutex is a recursive lock, meaning you can take it
> + * from a thread that is already holding it.
> + * This is bad for a number of reasons, so tty_lock_nested should
> + * really be used as rarely as possible. If a code location can
> + * be shown to never get called with this held already, it should
> + * use tty_lock() instead.
> + */
> +static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock)
> +{
> + lock_kernel();
> +}
> +static inline void tty_lock(void) __acquires(kernel_lock)
> +{
> + WARN_ON(kernel_locked());
> + lock_kernel();
> +}
> +static inline void tty_unlock(void) __releases(kernel_lock)
> +{
> + unlock_kernel();
> +}
> +#define tty_locked() (kernel_locked())
> +static inline int __reacquire_tty_lock(void)
> +{
> + return 0;
> +}
> +static inline void __release_tty_lock(void)
> +{
> +}
> +
> +#define release_tty_lock(tsk) do { } while (0)
> +#define reacquire_tty_lock(tsk) do { } while (0)
> +
> +/*
> + * mutex_lock_tty - lock a mutex without holding the BTM
> + *
> + * These three functions replace calls to mutex_lock
> + * in the tty layer, when locking on of the following
> + * mutexes:
> + * tty->ldisc_mutex
> + * tty->termios_mutex
> + * tty->atomic_write_lock
> + * port->mutex
> + * pn->all_ppp_mutex
> + *
> + * The reason we need these is to avoid an AB-BA deadlock
> + * with tty_lock(). When it can be shown that one of the
> + * above mutexes is either never acquired with the tty_lock()
> + * held, or is never held when tty_lock() is acquired, that
> + * mutex should be converted back to the regular mutex_lock
> + * function.
> + *
> + * In order to annotate the lock order, the mutex_lock_tty_on
> + * and mutex_lock_tty_off versions should be used whereever
> + * possible, to show if the mutex is used with or without
> + * tty_lock already held.
> + */
> +#define mutex_lock_tty(mutex) \
> +({ \
> + if (!mutex_trylock(mutex)) { \
> + if (tty_locked()) { \
> + __release_tty_lock(); \
> + mutex_lock(mutex); \
> + __reacquire_tty_lock(); \
> + } else \
> + mutex_lock(mutex); \
> + } \
> +})
> +
> +#define mutex_lock_tty_on(mutex) \
> +({ \
> + if (!mutex_trylock(mutex)) { \
> + if (!WARN_ON(!tty_locked())) { \
> + __release_tty_lock(); \
> + mutex_lock(mutex); \
> + __reacquire_tty_lock(); \
> + } else \
> + mutex_lock(mutex); \
> + } \
> +})
> +
> +#define mutex_lock_tty_off(mutex) \
> +({ \
> + if (!mutex_trylock(mutex)) { \
> + if (WARN_ON(tty_locked())) { \
> + __release_tty_lock(); \
> + mutex_lock(mutex); \
> + __reacquire_tty_lock(); \
> + } else \
> + mutex_lock(mutex); \
> + } \
> +})
> +
> +#define mutex_lock_interruptible_tty(mutex) \
> +({ \
> + int __ret = 0; \
> + if (!mutex_trylock(mutex)) { \
> + if (tty_locked()) { \
> + __release_tty_lock(); \
> + __ret = mutex_lock_interruptible(mutex); \
> + __reacquire_tty_lock(); \
> + } else \
> + __ret = mutex_lock_interruptible(mutex); \
> + } \
> + __ret; \
> +})
> +
> +/*
> + * wait_event*_tty -- wait for a condition with the tty lock held
> + *
> + * similar to the mutex_lock_tty family, these should be used when
> + * waiting for an event in a code location that may get called
> + * while tty_lock is held.
> + *
> + * The problem is that the condition we are waiting for might
> + * only become true if another thread runs that needs the tty_lock
> + * in order to get there.
> + *
> + * None of these should be needed and all callers should be removed
> + * when either the caller or the condition it waits for can be show
> + * to not rely on the tty_lock.
> + */
> +#define wait_event_tty(wq, condition) \
> +do { \
> + if (condition) \
> + break; \
> + release_tty_lock(current); \
> + __wait_event(wq, condition); \
> + reacquire_tty_lock(current); \
> +} while (0)
> +
> +#define wait_event_timeout_tty(wq, condition, timeout) \
> +({ \
> + long __ret = timeout; \
> + if (!(condition)) { \
> + release_tty_lock(current); \
> + __wait_event_timeout(wq, condition, __ret); \
> + reacquire_tty_lock(current); \
> + } \
> + __ret; \
> +})
> +
> +#define wait_event_interruptible_tty(wq, condition) \
> +({ \
> + int __ret = 0; \
> + if (!(condition)) { \
> + release_tty_lock(current); \
> + __wait_event_interruptible(wq, condition, __ret); \
> + reacquire_tty_lock(current); \
> + } \
> + __ret; \
> +})
> +
> +#define wait_event_interruptible_timeout_tty(wq, condition, timeout) \
> +({ \
> + long __ret = timeout; \
> + if (!(condition)) { \
> + release_tty_lock(current); \
> + __wait_event_interruptible_timeout(wq, condition, __ret); \
> + reacquire_tty_lock(current); \
> + } \
> + __ret; \
> +})
Ouch, these helpers make me living again all the insane things I had to
do in reiserfs :-)
I first had doubts about this Big Tty Mutex (or whatever german meaning :-)
Because I thought this only carries the problem forward, or even
worst: now that it's not the bkl anymore, fewer people will even care about
removing this new big lock.
But now I actually think this is a good thing as every single tricky points
is underlined explicitly with these wait_event_tty, mutex_lock_tty, and so...
It's not anymore something released under us on schedule, it's not something
that might or might not be acquired recursively.
Removing this big lock later will then be easier as we can do it with more
granularity and visibility.
This is at least the experience I had with reiserfs. Its code _looks_
crappier than ever since 2.6.33, but it's a wrong appearance.
Now it shows which points require the reiserfs lock to be released because
there is an event dependency and it shows what are these dependencies.
The fact we can use lockdep in such a scheme plays a huge role btw.
Things are much clearer now, and I have even released some small areas
from the reiserfs lock because the explicit locking made it clear enough
to prove it fine.
If reiserfs wasn't obsolete, I would have probably pushed the effort further
to turn it into a granular locking, because the current state makes it
possible.
Now here we are talking about tty, and tty is not obsolete at all, so
I expect this is going to reach the current reiserfs level, plus a
subsequent and progressive state of locking granularity work, until
a complete exorcism.
FWIW, I'm all for this patchset.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 0/9] BKL conversion in TTY drivers
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
` (8 preceding siblings ...)
2010-03-30 20:56 ` [RFC 9/9] tty: implement BTM as mutex instead of BKL Arnd Bergmann
@ 2010-03-30 22:37 ` Alan Cox
2010-03-31 7:57 ` Arnd Bergmann
9 siblings, 1 reply; 21+ messages in thread
From: Alan Cox @ 2010-03-30 22:37 UTC (permalink / raw)
To: Arnd Bergmann
Cc: LKML, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
> This means we are still safe, because there is no code
> left that the new BTM fails to serialize with.
We hope. I'm currently poking at sorting out the locking properly and
quite frankly the locking rules for the current tty reference have me
baffled. It clearly works as we've not got a pile of dumps in the
bugzilla tree but its also quite a mystery *how*.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 9/9] tty: implement BTM as mutex instead of BKL
2010-03-30 20:56 ` [RFC 9/9] tty: implement BTM as mutex instead of BKL Arnd Bergmann
@ 2010-03-30 22:50 ` Frederic Weisbecker
0 siblings, 0 replies; 21+ messages in thread
From: Frederic Weisbecker @ 2010-03-30 22:50 UTC (permalink / raw)
To: Arnd Bergmann
Cc: LKML, Alan Cox, Greg KH, Thomas Gleixner, Andrew Morton,
John Kacur, Al Viro, Ingo Molnar
On Tue, Mar 30, 2010 at 10:56:20PM +0200, Arnd Bergmann wrote:
> +config TTY_MUTEX
> + bool "Use a mutex instead of BKL for TTY locking"
> + depends on EXPERIMENTAL && SMP
You still need it on UP-PREEMPT.
The bkl disables preemption so you need to "reproduce"
this atomicity by locking your path.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 7/9] ppp: use big tty mutex
2010-03-30 20:56 ` [RFC 7/9] ppp: use big tty mutex Arnd Bergmann
@ 2010-03-31 4:37 ` Américo Wang
2010-03-31 7:39 ` Arnd Bergmann
0 siblings, 1 reply; 21+ messages in thread
From: Américo Wang @ 2010-03-31 4:37 UTC (permalink / raw)
To: Arnd Bergmann
Cc: LKML, Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
On Wed, Mar 31, 2010 at 4:56 AM, Arnd Bergmann <arnd@arndb.de> wrote:
> ppp interacts with the tty layer, so it should
> take the BTM instead of the BKL.
>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/net/ppp_generic.c | 29 +++++++++++++++--------------
> 1 files changed, 15 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
> index 6d61602..bc89a1b 100644
> --- a/drivers/net/ppp_generic.c
> +++ b/drivers/net/ppp_generic.c
> @@ -40,7 +40,7 @@
> #include <linux/if_arp.h>
> #include <linux/ip.h>
> #include <linux/tcp.h>
> -#include <linux/smp_lock.h>
> +#include <linux/tty.h>
> #include <linux/spinlock.h>
> #include <linux/rwsem.h>
> #include <linux/stddef.h>
> @@ -362,7 +362,8 @@ static const int npindex_to_ethertype[NUM_NP] = {
> */
> static int ppp_open(struct inode *inode, struct file *file)
> {
> - cycle_kernel_lock();
> + tty_lock();
> + tty_unlock();
I don't really get your point here. :) Why do you do this?
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 7/9] ppp: use big tty mutex
2010-03-31 4:37 ` Américo Wang
@ 2010-03-31 7:39 ` Arnd Bergmann
0 siblings, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-31 7:39 UTC (permalink / raw)
To: Américo Wang
Cc: LKML, Alan Cox, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
On Wednesday 31 March 2010 06:37:12 Américo Wang wrote:
> > @@ -362,7 +362,8 @@ static const int npindex_to_ethertype[NUM_NP] = {
> > */
> > static int ppp_open(struct inode *inode, struct file *file)
> > {
> > - cycle_kernel_lock();
> > + tty_lock();
> > + tty_unlock();
>
> I don't really get your point here. :) Why do you do this?
This is a blind conversion of the API from the common BKL functions to
the TTY lock functions. There is no cycle_tty_lock(), so I'm manually
doing the cycle.
The reason why cycle_kernel_lock() was introduced in the first place
is that some drivers may depend on the open() function not returning
while another CPU holds the BKL. I did not feel qualified (or motivated)
to determine if the ppp code has the behavior, so I left it at this.
Arnd
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 0/9] BKL conversion in TTY drivers
2010-03-30 22:37 ` [RFC 0/9] BKL conversion in TTY drivers Alan Cox
@ 2010-03-31 7:57 ` Arnd Bergmann
2010-03-31 10:02 ` Alan Cox
0 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2010-03-31 7:57 UTC (permalink / raw)
To: Alan Cox
Cc: LKML, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
On Wednesday 31 March 2010 00:37:59 Alan Cox wrote:
>
> > This means we are still safe, because there is no code
> > left that the new BTM fails to serialize with.
>
> We hope. I'm currently poking at sorting out the locking properly and
> quite frankly the locking rules for the current tty reference have me
> baffled. It clearly works as we've not got a pile of dumps in the
> bugzilla tree but its also quite a mystery *how*.
Yes, that's why I didn't even attempt to find out why the BKL is
in some places or what it protects, but only changed the way it gets
taken and released.
We also have empirical evidence that turning the BKL into a semaphore
doesn't make the code fall apart, so I'm assuming that the mutex based
implementation with the explicit release-when-blocking instead of
implicit release-when-sleeping is still equivalent.
Are you more worried that the interface conversion (patches 1-8)
can introduce bugs and make your life harder, or that the mutex
based implementation from patch 9 causes problems that were previously
hidden by other bugs?
Arnd
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 0/9] BKL conversion in TTY drivers
2010-03-31 7:57 ` Arnd Bergmann
@ 2010-03-31 10:02 ` Alan Cox
2010-04-01 12:51 ` Arnd Bergmann
0 siblings, 1 reply; 21+ messages in thread
From: Alan Cox @ 2010-03-31 10:02 UTC (permalink / raw)
To: Arnd Bergmann
Cc: LKML, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
> Are you more worried that the interface conversion (patches 1-8)
> can introduce bugs and make your life harder, or that the mutex
> based implementation from patch 9 causes problems that were previously
> hidden by other bugs?
It doesn't really make any difference to me - I'm either removing the BKL
or the BKM.
Alan
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 0/9] BKL conversion in TTY drivers
2010-03-31 10:02 ` Alan Cox
@ 2010-04-01 12:51 ` Arnd Bergmann
2010-04-01 14:17 ` Alan Cox
0 siblings, 1 reply; 21+ messages in thread
From: Arnd Bergmann @ 2010-04-01 12:51 UTC (permalink / raw)
To: Alan Cox
Cc: LKML, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
On Wednesday 31 March 2010, Alan Cox wrote:
> > Are you more worried that the interface conversion (patches 1-8)
> > can introduce bugs and make your life harder, or that the mutex
> > based implementation from patch 9 causes problems that were previously
> > hidden by other bugs?
>
> It doesn't really make any difference to me - I'm either removing the BKL
> or the BKM.
Ok, great!
Greg, are you ok with merging these TTY patches in your tree for 2.6.35
then? There will be at least one more respin of it for minor changes
and anything that comes up during testing, but it's essentially what I
posted here.
Arnd
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 0/9] BKL conversion in TTY drivers
2010-04-01 12:51 ` Arnd Bergmann
@ 2010-04-01 14:17 ` Alan Cox
2010-04-01 15:24 ` Greg KH
2010-04-01 19:10 ` Arnd Bergmann
0 siblings, 2 replies; 21+ messages in thread
From: Alan Cox @ 2010-04-01 14:17 UTC (permalink / raw)
To: Arnd Bergmann
Cc: LKML, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
> Greg, are you ok with merging these TTY patches in your tree for 2.6.35
> then? There will be at least one more respin of it for minor changes
> and anything that comes up during testing, but it's essentially what I
> posted here.
Can we please wait a bit with the tty bits. I'm slowing picking through
the job properly and there are a lot of low hanging fruit to clean up at
the driver end of things that is best done before we complicate the core
stuff.
I'll try and get some patches posted ASAP for those but for example most
of the BKL use in the drivers/char tty drivers is now done, and those
remaining are almost all in code that we should simply drop as its been
marked broken/obsolete anyway.
Arnd there is another problem I noticed in your changes - the ppp stuff
is not tty locking, its some kind of driver/network locking and I don't
claim to understand what is going on.
Another one that wants attention from someone brave is selection.c - that
isn't tty locking dependant either but relies on the callers happening
(mostly but not always!) to call it with the BKL held.
Alan
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 0/9] BKL conversion in TTY drivers
2010-04-01 14:17 ` Alan Cox
@ 2010-04-01 15:24 ` Greg KH
2010-04-01 19:10 ` Arnd Bergmann
1 sibling, 0 replies; 21+ messages in thread
From: Greg KH @ 2010-04-01 15:24 UTC (permalink / raw)
To: Alan Cox
Cc: Arnd Bergmann, LKML, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
On Thu, Apr 01, 2010 at 03:17:56PM +0100, Alan Cox wrote:
> > Greg, are you ok with merging these TTY patches in your tree for 2.6.35
> > then? There will be at least one more respin of it for minor changes
> > and anything that comes up during testing, but it's essentially what I
> > posted here.
>
> Can we please wait a bit with the tty bits. I'm slowing picking through
> the job properly and there are a lot of low hanging fruit to clean up at
> the driver end of things that is best done before we complicate the core
> stuff.
No problem, I'll wait for your work before picking up any of these bkl
tty patches.
thanks,
greg k-h
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC 0/9] BKL conversion in TTY drivers
2010-04-01 14:17 ` Alan Cox
2010-04-01 15:24 ` Greg KH
@ 2010-04-01 19:10 ` Arnd Bergmann
1 sibling, 0 replies; 21+ messages in thread
From: Arnd Bergmann @ 2010-04-01 19:10 UTC (permalink / raw)
To: Alan Cox
Cc: LKML, Greg KH, Frederic Weisbecker, Thomas Gleixner,
Andrew Morton, John Kacur, Al Viro, Ingo Molnar
On Thursday 01 April 2010, Alan Cox wrote:
> > Greg, are you ok with merging these TTY patches in your tree for 2.6.35
> > then? There will be at least one more respin of it for minor changes
> > and anything that comes up during testing, but it's essentially what I
> > posted here.
>
> Can we please wait a bit with the tty bits. I'm slowing picking through
> the job properly and there are a lot of low hanging fruit to clean up at
> the driver end of things that is best done before we complicate the core
> stuff.
Ok, sure thing. I tried to make the patches in a way that is helpful to your
goals, not hurting, but anything you are already working on should go in
first because it's more important in the long run.
> Arnd there is another problem I noticed in your changes - the ppp stuff
> is not tty locking, its some kind of driver/network locking and I don't
> claim to understand what is going on.
Ok. This was just me being conservative and assuming that it interacts
with TTY in ways I don't understand. The network layer does not use the
BKL at all, except for a few protocols (appletalk, ipx, ...), so I'm fairly
certain the ppp locking does not interact with that. I'll have a closer look
to see if there's any chance it could lock against TTY code at all and
do a patch to use a private lock if not.
Arnd
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2010-04-01 19:10 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-03-30 20:56 [RFC 0/9] BKL conversion in TTY drivers Arnd Bergmann
2010-03-30 20:56 ` [RFC 1/9] tty: replace BKL with a new tty_lock Arnd Bergmann
2010-03-30 22:23 ` Frederic Weisbecker
2010-03-30 20:56 ` [RFC 2/9] tty: make atomic_write_lock release tty_lock Arnd Bergmann
2010-03-30 20:56 ` [RFC 3/9] tty: make tty_port->mutex nest under tty_lock Arnd Bergmann
2010-03-30 20:56 ` [RFC 4/9] tty: make termios mutex " Arnd Bergmann
2010-03-30 20:56 ` [RFC 5/9] tty: make ldisc_mutex " Arnd Bergmann
2010-03-30 20:56 ` [RFC 6/9] tty: never hold tty_lock() while getting tty_mutex Arnd Bergmann
2010-03-30 20:56 ` [RFC 7/9] ppp: use big tty mutex Arnd Bergmann
2010-03-31 4:37 ` Américo Wang
2010-03-31 7:39 ` Arnd Bergmann
2010-03-30 20:56 ` [RFC 8/9] tty: release tty lock when blocking Arnd Bergmann
2010-03-30 20:56 ` [RFC 9/9] tty: implement BTM as mutex instead of BKL Arnd Bergmann
2010-03-30 22:50 ` Frederic Weisbecker
2010-03-30 22:37 ` [RFC 0/9] BKL conversion in TTY drivers Alan Cox
2010-03-31 7:57 ` Arnd Bergmann
2010-03-31 10:02 ` Alan Cox
2010-04-01 12:51 ` Arnd Bergmann
2010-04-01 14:17 ` Alan Cox
2010-04-01 15:24 ` Greg KH
2010-04-01 19:10 ` Arnd Bergmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox