Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6:
tty-ldisc: be more careful in 'put_ldisc' locking
tty-ldisc: turn ldisc user count into a proper refcount
tty-ldisc: make refcount be atomic_t 'users' count

+54 -100
+53 -99
drivers/char/tty_ldisc.c
··· 48 /* Line disc dispatch table */ 49 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; 50 51 /** 52 * tty_register_ldisc - install a line discipline 53 * @disc: ldisc number ··· 177 /* lock it */ 178 ldops->refcount++; 179 ld->ops = ldops; 180 - ld->refcount = 0; 181 err = 0; 182 } 183 } ··· 216 return ld; 217 } 218 219 - /** 220 - * tty_ldisc_put - drop ldisc reference 221 - * @ld: ldisc 222 - * 223 - * Drop a reference to a line discipline. Manage refcounts and 224 - * module usage counts. Free the ldisc once the recount hits zero. 225 - * 226 - * Locking: 227 - * takes tty_ldisc_lock to guard against ldisc races 228 - */ 229 - 230 - static void tty_ldisc_put(struct tty_ldisc *ld) 231 - { 232 - unsigned long flags; 233 - int disc = ld->ops->num; 234 - struct tty_ldisc_ops *ldo; 235 - 236 - BUG_ON(disc < N_TTY || disc >= NR_LDISCS); 237 - 238 - spin_lock_irqsave(&tty_ldisc_lock, flags); 239 - ldo = tty_ldiscs[disc]; 240 - BUG_ON(ldo->refcount == 0); 241 - ldo->refcount--; 242 - module_put(ldo->owner); 243 - spin_unlock_irqrestore(&tty_ldisc_lock, flags); 244 - WARN_ON(ld->refcount); 245 - kfree(ld); 246 - } 247 - 248 static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) 249 { 250 return (*pos < NR_LDISCS) ? pos : NULL; ··· 240 if (IS_ERR(ld)) 241 return 0; 242 seq_printf(m, "%-10s %2d\n", ld->ops->name ? ld->ops->name : "???", i); 243 - tty_ldisc_put(ld); 244 return 0; 245 } 246 ··· 294 * Locking: takes tty_ldisc_lock 295 */ 296 297 - static int tty_ldisc_try(struct tty_struct *tty) 298 { 299 unsigned long flags; 300 struct tty_ldisc *ld; 301 - int ret = 0; 302 303 spin_lock_irqsave(&tty_ldisc_lock, flags); 304 - ld = tty->ldisc; 305 - if (test_bit(TTY_LDISC, &tty->flags)) { 306 - ld->refcount++; 307 - ret = 1; 308 - } 309 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 310 - return ret; 311 } 312 313 /** ··· 325 326 struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) 327 { 328 /* wait_event is a macro */ 329 - wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); 330 - WARN_ON(tty->ldisc->refcount == 0); 331 - return tty->ldisc; 332 } 333 EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); 334 ··· 346 347 struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) 348 { 349 - if (tty_ldisc_try(tty)) 350 - return tty->ldisc; 351 - return NULL; 352 } 353 EXPORT_SYMBOL_GPL(tty_ldisc_ref); 354 ··· 362 363 void tty_ldisc_deref(struct tty_ldisc *ld) 364 { 365 - unsigned long flags; 366 - 367 - BUG_ON(ld == NULL); 368 - 369 - spin_lock_irqsave(&tty_ldisc_lock, flags); 370 - if (ld->refcount == 0) 371 - printk(KERN_ERR "tty_ldisc_deref: no references.\n"); 372 - else 373 - ld->refcount--; 374 - if (ld->refcount == 0) 375 - wake_up(&tty_ldisc_wait); 376 - spin_unlock_irqrestore(&tty_ldisc_lock, flags); 377 } 378 EXPORT_SYMBOL_GPL(tty_ldisc_deref); 379 380 /** 381 * tty_ldisc_enable - allow ldisc use ··· 519 } 520 521 /** 522 - * tty_ldisc_wait_idle - wait for the ldisc to become idle 523 - * @tty: tty to wait for 524 - * 525 - * Wait for the line discipline to become idle. The discipline must 526 - * have been halted for this to guarantee it remains idle. 527 - * 528 - * tty_ldisc_lock protects the ref counts currently. 529 - */ 530 - 531 - static int tty_ldisc_wait_idle(struct tty_struct *tty) 532 - { 533 - unsigned long flags; 534 - spin_lock_irqsave(&tty_ldisc_lock, flags); 535 - while (tty->ldisc->refcount) { 536 - spin_unlock_irqrestore(&tty_ldisc_lock, flags); 537 - if (wait_event_timeout(tty_ldisc_wait, 538 - tty->ldisc->refcount == 0, 5 * HZ) == 0) 539 - return -EBUSY; 540 - spin_lock_irqsave(&tty_ldisc_lock, flags); 541 - } 542 - spin_unlock_irqrestore(&tty_ldisc_lock, flags); 543 - return 0; 544 - } 545 - 546 - /** 547 * tty_set_ldisc - set line discipline 548 * @tty: the terminal to set 549 * @ldisc: the line discipline ··· 612 mutex_unlock(&tty->ldisc_mutex); 613 614 flush_scheduled_work(); 615 - 616 - /* Let any existing reference holders finish */ 617 - retval = tty_ldisc_wait_idle(tty); 618 - if (retval < 0) { 619 - clear_bit(TTY_LDISC_CHANGING, &tty->flags); 620 - tty_ldisc_put(new_ldisc); 621 - return retval; 622 - } 623 624 mutex_lock(&tty->ldisc_mutex); 625 if (test_bit(TTY_HUPPED, &tty->flags)) { ··· 758 if (tty->ldisc) { /* Not yet closed */ 759 /* Switch back to N_TTY */ 760 tty_ldisc_halt(tty); 761 - tty_ldisc_wait_idle(tty); 762 tty_ldisc_reinit(tty); 763 /* At this point we have a closed ldisc and we want to 764 reopen it. We could defer this to the next open but ··· 821 822 tty_ldisc_halt(tty); 823 flush_scheduled_work(); 824 - 825 - /* 826 - * Wait for any short term users (we know they are just driver 827 - * side waiters as the file is closing so user count on the file 828 - * side is zero. 829 - */ 830 - 831 - tty_ldisc_wait_idle(tty); 832 833 mutex_lock(&tty->ldisc_mutex); 834 /*
··· 48 /* Line disc dispatch table */ 49 static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; 50 51 + static inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld) 52 + { 53 + if (ld) 54 + atomic_inc(&ld->users); 55 + return ld; 56 + } 57 + 58 + static void put_ldisc(struct tty_ldisc *ld) 59 + { 60 + unsigned long flags; 61 + 62 + if (WARN_ON_ONCE(!ld)) 63 + return; 64 + 65 + /* 66 + * If this is the last user, free the ldisc, and 67 + * release the ldisc ops. 68 + * 69 + * We really want an "atomic_dec_and_lock_irqsave()", 70 + * but we don't have it, so this does it by hand. 71 + */ 72 + local_irq_save(flags); 73 + if (atomic_dec_and_lock(&ld->users, &tty_ldisc_lock)) { 74 + struct tty_ldisc_ops *ldo = ld->ops; 75 + 76 + ldo->refcount--; 77 + module_put(ldo->owner); 78 + spin_unlock_irqrestore(&tty_ldisc_lock, flags); 79 + 80 + kfree(ld); 81 + return; 82 + } 83 + local_irq_restore(flags); 84 + } 85 + 86 /** 87 * tty_register_ldisc - install a line discipline 88 * @disc: ldisc number ··· 142 /* lock it */ 143 ldops->refcount++; 144 ld->ops = ldops; 145 + atomic_set(&ld->users, 1); 146 err = 0; 147 } 148 } ··· 181 return ld; 182 } 183 184 static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) 185 { 186 return (*pos < NR_LDISCS) ? pos : NULL; ··· 234 if (IS_ERR(ld)) 235 return 0; 236 seq_printf(m, "%-10s %2d\n", ld->ops->name ? ld->ops->name : "???", i); 237 + put_ldisc(ld); 238 return 0; 239 } 240 ··· 288 * Locking: takes tty_ldisc_lock 289 */ 290 291 + static struct tty_ldisc *tty_ldisc_try(struct tty_struct *tty) 292 { 293 unsigned long flags; 294 struct tty_ldisc *ld; 295 296 spin_lock_irqsave(&tty_ldisc_lock, flags); 297 + ld = NULL; 298 + if (test_bit(TTY_LDISC, &tty->flags)) 299 + ld = get_ldisc(tty->ldisc); 300 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 301 + return ld; 302 } 303 304 /** ··· 322 323 struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) 324 { 325 + struct tty_ldisc *ld; 326 + 327 /* wait_event is a macro */ 328 + wait_event(tty_ldisc_wait, (ld = tty_ldisc_try(tty)) != NULL); 329 + return ld; 330 } 331 EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); 332 ··· 342 343 struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) 344 { 345 + return tty_ldisc_try(tty); 346 } 347 EXPORT_SYMBOL_GPL(tty_ldisc_ref); 348 ··· 360 361 void tty_ldisc_deref(struct tty_ldisc *ld) 362 { 363 + put_ldisc(ld); 364 } 365 EXPORT_SYMBOL_GPL(tty_ldisc_deref); 366 + 367 + static inline void tty_ldisc_put(struct tty_ldisc *ld) 368 + { 369 + put_ldisc(ld); 370 + } 371 372 /** 373 * tty_ldisc_enable - allow ldisc use ··· 523 } 524 525 /** 526 * tty_set_ldisc - set line discipline 527 * @tty: the terminal to set 528 * @ldisc: the line discipline ··· 641 mutex_unlock(&tty->ldisc_mutex); 642 643 flush_scheduled_work(); 644 645 mutex_lock(&tty->ldisc_mutex); 646 if (test_bit(TTY_HUPPED, &tty->flags)) { ··· 795 if (tty->ldisc) { /* Not yet closed */ 796 /* Switch back to N_TTY */ 797 tty_ldisc_halt(tty); 798 tty_ldisc_reinit(tty); 799 /* At this point we have a closed ldisc and we want to 800 reopen it. We could defer this to the next open but ··· 859 860 tty_ldisc_halt(tty); 861 flush_scheduled_work(); 862 863 mutex_lock(&tty->ldisc_mutex); 864 /*
+1 -1
include/linux/tty_ldisc.h
··· 144 145 struct tty_ldisc { 146 struct tty_ldisc_ops *ops; 147 - int refcount; 148 }; 149 150 #define TTY_LDISC_MAGIC 0x5403
··· 144 145 struct tty_ldisc { 146 struct tty_ldisc_ops *ops; 147 + atomic_t users; 148 }; 149 150 #define TTY_LDISC_MAGIC 0x5403