| From stable-bounces@linux.kernel.org Wed Mar 7 18:46:31 2007 |
| From: Philipp Reisner <philipp.reisner@linbit.com> |
| Date: Wed, 07 Mar 2007 18:45:12 -0800 (PST) |
| Subject: Fix callback bug in connector |
| To: stable@kernel.org |
| Cc: bunk@stusta.de |
| Message-ID: <20070307.184512.78710320.davem@davemloft.net> |
| |
| From: Philipp Reisner <philipp.reisner@linbit.com> |
| |
| [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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/connector/connector.c | 22 +++++++++++----------- |
| 1 file changed, 11 insertions(+), 11 deletions(-) |
| |
| --- 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_ms |
| } 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; |
| } |