From patchwork Thu Mar 28 18:26:06 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 2359071 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork2.kernel.org (Postfix) with ESMTP id 7124ADF2A1 for ; Thu, 28 Mar 2013 18:18:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753082Ab3C1SSn (ORCPT ); Thu, 28 Mar 2013 14:18:43 -0400 Received: from dkim2.fusionio.com ([66.114.96.54]:59846 "EHLO dkim2.fusionio.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752963Ab3C1SSm (ORCPT ); Thu, 28 Mar 2013 14:18:42 -0400 Received: from mx2.fusionio.com (unknown [10.101.1.160]) by dkim2.fusionio.com (Postfix) with ESMTP id 3EA4B9A067F for ; Thu, 28 Mar 2013 12:18:42 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=fusionio.com; s=default; t=1364494722; bh=Mvh4q5xt9SGl+hI07039dbKBQR6OEsMYDZvoAm9vT0g=; h=From:To:Subject:Date; b=n3/a9dLlUxmB5EOrbRnh7tbPHITfVXwwo+EZcVrDmFj6NrOHFRCiF7797gNwF5hOK 4JYnzrjyDHoAlGS+AOesRSBCFUx5cnKO/efJRs7Q8nPZzuiLHUV+GzuoQPqcc38pbk LEt4NHrhgFKGhssFds76vKf8t+3fUsjTsSFVx9Zk= X-ASG-Debug-ID: 1364494721-0421b5172b38bc0001-6jHSXT Received: from mail1.int.fusionio.com (mail1.int.fusionio.com [10.101.1.21]) by mx2.fusionio.com with ESMTP id 9QvIcCO0E8urEIbE (version=TLSv1 cipher=AES128-SHA bits=128 verify=NO) for ; Thu, 28 Mar 2013 12:18:41 -0600 (MDT) X-Barracuda-Envelope-From: JBacik@fusionio.com Received: from localhost (98.26.82.158) by mail.fusionio.com (10.101.1.19) with Microsoft SMTP Server (TLS) id 8.3.83.0; Thu, 28 Mar 2013 12:18:40 -0600 From: Josef Bacik To: Subject: [PATCH] Btrfs: find free ino outside of the transaction and cleanup properly Date: Thu, 28 Mar 2013 14:26:06 -0400 X-ASG-Orig-Subj: [PATCH] Btrfs: find free ino outside of the transaction and cleanup properly Message-ID: <1364495166-19396-1-git-send-email-jbacik@fusionio.com> X-Mailer: git-send-email 1.7.7.6 MIME-Version: 1.0 X-Barracuda-Connect: mail1.int.fusionio.com[10.101.1.21] X-Barracuda-Start-Time: 1364494721 X-Barracuda-Encrypted: AES128-SHA X-Barracuda-URL: http://10.101.1.181:8000/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at fusionio.com X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using global scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=9.0 tests=MARKETING_SUBJECT X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.2.126504 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org A user reported a hang on mount and it looks like we are waiting for the inode cache to fill up. The caching thread will stop if it sees that we are committing a transaction every time it has to move leaves and then it will re-search. But we call btrfs_find_free_ino() inside of a transaction so if the transaction goes to commit it will be held open while we wait for an inode to show up. This will make the caching thread take for freaking ever and appear to lock up the box. The other thing this patch fixes is that if we have an error creating the inode we won't properly free up the inode number we just took, so we could leak inode numbers if we have inode caching on in this case. Thanks, Signed-off-by: Josef Bacik Reviewed-by: Liu Bo --- fs/btrfs/inode.c | 52 ++++++++++++++++++++++++++++++++-------------------- 1 files changed, 32 insertions(+), 20 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b883815..725e268 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -5713,23 +5713,26 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, if (!new_valid_dev(rdev)) return -EINVAL; + err = btrfs_find_free_ino(root, &objectid); + if (err) + return err; + /* * 2 for inode item and ref * 2 for dir items * 1 for xattr if selinux is on */ trans = btrfs_start_transaction(root, 5); - if (IS_ERR(trans)) + if (IS_ERR(trans)) { + btrfs_return_ino(root, objectid); return PTR_ERR(trans); - - err = btrfs_find_free_ino(root, &objectid); - if (err) - goto out_unlock; + } inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, dentry->d_name.len, btrfs_ino(dir), objectid, mode, &index); if (IS_ERR(inode)) { + btrfs_return_ino(root, objectid); err = PTR_ERR(inode); goto out_unlock; } @@ -5777,23 +5780,26 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, u64 objectid; u64 index = 0; + err = btrfs_find_free_ino(root, &objectid); + if (err) + return err; + /* * 2 for inode item and ref * 2 for dir items * 1 for xattr if selinux is on */ trans = btrfs_start_transaction(root, 5); - if (IS_ERR(trans)) + if (IS_ERR(trans)) { + btrfs_return_ino(root, objectid); return PTR_ERR(trans); - - err = btrfs_find_free_ino(root, &objectid); - if (err) - goto out_unlock; + } inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, dentry->d_name.len, btrfs_ino(dir), objectid, mode, &index); if (IS_ERR(inode)) { + btrfs_return_ino(root, objectid); err = PTR_ERR(inode); goto out_unlock; } @@ -5906,24 +5912,27 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) u64 objectid = 0; u64 index = 0; + err = btrfs_find_free_ino(root, &objectid); + if (err) + return err; + /* * 2 items for inode and ref * 2 items for dir items * 1 for xattr if selinux is on */ trans = btrfs_start_transaction(root, 5); - if (IS_ERR(trans)) + if (IS_ERR(trans)) { + btrfs_return_ino(root, objectid); return PTR_ERR(trans); - - err = btrfs_find_free_ino(root, &objectid); - if (err) - goto out_fail; + } inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, dentry->d_name.len, btrfs_ino(dir), objectid, S_IFDIR | mode, &index); if (IS_ERR(inode)) { err = PTR_ERR(inode); + btrfs_return_ino(root, objectid); goto out_fail; } @@ -8407,23 +8416,26 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, if (name_len > BTRFS_MAX_INLINE_DATA_SIZE(root)) return -ENAMETOOLONG; + err = btrfs_find_free_ino(root, &objectid); + if (err) + return err; + /* * 2 items for inode item and ref * 2 items for dir items * 1 item for xattr if selinux is on */ trans = btrfs_start_transaction(root, 5); - if (IS_ERR(trans)) + if (IS_ERR(trans)) { + btrfs_return_ino(root, objectid); return PTR_ERR(trans); - - err = btrfs_find_free_ino(root, &objectid); - if (err) - goto out_unlock; + } inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, dentry->d_name.len, btrfs_ino(dir), objectid, S_IFLNK|S_IRWXUGO, &index); if (IS_ERR(inode)) { + btrfs_return_ino(root, objectid); err = PTR_ERR(inode); goto out_unlock; }