Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756232AbZDWLtS (ORCPT ); Thu, 23 Apr 2009 07:49:18 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756174AbZDWLsY (ORCPT ); Thu, 23 Apr 2009 07:48:24 -0400 Received: from mtagate7.de.ibm.com ([195.212.29.156]:39245 "EHLO mtagate7.de.ibm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755594AbZDWLsV (ORCPT ); Thu, 23 Apr 2009 07:48:21 -0400 Message-Id: <20090423114725.327324472@de.ibm.com> References: <20090423114638.865214111@de.ibm.com> User-Agent: quilt/0.46-1 Date: Thu, 23 Apr 2009 13:46:40 +0200 From: Martin Schwidefsky To: linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org Cc: Heiko Carstens , Gerald Schaefer , Martin Schwidefsky Subject: [patch 2/6] appldata: avoid deadlock with appldata_mem Content-Disposition: inline; filename=002-appldata-mem-deadlock.diff Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4757 Lines: 157 From: Gerald Schaefer The appldata_ops callbacks are called with a spin_lock held. But the appldata_mem callback then calls all_vm_events(), which calls get_online_cpus(), which might sleep. This possible deadlock is fixed by using a mutex instead of a spin_lock. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- arch/s390/appldata/appldata_base.c | 32 ++++++++++++++++---------------- arch/s390/appldata/appldata_mem.c | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) Index: quilt-2.6/arch/s390/appldata/appldata_base.c =================================================================== --- quilt-2.6.orig/arch/s390/appldata/appldata_base.c +++ quilt-2.6/arch/s390/appldata/appldata_base.c @@ -98,7 +98,7 @@ static DECLARE_WORK(appldata_work, appld /* * Ops list */ -static DEFINE_SPINLOCK(appldata_ops_lock); +static DEFINE_MUTEX(appldata_ops_mutex); static LIST_HEAD(appldata_ops_list); @@ -129,14 +129,14 @@ static void appldata_work_fn(struct work i = 0; get_online_cpus(); - spin_lock(&appldata_ops_lock); + mutex_lock(&appldata_ops_mutex); list_for_each(lh, &appldata_ops_list) { ops = list_entry(lh, struct appldata_ops, list); if (ops->active == 1) { ops->callback(ops->data); } } - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); put_online_cpus(); } @@ -338,7 +338,7 @@ appldata_generic_handler(ctl_table *ctl, struct list_head *lh; found = 0; - spin_lock(&appldata_ops_lock); + mutex_lock(&appldata_ops_mutex); list_for_each(lh, &appldata_ops_list) { tmp_ops = list_entry(lh, struct appldata_ops, list); if (&tmp_ops->ctl_table[2] == ctl) { @@ -346,15 +346,15 @@ appldata_generic_handler(ctl_table *ctl, } } if (!found) { - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); return -ENODEV; } ops = ctl->data; if (!try_module_get(ops->owner)) { // protect this function - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); return -ENODEV; } - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); if (!*lenp || *ppos) { *lenp = 0; @@ -378,11 +378,11 @@ appldata_generic_handler(ctl_table *ctl, return -EFAULT; } - spin_lock(&appldata_ops_lock); + mutex_lock(&appldata_ops_mutex); if ((buf[0] == '1') && (ops->active == 0)) { // protect work queue callback if (!try_module_get(ops->owner)) { - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); module_put(ops->owner); return -ENODEV; } @@ -407,7 +407,7 @@ appldata_generic_handler(ctl_table *ctl, "failed with rc=%d\n", ops->name, rc); module_put(ops->owner); } - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); out: *lenp = len; *ppos += len; @@ -433,9 +433,9 @@ int appldata_register_ops(struct appldat if (!ops->ctl_table) return -ENOMEM; - spin_lock(&appldata_ops_lock); + mutex_lock(&appldata_ops_mutex); list_add(&ops->list, &appldata_ops_list); - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); ops->ctl_table[0].procname = appldata_proc_name; ops->ctl_table[0].maxlen = 0; @@ -452,9 +452,9 @@ int appldata_register_ops(struct appldat goto out; return 0; out: - spin_lock(&appldata_ops_lock); + mutex_lock(&appldata_ops_mutex); list_del(&ops->list); - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); kfree(ops->ctl_table); return -ENOMEM; } @@ -466,9 +466,9 @@ out: */ void appldata_unregister_ops(struct appldata_ops *ops) { - spin_lock(&appldata_ops_lock); + mutex_lock(&appldata_ops_mutex); list_del(&ops->list); - spin_unlock(&appldata_ops_lock); + mutex_unlock(&appldata_ops_mutex); unregister_sysctl_table(ops->sysctl_header); kfree(ops->ctl_table); } Index: quilt-2.6/arch/s390/appldata/appldata_mem.c =================================================================== --- quilt-2.6.orig/arch/s390/appldata/appldata_mem.c +++ quilt-2.6/arch/s390/appldata/appldata_mem.c @@ -78,7 +78,7 @@ static void appldata_get_mem_data(void * { /* * don't put large structures on the stack, we are - * serialized through the appldata_ops_lock and can use static + * serialized through the appldata_ops_mutex and can use static */ static struct sysinfo val; unsigned long ev[NR_VM_EVENT_ITEMS]; -- blue skies, Martin. "Reality continues to ruin my life." - Calvin. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/