linux/drivers/tty/tty_ldisc.c
<<
>>
Prefs
   1#include <linux/types.h>
   2#include <linux/errno.h>
   3#include <linux/kmod.h>
   4#include <linux/sched.h>
   5#include <linux/interrupt.h>
   6#include <linux/tty.h>
   7#include <linux/tty_driver.h>
   8#include <linux/file.h>
   9#include <linux/mm.h>
  10#include <linux/string.h>
  11#include <linux/slab.h>
  12#include <linux/poll.h>
  13#include <linux/proc_fs.h>
  14#include <linux/init.h>
  15#include <linux/module.h>
  16#include <linux/device.h>
  17#include <linux/wait.h>
  18#include <linux/bitops.h>
  19#include <linux/seq_file.h>
  20#include <linux/uaccess.h>
  21#include <linux/ratelimit.h>
  22
  23#undef LDISC_DEBUG_HANGUP
  24
  25#ifdef LDISC_DEBUG_HANGUP
  26#define tty_ldisc_debug(tty, f, args...) ({                                    \
  27        char __b[64];                                                          \
  28        printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty, __b), ##args); \
  29})
  30#else
  31#define tty_ldisc_debug(tty, f, args...)
  32#endif
  33
  34/* lockdep nested classes for tty->ldisc_sem */
  35enum {
  36        LDISC_SEM_NORMAL,
  37        LDISC_SEM_OTHER,
  38};
  39
  40
  41/*
  42 *      This guards the refcounted line discipline lists. The lock
  43 *      must be taken with irqs off because there are hangup path
  44 *      callers who will do ldisc lookups and cannot sleep.
  45 */
  46
  47static DEFINE_RAW_SPINLOCK(tty_ldiscs_lock);
  48/* Line disc dispatch table */
  49static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];
  50
  51/**
  52 *      tty_register_ldisc      -       install a line discipline
  53 *      @disc: ldisc number
  54 *      @new_ldisc: pointer to the ldisc object
  55 *
  56 *      Installs a new line discipline into the kernel. The discipline
  57 *      is set up as unreferenced and then made available to the kernel
  58 *      from this point onwards.
  59 *
  60 *      Locking:
  61 *              takes tty_ldiscs_lock to guard against ldisc races
  62 */
  63
  64int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
  65{
  66        unsigned long flags;
  67        int ret = 0;
  68
  69        if (disc < N_TTY || disc >= NR_LDISCS)
  70                return -EINVAL;
  71
  72        raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
  73        tty_ldiscs[disc] = new_ldisc;
  74        new_ldisc->num = disc;
  75        new_ldisc->refcount = 0;
  76        raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
  77
  78        return ret;
  79}
  80EXPORT_SYMBOL(tty_register_ldisc);
  81
  82/**
  83 *      tty_unregister_ldisc    -       unload a line discipline
  84 *      @disc: ldisc number
  85 *      @new_ldisc: pointer to the ldisc object
  86 *
  87 *      Remove a line discipline from the kernel providing it is not
  88 *      currently in use.
  89 *
  90 *      Locking:
  91 *              takes tty_ldiscs_lock to guard against ldisc races
  92 */
  93
  94int tty_unregister_ldisc(int disc)
  95{
  96        unsigned long flags;
  97        int ret = 0;
  98
  99        if (disc < N_TTY || disc >= NR_LDISCS)
 100                return -EINVAL;
 101
 102        raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
 103        if (tty_ldiscs[disc]->refcount)
 104                ret = -EBUSY;
 105        else
 106                tty_ldiscs[disc] = NULL;
 107        raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
 108
 109        return ret;
 110}
 111EXPORT_SYMBOL(tty_unregister_ldisc);
 112
 113static struct tty_ldisc_ops *get_ldops(int disc)
 114{
 115        unsigned long flags;
 116        struct tty_ldisc_ops *ldops, *ret;
 117
 118        raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
 119        ret = ERR_PTR(-EINVAL);
 120        ldops = tty_ldiscs[disc];
 121        if (ldops) {
 122                ret = ERR_PTR(-EAGAIN);
 123                if (try_module_get(ldops->owner)) {
 124                        ldops->refcount++;
 125                        ret = ldops;
 126                }
 127        }
 128        raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
 129        return ret;
 130}
 131
 132static void put_ldops(struct tty_ldisc_ops *ldops)
 133{
 134        unsigned long flags;
 135
 136        raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);
 137        ldops->refcount--;
 138        module_put(ldops->owner);
 139        raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);
 140}
 141
 142/**
 143 *      tty_ldisc_get           -       take a reference to an ldisc
 144 *      @disc: ldisc number
 145 *
 146 *      Takes a reference to a line discipline. Deals with refcounts and
 147 *      module locking counts. Returns NULL if the discipline is not available.
 148 *      Returns a pointer to the discipline and bumps the ref count if it is
 149 *      available
 150 *
 151 *      Locking:
 152 *              takes tty_ldiscs_lock to guard against ldisc races
 153 */
 154
 155static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
 156{
 157        struct tty_ldisc *ld;
 158        struct tty_ldisc_ops *ldops;
 159
 160        if (disc < N_TTY || disc >= NR_LDISCS)
 161                return ERR_PTR(-EINVAL);
 162
 163        /*
 164         * Get the ldisc ops - we may need to request them to be loaded
 165         * dynamically and try again.
 166         */
 167        ldops = get_ldops(disc);
 168        if (IS_ERR(ldops)) {
 169                request_module("tty-ldisc-%d", disc);
 170                ldops = get_ldops(disc);
 171                if (IS_ERR(ldops))
 172                        return ERR_CAST(ldops);
 173        }
 174
 175        ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL);
 176        if (ld == NULL) {
 177                put_ldops(ldops);
 178                return ERR_PTR(-ENOMEM);
 179        }
 180
 181        ld->ops = ldops;
 182        ld->tty = tty;
 183
 184        return ld;
 185}
 186
 187/**
 188 *      tty_ldisc_put           -       release the ldisc
 189 *
 190 *      Complement of tty_ldisc_get().
 191 */
 192static inline void tty_ldisc_put(struct tty_ldisc *ld)
 193{
 194        if (WARN_ON_ONCE(!ld))
 195                return;
 196
 197        put_ldops(ld->ops);
 198        kfree(ld);
 199}
 200
 201static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos)
 202{
 203        return (*pos < NR_LDISCS) ? pos : NULL;
 204}
 205
 206static void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos)
 207{
 208        (*pos)++;
 209        return (*pos < NR_LDISCS) ? pos : NULL;
 210}
 211
 212static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
 213{
 214}
 215
 216static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
 217{
 218        int i = *(loff_t *)v;
 219        struct tty_ldisc_ops *ldops;
 220
 221        ldops = get_ldops(i);
 222        if (IS_ERR(ldops))
 223                return 0;
 224        seq_printf(m, "%-10s %2d\n", ldops->name ? ldops->name : "???", i);
 225        put_ldops(ldops);
 226        return 0;
 227}
 228
 229static const struct seq_operations tty_ldiscs_seq_ops = {
 230        .start  = tty_ldiscs_seq_start,
 231        .next   = tty_ldiscs_seq_next,
 232        .stop   = tty_ldiscs_seq_stop,
 233        .show   = tty_ldiscs_seq_show,
 234};
 235
 236static int proc_tty_ldiscs_open(struct inode *inode, struct file *file)
 237{
 238        return seq_open(file, &tty_ldiscs_seq_ops);
 239}
 240
 241const struct file_operations tty_ldiscs_proc_fops = {
 242        .owner          = THIS_MODULE,
 243        .open           = proc_tty_ldiscs_open,
 244        .read           = seq_read,
 245        .llseek         = seq_lseek,
 246        .release        = seq_release,
 247};
 248
 249/**
 250 *      tty_ldisc_ref_wait      -       wait for the tty ldisc
 251 *      @tty: tty device
 252 *
 253 *      Dereference the line discipline for the terminal and take a
 254 *      reference to it. If the line discipline is in flux then
 255 *      wait patiently until it changes.
 256 *
 257 *      Note: Must not be called from an IRQ/timer context. The caller
 258 *      must also be careful not to hold other locks that will deadlock
 259 *      against a discipline change, such as an existing ldisc reference
 260 *      (which we check for)
 261 *
 262 *      Note: only callable from a file_operations routine (which
 263 *      guarantees tty->ldisc != NULL when the lock is acquired).
 264 */
 265
 266struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
 267{
 268        ldsem_down_read(&tty->ldisc_sem, MAX_SCHEDULE_TIMEOUT);
 269        WARN_ON(!tty->ldisc);
 270        return tty->ldisc;
 271}
 272EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
 273
 274/**
 275 *      tty_ldisc_ref           -       get the tty ldisc
 276 *      @tty: tty device
 277 *
 278 *      Dereference the line discipline for the terminal and take a
 279 *      reference to it. If the line discipline is in flux then
 280 *      return NULL. Can be called from IRQ and timer functions.
 281 */
 282
 283struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
 284{
 285        struct tty_ldisc *ld = NULL;
 286
 287        if (ldsem_down_read_trylock(&tty->ldisc_sem)) {
 288                ld = tty->ldisc;
 289                if (!ld)
 290                        ldsem_up_read(&tty->ldisc_sem);
 291        }
 292        return ld;
 293}
 294EXPORT_SYMBOL_GPL(tty_ldisc_ref);
 295
 296/**
 297 *      tty_ldisc_deref         -       free a tty ldisc reference
 298 *      @ld: reference to free up
 299 *
 300 *      Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
 301 *      be called in IRQ context.
 302 */
 303
 304void tty_ldisc_deref(struct tty_ldisc *ld)
 305{
 306        ldsem_up_read(&ld->tty->ldisc_sem);
 307}
 308EXPORT_SYMBOL_GPL(tty_ldisc_deref);
 309
 310
 311static inline int __lockfunc
 312tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout)
 313{
 314        return ldsem_down_write(&tty->ldisc_sem, timeout);
 315}
 316
 317static inline int __lockfunc
 318tty_ldisc_lock_nested(struct tty_struct *tty, unsigned long timeout)
 319{
 320        return ldsem_down_write_nested(&tty->ldisc_sem,
 321                                       LDISC_SEM_OTHER, timeout);
 322}
 323
 324static inline void tty_ldisc_unlock(struct tty_struct *tty)
 325{
 326        return ldsem_up_write(&tty->ldisc_sem);
 327}
 328
 329static int __lockfunc
 330tty_ldisc_lock_pair_timeout(struct tty_struct *tty, struct tty_struct *tty2,
 331                            unsigned long timeout)
 332{
 333        int ret;
 334
 335        if (tty < tty2) {
 336                ret = tty_ldisc_lock(tty, timeout);
 337                if (ret) {
 338                        ret = tty_ldisc_lock_nested(tty2, timeout);
 339                        if (!ret)
 340                                tty_ldisc_unlock(tty);
 341                }
 342        } else {
 343                /* if this is possible, it has lots of implications */
 344                WARN_ON_ONCE(tty == tty2);
 345                if (tty2 && tty != tty2) {
 346                        ret = tty_ldisc_lock(tty2, timeout);
 347                        if (ret) {
 348                                ret = tty_ldisc_lock_nested(tty, timeout);
 349                                if (!ret)
 350                                        tty_ldisc_unlock(tty2);
 351                        }
 352                } else
 353                        ret = tty_ldisc_lock(tty, timeout);
 354        }
 355
 356        if (!ret)
 357                return -EBUSY;
 358
 359        set_bit(TTY_LDISC_HALTED, &tty->flags);
 360        if (tty2)
 361                set_bit(TTY_LDISC_HALTED, &tty2->flags);
 362        return 0;
 363}
 364
 365static void __lockfunc
 366tty_ldisc_lock_pair(struct tty_struct *tty, struct tty_struct *tty2)
 367{
 368        tty_ldisc_lock_pair_timeout(tty, tty2, MAX_SCHEDULE_TIMEOUT);
 369}
 370
 371static void __lockfunc tty_ldisc_unlock_pair(struct tty_struct *tty,
 372                                             struct tty_struct *tty2)
 373{
 374        tty_ldisc_unlock(tty);
 375        if (tty2)
 376                tty_ldisc_unlock(tty2);
 377}
 378
 379static void __lockfunc tty_ldisc_enable_pair(struct tty_struct *tty,
 380                                             struct tty_struct *tty2)
 381{
 382        clear_bit(TTY_LDISC_HALTED, &tty->flags);
 383        if (tty2)
 384                clear_bit(TTY_LDISC_HALTED, &tty2->flags);
 385
 386        tty_ldisc_unlock_pair(tty, tty2);
 387}
 388
 389/**
 390 *      tty_ldisc_flush -       flush line discipline queue
 391 *      @tty: tty
 392 *
 393 *      Flush the line discipline queue (if any) for this tty. If there
 394 *      is no line discipline active this is a no-op.
 395 */
 396
 397void tty_ldisc_flush(struct tty_struct *tty)
 398{
 399        struct tty_ldisc *ld = tty_ldisc_ref(tty);
 400        if (ld) {
 401                if (ld->ops->flush_buffer)
 402                        ld->ops->flush_buffer(tty);
 403                tty_ldisc_deref(ld);
 404        }
 405        tty_buffer_flush(tty);
 406}
 407EXPORT_SYMBOL_GPL(tty_ldisc_flush);
 408
 409/**
 410 *      tty_set_termios_ldisc           -       set ldisc field
 411 *      @tty: tty structure
 412 *      @num: line discipline number
 413 *
 414 *      This is probably overkill for real world processors but
 415 *      they are not on hot paths so a little discipline won't do
 416 *      any harm.
 417 *
 418 *      Locking: takes termios_rwsem
 419 */
 420
 421static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
 422{
 423        down_write(&tty->termios_rwsem);
 424        tty->termios.c_line = num;
 425        up_write(&tty->termios_rwsem);
 426}
 427
 428/**
 429 *      tty_ldisc_open          -       open a line discipline
 430 *      @tty: tty we are opening the ldisc on
 431 *      @ld: discipline to open
 432 *
 433 *      A helper opening method. Also a convenient debugging and check
 434 *      point.
 435 *
 436 *      Locking: always called with BTM already held.
 437 */
 438
 439static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld)
 440{
 441        WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags));
 442        if (ld->ops->open) {
 443                int ret;
 444                /* BTM here locks versus a hangup event */
 445                ret = ld->ops->open(tty);
 446                if (ret)
 447                        clear_bit(TTY_LDISC_OPEN, &tty->flags);
 448                return ret;
 449        }
 450        return 0;
 451}
 452
 453/**
 454 *      tty_ldisc_close         -       close a line discipline
 455 *      @tty: tty we are opening the ldisc on
 456 *      @ld: discipline to close
 457 *
 458 *      A helper close method. Also a convenient debugging and check
 459 *      point.
 460 */
 461
 462static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
 463{
 464        WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags));
 465        clear_bit(TTY_LDISC_OPEN, &tty->flags);
 466        if (ld->ops->close)
 467                ld->ops->close(tty);
 468}
 469
 470/**
 471 *      tty_ldisc_restore       -       helper for tty ldisc change
 472 *      @tty: tty to recover
 473 *      @old: previous ldisc
 474 *
 475 *      Restore the previous line discipline or N_TTY when a line discipline
 476 *      change fails due to an open error
 477 */
 478
 479static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old)
 480{
 481        char buf[64];
 482        struct tty_ldisc *new_ldisc;
 483        int r;
 484
 485        /* There is an outstanding reference here so this is safe */
 486        old = tty_ldisc_get(tty, old->ops->num);
 487        WARN_ON(IS_ERR(old));
 488        tty->ldisc = old;
 489        tty_set_termios_ldisc(tty, old->ops->num);
 490        if (tty_ldisc_open(tty, old) < 0) {
 491                tty_ldisc_put(old);
 492                /* This driver is always present */
 493                new_ldisc = tty_ldisc_get(tty, N_TTY);
 494                if (IS_ERR(new_ldisc))
 495                        panic("n_tty: get");
 496                tty->ldisc = new_ldisc;
 497                tty_set_termios_ldisc(tty, N_TTY);
 498                r = tty_ldisc_open(tty, new_ldisc);
 499                if (r < 0)
 500                        panic("Couldn't open N_TTY ldisc for "
 501                              "%s --- error %d.",
 502                              tty_name(tty, buf), r);
 503        }
 504}
 505
 506/**
 507 *      tty_set_ldisc           -       set line discipline
 508 *      @tty: the terminal to set
 509 *      @ldisc: the line discipline
 510 *
 511 *      Set the discipline of a tty line. Must be called from a process
 512 *      context. The ldisc change logic has to protect itself against any
 513 *      overlapping ldisc change (including on the other end of pty pairs),
 514 *      the close of one side of a tty/pty pair, and eventually hangup.
 515 */
 516
 517int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 518{
 519        int retval;
 520        struct tty_ldisc *old_ldisc, *new_ldisc;
 521        struct tty_struct *o_tty = tty->link;
 522
 523        new_ldisc = tty_ldisc_get(tty, ldisc);
 524        if (IS_ERR(new_ldisc))
 525                return PTR_ERR(new_ldisc);
 526
 527        retval = tty_ldisc_lock_pair_timeout(tty, o_tty, 5 * HZ);
 528        if (retval) {
 529                tty_ldisc_put(new_ldisc);
 530                return retval;
 531        }
 532
 533        /*
 534         *      Check the no-op case
 535         */
 536
 537        if (tty->ldisc->ops->num == ldisc) {
 538                tty_ldisc_enable_pair(tty, o_tty);
 539                tty_ldisc_put(new_ldisc);
 540                return 0;
 541        }
 542
 543        old_ldisc = tty->ldisc;
 544        tty_lock(tty);
 545
 546        if (test_bit(TTY_HUPPING, &tty->flags) ||
 547            test_bit(TTY_HUPPED, &tty->flags)) {
 548                /* We were raced by the hangup method. It will have stomped
 549                   the ldisc data and closed the ldisc down */
 550                tty_ldisc_enable_pair(tty, o_tty);
 551                tty_ldisc_put(new_ldisc);
 552                tty_unlock(tty);
 553                return -EIO;
 554        }
 555
 556        /* Shutdown the old discipline. */
 557        tty_ldisc_close(tty, old_ldisc);
 558
 559        /* Now set up the new line discipline. */
 560        tty->ldisc = new_ldisc;
 561        tty_set_termios_ldisc(tty, ldisc);
 562
 563        retval = tty_ldisc_open(tty, new_ldisc);
 564        if (retval < 0) {
 565                /* Back to the old one or N_TTY if we can't */
 566                tty_ldisc_put(new_ldisc);
 567                tty_ldisc_restore(tty, old_ldisc);
 568        }
 569
 570        if (tty->ldisc->ops->num != old_ldisc->ops->num && tty->ops->set_ldisc)
 571                tty->ops->set_ldisc(tty);
 572
 573        /* At this point we hold a reference to the new ldisc and a
 574           reference to the old ldisc, or we hold two references to
 575           the old ldisc (if it was restored as part of error cleanup
 576           above). In either case, releasing a single reference from
 577           the old ldisc is correct. */
 578
 579        tty_ldisc_put(old_ldisc);
 580
 581        /*
 582         *      Allow ldisc referencing to occur again
 583         */
 584        tty_ldisc_enable_pair(tty, o_tty);
 585
 586        /* Restart the work queue in case no characters kick it off. Safe if
 587           already running */
 588        schedule_work(&tty->port->buf.work);
 589        if (o_tty)
 590                schedule_work(&o_tty->port->buf.work);
 591
 592        tty_unlock(tty);
 593        return retval;
 594}
 595
 596/**
 597 *      tty_reset_termios       -       reset terminal state
 598 *      @tty: tty to reset
 599 *
 600 *      Restore a terminal to the driver default state.
 601 */
 602
 603static void tty_reset_termios(struct tty_struct *tty)
 604{
 605        down_write(&tty->termios_rwsem);
 606        tty->termios = tty->driver->init_termios;
 607        tty->termios.c_ispeed = tty_termios_input_baud_rate(&tty->termios);
 608        tty->termios.c_ospeed = tty_termios_baud_rate(&tty->termios);
 609        up_write(&tty->termios_rwsem);
 610}
 611
 612
 613/**
 614 *      tty_ldisc_reinit        -       reinitialise the tty ldisc
 615 *      @tty: tty to reinit
 616 *      @ldisc: line discipline to reinitialize
 617 *
 618 *      Switch the tty to a line discipline and leave the ldisc
 619 *      state closed
 620 */
 621
 622static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
 623{
 624        struct tty_ldisc *ld = tty_ldisc_get(tty, ldisc);
 625
 626        if (IS_ERR(ld))
 627                return -1;
 628
 629        tty_ldisc_close(tty, tty->ldisc);
 630        tty_ldisc_put(tty->ldisc);
 631        /*
 632         *      Switch the line discipline back
 633         */
 634        tty->ldisc = ld;
 635        tty_set_termios_ldisc(tty, ldisc);
 636
 637        return 0;
 638}
 639
 640/**
 641 *      tty_ldisc_hangup                -       hangup ldisc reset
 642 *      @tty: tty being hung up
 643 *
 644 *      Some tty devices reset their termios when they receive a hangup
 645 *      event. In that situation we must also switch back to N_TTY properly
 646 *      before we reset the termios data.
 647 *
 648 *      Locking: We can take the ldisc mutex as the rest of the code is
 649 *      careful to allow for this.
 650 *
 651 *      In the pty pair case this occurs in the close() path of the
 652 *      tty itself so we must be careful about locking rules.
 653 */
 654
 655void tty_ldisc_hangup(struct tty_struct *tty)
 656{
 657        struct tty_ldisc *ld;
 658        int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
 659        int err = 0;
 660
 661        tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
 662
 663        ld = tty_ldisc_ref(tty);
 664        if (ld != NULL) {
 665                if (ld->ops->flush_buffer)
 666                        ld->ops->flush_buffer(tty);
 667                tty_driver_flush_buffer(tty);
 668                if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) &&
 669                    ld->ops->write_wakeup)
 670                        ld->ops->write_wakeup(tty);
 671                if (ld->ops->hangup)
 672                        ld->ops->hangup(tty);
 673                tty_ldisc_deref(ld);
 674        }
 675
 676        wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
 677        wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 678
 679        tty_unlock(tty);
 680
 681        /*
 682         * Shutdown the current line discipline, and reset it to
 683         * N_TTY if need be.
 684         *
 685         * Avoid racing set_ldisc or tty_ldisc_release
 686         */
 687        tty_ldisc_lock_pair(tty, tty->link);
 688        tty_lock(tty);
 689
 690        if (tty->ldisc) {
 691
 692                /* At this point we have a halted ldisc; we want to close it and
 693                   reopen a new ldisc. We could defer the reopen to the next
 694                   open but it means auditing a lot of other paths so this is
 695                   a FIXME */
 696                if (reset == 0) {
 697
 698                        if (!tty_ldisc_reinit(tty, tty->termios.c_line))
 699                                err = tty_ldisc_open(tty, tty->ldisc);
 700                        else
 701                                err = 1;
 702                }
 703                /* If the re-open fails or we reset then go to N_TTY. The
 704                   N_TTY open cannot fail */
 705                if (reset || err) {
 706                        BUG_ON(tty_ldisc_reinit(tty, N_TTY));
 707                        WARN_ON(tty_ldisc_open(tty, tty->ldisc));
 708                }
 709        }
 710        tty_ldisc_enable_pair(tty, tty->link);
 711        if (reset)
 712                tty_reset_termios(tty);
 713
 714        tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc);
 715}
 716
 717/**
 718 *      tty_ldisc_setup                 -       open line discipline
 719 *      @tty: tty being shut down
 720 *      @o_tty: pair tty for pty/tty pairs
 721 *
 722 *      Called during the initial open of a tty/pty pair in order to set up the
 723 *      line disciplines and bind them to the tty. This has no locking issues
 724 *      as the device isn't yet active.
 725 */
 726
 727int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty)
 728{
 729        struct tty_ldisc *ld = tty->ldisc;
 730        int retval;
 731
 732        retval = tty_ldisc_open(tty, ld);
 733        if (retval)
 734                return retval;
 735
 736        if (o_tty) {
 737                retval = tty_ldisc_open(o_tty, o_tty->ldisc);
 738                if (retval) {
 739                        tty_ldisc_close(tty, ld);
 740                        return retval;
 741                }
 742        }
 743        return 0;
 744}
 745
 746static void tty_ldisc_kill(struct tty_struct *tty)
 747{
 748        /*
 749         * Now kill off the ldisc
 750         */
 751        tty_ldisc_close(tty, tty->ldisc);
 752        tty_ldisc_put(tty->ldisc);
 753        /* Force an oops if we mess this up */
 754        tty->ldisc = NULL;
 755
 756        /* Ensure the next open requests the N_TTY ldisc */
 757        tty_set_termios_ldisc(tty, N_TTY);
 758}
 759
 760/**
 761 *      tty_ldisc_release               -       release line discipline
 762 *      @tty: tty being shut down
 763 *      @o_tty: pair tty for pty/tty pairs
 764 *
 765 *      Called during the final close of a tty/pty pair in order to shut down
 766 *      the line discpline layer. On exit the ldisc assigned is N_TTY and the
 767 *      ldisc has not been opened.
 768 */
 769
 770void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
 771{
 772        /*
 773         * Shutdown this line discipline. As this is the final close,
 774         * it does not race with the set_ldisc code path.
 775         */
 776
 777        tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
 778
 779        tty_ldisc_lock_pair(tty, o_tty);
 780        tty_lock_pair(tty, o_tty);
 781
 782        tty_ldisc_kill(tty);
 783        if (o_tty)
 784                tty_ldisc_kill(o_tty);
 785
 786        tty_unlock_pair(tty, o_tty);
 787        tty_ldisc_unlock_pair(tty, o_tty);
 788
 789        /* And the memory resources remaining (buffers, termios) will be
 790           disposed of when the kref hits zero */
 791
 792        tty_ldisc_debug(tty, "ldisc closed\n");
 793}
 794
 795/**
 796 *      tty_ldisc_init          -       ldisc setup for new tty
 797 *      @tty: tty being allocated
 798 *
 799 *      Set up the line discipline objects for a newly allocated tty. Note that
 800 *      the tty structure is not completely set up when this call is made.
 801 */
 802
 803void tty_ldisc_init(struct tty_struct *tty)
 804{
 805        struct tty_ldisc *ld = tty_ldisc_get(tty, N_TTY);
 806        if (IS_ERR(ld))
 807                panic("n_tty: init_tty");
 808        tty->ldisc = ld;
 809}
 810
 811/**
 812 *      tty_ldisc_init          -       ldisc cleanup for new tty
 813 *      @tty: tty that was allocated recently
 814 *
 815 *      The tty structure must not becompletely set up (tty_ldisc_setup) when
 816 *      this call is made.
 817 */
 818void tty_ldisc_deinit(struct tty_struct *tty)
 819{
 820        tty_ldisc_put(tty->ldisc);
 821        tty->ldisc = NULL;
 822}
 823
 824void tty_ldisc_begin(void)
 825{
 826        /* Setup the default TTY line discipline. */
 827        (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
 828}
 829
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.