diff options
Diffstat (limited to 'drivers/char/tty_io.c')
| -rw-r--r-- | drivers/char/tty_io.c | 139 |
1 files changed, 87 insertions, 52 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index fdcc43c8ef3c..a5408496d301 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -1204,6 +1204,80 @@ static void tty_line_name(struct tty_driver *driver, int index, char *p) | |||
| 1204 | sprintf(p, "%s%d", driver->name, index + driver->name_base); | 1204 | sprintf(p, "%s%d", driver->name, index + driver->name_base); |
| 1205 | } | 1205 | } |
| 1206 | 1206 | ||
| 1207 | /* | ||
| 1208 | * find_tty() - find an existing tty, if any | ||
| 1209 | * @driver: the driver for the tty | ||
| 1210 | * @idx: the minor number | ||
| 1211 | * | ||
| 1212 | * Return the tty, if found or ERR_PTR() otherwise. | ||
| 1213 | * | ||
| 1214 | * Locking: tty_mutex must be held. If tty is found, the mutex must | ||
| 1215 | * be held until the 'fast-open' is also done. | ||
| 1216 | */ | ||
| 1217 | struct tty_struct *find_tty(struct tty_driver *driver, int idx) | ||
| 1218 | { | ||
| 1219 | struct tty_struct *tty; | ||
| 1220 | |||
| 1221 | /* check whether we're reopening an existing tty */ | ||
| 1222 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | ||
| 1223 | tty = devpts_get_tty(idx); | ||
| 1224 | /* | ||
| 1225 | * If we don't have a tty here on a slave open, it's because | ||
| 1226 | * the master already started the close process and there's | ||
| 1227 | * no relation between devpts file and tty anymore. | ||
| 1228 | */ | ||
| 1229 | if (!tty && driver->subtype == PTY_TYPE_SLAVE) | ||
| 1230 | return ERR_PTR(-EIO); | ||
| 1231 | |||
| 1232 | /* | ||
| 1233 | * tty is safe on because we are called with tty_mutex held | ||
| 1234 | * and release_dev() won't change tty->count or tty->flags | ||
| 1235 | * without grabbing tty_mutex. | ||
| 1236 | */ | ||
| 1237 | if (tty && driver->subtype == PTY_TYPE_MASTER) | ||
| 1238 | tty = tty->link; | ||
| 1239 | } else | ||
| 1240 | tty = driver->ttys[idx]; | ||
| 1241 | return tty; | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | /* | ||
| 1245 | * fast_tty_open() - fast re-open of an open tty | ||
| 1246 | * @tty - the tty to open | ||
| 1247 | * | ||
| 1248 | * Return 0 on success, -errno on error. | ||
| 1249 | * | ||
| 1250 | * Locking: tty_mutex must be held from the time the tty was found | ||
| 1251 | * till this open completes. | ||
| 1252 | */ | ||
| 1253 | static int fast_tty_open(struct tty_struct *tty) | ||
| 1254 | { | ||
| 1255 | struct tty_driver *driver = tty->driver; | ||
| 1256 | |||
| 1257 | if (test_bit(TTY_CLOSING, &tty->flags)) | ||
| 1258 | return -EIO; | ||
| 1259 | |||
| 1260 | if (driver->type == TTY_DRIVER_TYPE_PTY && | ||
| 1261 | driver->subtype == PTY_TYPE_MASTER) { | ||
| 1262 | /* | ||
| 1263 | * special case for PTY masters: only one open permitted, | ||
| 1264 | * and the slave side open count is incremented as well. | ||
| 1265 | */ | ||
| 1266 | if (tty->count) | ||
| 1267 | return -EIO; | ||
| 1268 | |||
| 1269 | tty->link->count++; | ||
| 1270 | } | ||
| 1271 | tty->count++; | ||
| 1272 | tty->driver = driver; /* N.B. why do this every time?? */ | ||
| 1273 | |||
| 1274 | /* FIXME */ | ||
| 1275 | if (!test_bit(TTY_LDISC, &tty->flags)) | ||
| 1276 | printk(KERN_ERR "fast_tty_open: no ldisc\n"); | ||
| 1277 | |||
| 1278 | return 0; | ||
| 1279 | } | ||
| 1280 | |||
| 1207 | /** | 1281 | /** |
| 1208 | * tty_init_dev - initialise a tty device | 1282 | * tty_init_dev - initialise a tty device |
| 1209 | * @driver: tty driver we are opening a device on | 1283 | * @driver: tty driver we are opening a device on |
| @@ -1238,29 +1312,21 @@ int tty_init_dev(struct tty_driver *driver, int idx, | |||
| 1238 | int retval = 0; | 1312 | int retval = 0; |
| 1239 | 1313 | ||
| 1240 | /* check whether we're reopening an existing tty */ | 1314 | /* check whether we're reopening an existing tty */ |
| 1241 | if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { | 1315 | tty = find_tty(driver, idx); |
| 1242 | tty = devpts_get_tty(idx); | 1316 | if (IS_ERR(tty)) { |
| 1243 | /* | 1317 | retval = PTR_ERR(tty); |
| 1244 | * If we don't have a tty here on a slave open, it's because | 1318 | goto end_init; |
| 1245 | * the master already started the close process and there's | 1319 | } |
| 1246 | * no relation between devpts file and tty anymore. | 1320 | |
| 1247 | */ | 1321 | if (tty) { |
| 1248 | if (!tty && driver->subtype == PTY_TYPE_SLAVE) { | 1322 | retval = fast_tty_open(tty); |
| 1249 | retval = -EIO; | 1323 | if (retval) |
| 1250 | goto end_init; | 1324 | return retval; |
| 1251 | } | 1325 | *ret_tty = tty; |
| 1252 | /* | 1326 | return 0; |
| 1253 | * It's safe from now on because tty_init_dev() is called with | ||
| 1254 | * tty_mutex held and tty_release_dev() won't change tty->count | ||
| 1255 | * or tty->flags without having to grab tty_mutex | ||
| 1256 | */ | ||
| 1257 | if (tty && driver->subtype == PTY_TYPE_MASTER) | ||
| 1258 | tty = tty->link; | ||
| 1259 | } else { | ||
| 1260 | tty = driver->ttys[idx]; | ||
| 1261 | } | 1327 | } |
| 1262 | if (tty) goto fast_track; | ||
| 1263 | 1328 | ||
| 1329 | /* Check if pty master is being opened multiple times */ | ||
| 1264 | if (driver->subtype == PTY_TYPE_MASTER && | 1330 | if (driver->subtype == PTY_TYPE_MASTER && |
| 1265 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { | 1331 | (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { |
| 1266 | retval = -EIO; | 1332 | retval = -EIO; |
| @@ -1400,37 +1466,6 @@ int tty_init_dev(struct tty_driver *driver, int idx, | |||
| 1400 | 1466 | ||
| 1401 | if (retval) | 1467 | if (retval) |
| 1402 | goto release_mem_out; | 1468 | goto release_mem_out; |
| 1403 | goto success; | ||
| 1404 | |||
| 1405 | /* | ||
| 1406 | * This fast open can be used if the tty is already open. | ||
| 1407 | * No memory is allocated, and the only failures are from | ||
| 1408 | * attempting to open a closing tty or attempting multiple | ||
| 1409 | * opens on a pty master. | ||
| 1410 | */ | ||
| 1411 | fast_track: | ||
| 1412 | if (test_bit(TTY_CLOSING, &tty->flags)) { | ||
| 1413 | retval = -EIO; | ||
| 1414 | goto end_init; | ||
| 1415 | } | ||
| 1416 | if (driver->type == TTY_DRIVER_TYPE_PTY && | ||
| 1417 | driver->subtype == PTY_TYPE_MASTER) { | ||
| 1418 | /* | ||
| 1419 | * special case for PTY masters: only one open permitted, | ||
| 1420 | * and the slave side open count is incremented as well. | ||
| 1421 | */ | ||
| 1422 | if (tty->count) { | ||
| 1423 | retval = -EIO; | ||
| 1424 | goto end_init; | ||
| 1425 | } | ||
| 1426 | tty->link->count++; | ||
| 1427 | } | ||
| 1428 | tty->count++; | ||
| 1429 | tty->driver = driver; /* N.B. why do this every time?? */ | ||
| 1430 | |||
| 1431 | /* FIXME */ | ||
| 1432 | if (!test_bit(TTY_LDISC, &tty->flags)) | ||
| 1433 | printk(KERN_ERR "tty_init_dev but no ldisc\n"); | ||
| 1434 | success: | 1469 | success: |
| 1435 | *ret_tty = tty; | 1470 | *ret_tty = tty; |
| 1436 | 1471 | ||
