diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2007-03-07 20:55:39 (GMT) |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-03-08 00:08:08 (GMT) |
commit | 05e52dd7396514648fba6c275eb7b49eca333c6d (patch) | |
tree | 144ecb4d6986128773e6d5aad4e9aae52ce554d1 | |
parent | 151a99317ee9efcfd3e642da62e1edf4f47fcb3e (diff) | |
download | linux-05e52dd7396514648fba6c275eb7b49eca333c6d.tar.xz |
[CONNECTOR]: Bugfix for cn_call_callback()
When system under heavy stress and must allocate new work
instead of reusing old one, new work must use correct
completion callback.
Patch is based on Philipp's and Lars' work.
I only cleaned small stuff (and removed spaces instead of tabs).
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/connector/connector.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index a44db75..a905f78 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(cn_netlink_send); */ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), void *data) { - struct cn_callback_entry *__cbq; + struct cn_callback_entry *__cbq, *__new_cbq; struct cn_dev *dev = &cdev; int err = -ENODEV; @@ -148,27 +148,27 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v } else { struct cn_callback_data *d; - __cbq = kzalloc(sizeof(*__cbq), GFP_ATOMIC); - if (__cbq) { - d = &__cbq->data; + err = -ENOMEM; + __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC); + if (__new_cbq) { + d = &__new_cbq->data; d->callback_priv = msg; d->callback = __cbq->data.callback; d->ddata = data; d->destruct_data = destruct_data; - d->free = __cbq; + d->free = __new_cbq; - INIT_WORK(&__cbq->work, + INIT_WORK(&__new_cbq->work, &cn_queue_wrapper); - + if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + &__new_cbq->work)) err = 0; else { - kfree(__cbq); + kfree(__new_cbq); err = -EINVAL; } - } else - err = -ENOMEM; + } } break; } |