From mboxrd@z Thu Jan 1 00:00:00 1970 From: Steven Whitehouse Subject: Re: [RFC PATCH] locks: skip posix unlock when there are no posix locks Date: Fri, 19 Aug 2011 10:40:39 +0100 Message-ID: <1313746839.2704.29.camel@menhir> References: <20110818203816.GB315@redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit Cc: linux-fsdevel@vger.kernel.org To: David Teigland Return-path: Received: from mx1.redhat.com ([209.132.183.28]:63374 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752054Ab1HSKVm (ORCPT ); Fri, 19 Aug 2011 06:21:42 -0400 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p7J9efjO024720 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 19 Aug 2011 05:40:41 -0400 In-Reply-To: <20110818203816.GB315@redhat.com> Sender: linux-fsdevel-owner@vger.kernel.org List-ID: Hi, On Thu, 2011-08-18 at 16:38 -0400, David Teigland wrote: > When i_flock contains only flocks, the posix unlock is > extraneous. On gfs2, ocfs2, and possibly others, the > posix unlock can be costly, and something to avoid if > possible. > > As the comment implies, there will be races here. The > question is, do those races become harmful with this > new loop? > The problem is that you don't hold the right lock (file_lock_lock) at this point, so its ok to test the i_flock pointer for being NULL, but its not ok to dereference it. Since this check is made for every file that is closed, taking a global spinlock in this code path is frowned upon from a performance PoV. > Signed-off-by: David Teigland > --- > fs/locks.c | 14 +++++++++++++- > 1 files changed, 13 insertions(+), 1 deletions(-) > > diff --git a/fs/locks.c b/fs/locks.c > index 703f545..4507401 100644 > --- a/fs/locks.c > +++ b/fs/locks.c > @@ -1982,15 +1982,27 @@ out: > void locks_remove_posix(struct file *filp, fl_owner_t owner) > { > struct file_lock lock; > + struct file_lock **before; > + struct inode *inode; > > /* > * If there are no locks held on this file, we don't need to call > * posix_lock_file(). Another process could be setting a lock on this > * file at the same time, but we wouldn't remove that lock anyway. > */ > - if (!filp->f_path.dentry->d_inode->i_flock) > + inode = filp->f_path.dentry->d_inode; > + > + if (!inode->i_flock) > return; > So if you take the lock at this point, and drop it after the loop, that should resolve the issue without incurring the extra overhead on every single close, Steve. > + for_each_lock(inode, before) { > + struct file_lock *fl = *before; > + if (IS_POSIX(fl)) > + goto do_unlock; > + } > + return; > + > +do_unlock: > lock.fl_type = F_UNLCK; > lock.fl_flags = FL_POSIX | FL_CLOSE; > lock.fl_start = 0;