From patchwork Wed Nov 26 10:23:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Theodore Ts'o X-Patchwork-Id: 415060 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.180.67]) by ozlabs.org (Postfix) with ESMTP id D1991140168 for ; Wed, 26 Nov 2014 21:25:14 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751508AbaKZKYT (ORCPT ); Wed, 26 Nov 2014 05:24:19 -0500 Received: from imap.thunk.org ([74.207.234.97]:52557 "EHLO imap.thunk.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751338AbaKZKYI (ORCPT ); Wed, 26 Nov 2014 05:24:08 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=thunk.org; s=ef5046eb; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=UKkO2ur6FCjX6kUqrvW6aJYG2DVCxrOx5zSQ8TLBxs8=; b=rq+sOs3bbRmlHdGqcqeDMSD98rIbV00sSNSr8Rwz5rfaJWNbj+Ywvps1rMoeFfOGw0vhHq8xVNq8kORN2+j9H8eTKFzHtA2AvwfEh+a3PSAxKRCrK8kT60lo7X73BR/vkDnjKkZTtuaQCJkChuKTMAJPaTRDAfInU3IUddoyR/8=; Received: from root (helo=closure.thunk.org) by imap.thunk.org with local-esmtp (Exim 4.80) (envelope-from ) id 1XtZlW-0003Qy-Te; Wed, 26 Nov 2014 10:24:07 +0000 Received: by closure.thunk.org (Postfix, from userid 15806) id 6C51F5802D0; Wed, 26 Nov 2014 05:24:02 -0500 (EST) From: Theodore Ts'o To: Linux Filesystem Development List Cc: Ext4 Developers List , Linux btrfs Developers List , XFS Developers , Theodore Ts'o Subject: [PATCH-v4 5/7] vfs: add find_active_inode_nowait() function Date: Wed, 26 Nov 2014 05:23:55 -0500 Message-Id: <1416997437-26092-6-git-send-email-tytso@mit.edu> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1416997437-26092-1-git-send-email-tytso@mit.edu> References: <1416997437-26092-1-git-send-email-tytso@mit.edu> X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: tytso@thunk.org X-SA-Exim-Scanned: No (on imap.thunk.org); SAEximRunCond expanded to false Sender: linux-ext4-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org Add a new function find_active_inode_nowait() which will never block. If there is an inode being freed or is still being initialized, this function will return NULL instead of blocking waiting for an inode to be freed or to finish initializing. Hence, a negative return from this function does not mean that inode number is free for use. It is useful for callers that want to opportunistically do some work on an inode only if it is present and available in the cache, and where blocking is not an option. Signed-off-by: Theodore Ts'o --- fs/inode.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 2 ++ 2 files changed, 38 insertions(+) diff --git a/fs/inode.c b/fs/inode.c index b2fea60..0b4c6ae 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1283,6 +1283,42 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino) } EXPORT_SYMBOL(ilookup); +/** + * find_active_inode_nowait - find an active inode in the inode cache + * @sb: super block of file system to search + * @ino: inode number to search for + * + * Search for an active inode @ino in the inode cache, and if the + * inode is in the cache, the inode is returned with an incremented + * reference count. If the inode is being freed or is newly + * initialized, return nothing instead of trying to wait for the inode + * initialization or destruction to be complete. + */ +struct inode *find_active_inode_nowait(struct super_block *sb, + unsigned long ino) +{ + struct hlist_head *head = inode_hashtable + hash(sb, ino); + struct inode *inode, *ret_inode = NULL; + + spin_lock(&inode_hash_lock); + hlist_for_each_entry(inode, head, i_hash) { + if ((inode->i_ino != ino) || + (inode->i_sb != sb)) + continue; + spin_lock(&inode->i_lock); + if ((inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) == 0) { + __iget(inode); + ret_inode = inode; + } + spin_unlock(&inode->i_lock); + goto out; + } +out: + spin_unlock(&inode_hash_lock); + return ret_inode; +} +EXPORT_SYMBOL(find_active_inode_nowait); + int insert_inode_locked(struct inode *inode) { struct super_block *sb = inode->i_sb; diff --git a/include/linux/fs.h b/include/linux/fs.h index d0a2181..dc615ec 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2419,6 +2419,8 @@ extern struct inode *ilookup(struct super_block *sb, unsigned long ino); extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); extern struct inode * iget_locked(struct super_block *, unsigned long); +extern struct inode *find_active_inode_nowait(struct super_block *, + unsigned long); extern int insert_inode_locked4(struct inode *, unsigned long, int (*test)(struct inode *, void *), void *); extern int insert_inode_locked(struct inode *); #ifdef CONFIG_DEBUG_LOCK_ALLOC