mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-23 14:54:03 +00:00
tty: Separate release semantics of ldisc reference
tty_ldisc_ref()/tty_ldisc_unref() have usage semantics equivalent to down_read_trylock()/up_read(). Only callers of tty_ldisc_put() are performing the additional operations necessary for proper ldisc teardown, and then only after ensuring no outstanding 'read lock' remains. Thus, tty_ldisc_unref() should never be the last reference; WARN if it is. Conversely, tty_ldisc_put() should never be destructing if the use count != 1. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
8842dda236
commit
ebc9baed42
1 changed files with 35 additions and 34 deletions
|
@ -49,37 +49,6 @@ static inline struct tty_ldisc *get_ldisc(struct tty_ldisc *ld)
|
||||||
return ld;
|
return ld;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void put_ldisc(struct tty_ldisc *ld)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
if (WARN_ON_ONCE(!ld))
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is the last user, free the ldisc, and
|
|
||||||
* release the ldisc ops.
|
|
||||||
*
|
|
||||||
* We really want an "atomic_dec_and_raw_lock_irqsave()",
|
|
||||||
* but we don't have it, so this does it by hand.
|
|
||||||
*/
|
|
||||||
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
|
||||||
if (atomic_dec_and_test(&ld->users)) {
|
|
||||||
struct tty_ldisc_ops *ldo = ld->ops;
|
|
||||||
|
|
||||||
ldo->refcount--;
|
|
||||||
module_put(ldo->owner);
|
|
||||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
|
||||||
|
|
||||||
kfree(ld);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
|
||||||
|
|
||||||
if (waitqueue_active(&ld->wq_idle))
|
|
||||||
wake_up(&ld->wq_idle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tty_register_ldisc - install a line discipline
|
* tty_register_ldisc - install a line discipline
|
||||||
* @disc: ldisc number
|
* @disc: ldisc number
|
||||||
|
@ -363,13 +332,45 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
|
||||||
|
|
||||||
void tty_ldisc_deref(struct tty_ldisc *ld)
|
void tty_ldisc_deref(struct tty_ldisc *ld)
|
||||||
{
|
{
|
||||||
put_ldisc(ld);
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!ld))
|
||||||
|
return;
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||||
|
/*
|
||||||
|
* WARNs if one-too-many reader references were released
|
||||||
|
* - the last reference must be released with tty_ldisc_put
|
||||||
|
*/
|
||||||
|
WARN_ON(atomic_dec_and_test(&ld->users));
|
||||||
|
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||||
|
|
||||||
|
if (waitqueue_active(&ld->wq_idle))
|
||||||
|
wake_up(&ld->wq_idle);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tty_ldisc_deref);
|
EXPORT_SYMBOL_GPL(tty_ldisc_deref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tty_ldisc_put - release the ldisc
|
||||||
|
*
|
||||||
|
* Complement of tty_ldisc_get().
|
||||||
|
*/
|
||||||
static inline void tty_ldisc_put(struct tty_ldisc *ld)
|
static inline void tty_ldisc_put(struct tty_ldisc *ld)
|
||||||
{
|
{
|
||||||
put_ldisc(ld);
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (WARN_ON_ONCE(!ld))
|
||||||
|
return;
|
||||||
|
|
||||||
|
raw_spin_lock_irqsave(&tty_ldisc_lock, flags);
|
||||||
|
|
||||||
|
/* unreleased reader reference(s) will cause this WARN */
|
||||||
|
WARN_ON(!atomic_dec_and_test(&ld->users));
|
||||||
|
|
||||||
|
ld->ops->refcount--;
|
||||||
|
module_put(ld->ops->owner);
|
||||||
|
kfree(ld);
|
||||||
|
raw_spin_unlock_irqrestore(&tty_ldisc_lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1001,7 +1002,7 @@ void tty_ldisc_init(struct tty_struct *tty)
|
||||||
*/
|
*/
|
||||||
void tty_ldisc_deinit(struct tty_struct *tty)
|
void tty_ldisc_deinit(struct tty_struct *tty)
|
||||||
{
|
{
|
||||||
put_ldisc(tty->ldisc);
|
tty_ldisc_put(tty->ldisc);
|
||||||
tty_ldisc_assign(tty, NULL);
|
tty_ldisc_assign(tty, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue