From patchwork Mon Mar 30 14:01:50 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Corbet X-Patchwork-Id: 25312 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by ozlabs.org (Postfix) with ESMTP id B937ADDE41 for ; Tue, 31 Mar 2009 01:01:57 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753421AbZC3OB4 (ORCPT ); Mon, 30 Mar 2009 10:01:56 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753208AbZC3OBz (ORCPT ); Mon, 30 Mar 2009 10:01:55 -0400 Received: from vena.lwn.net ([206.168.112.25]:54935 "EHLO vena.lwn.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750927AbZC3OBy convert rfc822-to-8bit (ORCPT ); Mon, 30 Mar 2009 10:01:54 -0400 Received: from bike.lwn.net (jon-dsl [199.45.162.133]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by vena (Postfix) with ESMTP id 4CA1716BEFB; Mon, 30 Mar 2009 08:01:52 -0600 (MDT) Date: Mon, 30 Mar 2009 08:01:50 -0600 From: Jonathan Corbet To: Jarek Poplawski Cc: Markus Trippelsdorf , =?ISO-8859-2?Q?Ilpo_J?= =?ISO-8859-2?Q?=E4rvinen?= , Netdev , LKML Subject: Re: WARNING: at net/ipv4/tcp_input.c:2927 tcp_ack+0xd55/0x1991() Message-ID: <20090330080150.724378b0@bike.lwn.net> In-Reply-To: <20090330085107.GA5822@ff.dom.local> References: <20090328075628.3565eb39@bike.lwn.net> <20090330085107.GA5822@ff.dom.local> Organization: LWN.net X-Mailer: Claws Mail 3.7.0 (GTK+ 2.15.5; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On Mon, 30 Mar 2009 08:51:07 +0000 Jarek Poplawski wrote: > Probably I miss something, but generally in a case like this "a_lock" > doesn't have to be taken in IRQ mode to be dangerous. Eg. if one cpu > is trying to take this lock after fasync_lock (with IRQs disabled), > while another cpu is waiting for fasync_lock in IRQ, which preempted > such "a_lock". The possibility exists, I guess, yes. > Could you give some details of this fix? I just reverse the order of lock acquisition in fasync_helper(). Patch is attached. I'll be sending up a pull request shortly. jon From 4a6a4499693a419a20559c41e33a7bd70bf20a6f Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 27 Mar 2009 12:24:31 -0600 Subject: [PATCH] Fix a lockdep warning in fasync_helper() Lockdep gripes if file->f_lock is taken in a no-IRQ situation, since that is not always the case. We don't really want to disable IRQs for every acquisition of f_lock; instead, just move it outside of fasync_lock. Reported-by: Bartlomiej Zolnierkiewicz Reported-by: Larry Finger Reported-by: Wu Fengguang Signed-off-by: Jonathan Corbet --- fs/fcntl.c | 10 +++++++--- include/linux/fs.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/fcntl.c b/fs/fcntl.c index d865ca6..cc8e4de 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -531,6 +531,12 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap if (!new) return -ENOMEM; } + + /* + * We need to take f_lock first since it's not an IRQ-safe + * lock. + */ + spin_lock(&filp->f_lock); write_lock_irq(&fasync_lock); for (fp = fapp; (fa = *fp) != NULL; fp = &fa->fa_next) { if (fa->fa_file == filp) { @@ -555,14 +561,12 @@ int fasync_helper(int fd, struct file * filp, int on, struct fasync_struct **fap result = 1; } out: - /* Fix up FASYNC bit while still holding fasync_lock */ - spin_lock(&filp->f_lock); if (on) filp->f_flags |= FASYNC; else filp->f_flags &= ~FASYNC; - spin_unlock(&filp->f_lock); write_unlock_irq(&fasync_lock); + spin_unlock(&filp->f_lock); return result; } diff --git a/include/linux/fs.h b/include/linux/fs.h index 7428c6d..2f13c1d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -848,7 +848,7 @@ struct file { #define f_dentry f_path.dentry #define f_vfsmnt f_path.mnt const struct file_operations *f_op; - spinlock_t f_lock; /* f_ep_links, f_flags */ + spinlock_t f_lock; /* f_ep_links, f_flags, no IRQ */ atomic_long_t f_count; unsigned int f_flags; fmode_t f_mode;