From patchwork Thu May 5 01:34:16 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Filipe Manana X-Patchwork-Id: 9026201 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id A1AA69F372 for ; Thu, 5 May 2016 16:44:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CA7C0203A0 for ; Thu, 5 May 2016 16:44:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CE2B4203A5 for ; Thu, 5 May 2016 16:44:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757815AbcEEQoV (ORCPT ); Thu, 5 May 2016 12:44:21 -0400 Received: from mail.kernel.org ([198.145.29.136]:47177 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757357AbcEEQoU (ORCPT ); Thu, 5 May 2016 12:44:20 -0400 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E7FF1203B8 for ; Thu, 5 May 2016 16:44:18 +0000 (UTC) Received: from debian3.lan (bl12-226-64.dsl.telepac.pt [85.245.226.64]) (using TLSv1.2 with cipher AES128-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id C8094203A5 for ; Thu, 5 May 2016 16:44:17 +0000 (UTC) From: fdmanana@kernel.org To: linux-btrfs@vger.kernel.org Subject: [PATCH 3/3] Btrfs: pin logs earlier when doing a rename exchange operation Date: Thu, 5 May 2016 02:34:16 +0100 Message-Id: <1462412056-27878-3-git-send-email-fdmanana@kernel.org> X-Mailer: git-send-email 2.7.0.rc3 In-Reply-To: <1462412056-27878-1-git-send-email-fdmanana@kernel.org> References: <1462412056-27878-1-git-send-email-fdmanana@kernel.org> X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, DATE_IN_PAST_12_24, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Filipe Manana The btrfs_rename_exchange() started as a copy-paste from btrfs_rename(), which had a race fixed by my previous patch titled "Btrfs: pin log earlier when renaming", and so it suffers from the same problem. We pin the logs of the affected roots after we insert the new inode references, leaving a time window where concurrent tasks logging the inodes can end up logging both the new and old references, resulting in log trees that when replayed can turn the metadata into inconsistent states. This behaviour was added to btrfs_rename() in 2009 without any explanation about why not pinning the logs earlier, just leaving a comment about the posibility for the race. As of today it's perfectly safe and sane to pin the logs before we start doing any of the steps involved in the rename operation. Signed-off-by: Filipe Manana --- fs/btrfs/inode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 503d749..dab6c08f 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -9458,6 +9458,8 @@ static int btrfs_rename_exchange(struct inode *old_dir, /* force full log commit if subvolume involved. */ btrfs_set_log_full_commit(root->fs_info, trans); } else { + btrfs_pin_log_trans(root); + root_log_pinned = true; ret = btrfs_insert_inode_ref(trans, dest, new_dentry->d_name.name, new_dentry->d_name.len, @@ -9465,8 +9467,6 @@ static int btrfs_rename_exchange(struct inode *old_dir, btrfs_ino(new_dir), old_idx); if (ret) goto out_fail; - btrfs_pin_log_trans(root); - root_log_pinned = true; } /* And now for the dest. */ @@ -9474,6 +9474,8 @@ static int btrfs_rename_exchange(struct inode *old_dir, /* force full log commit if subvolume involved. */ btrfs_set_log_full_commit(dest->fs_info, trans); } else { + btrfs_pin_log_trans(dest); + dest_log_pinned = true; ret = btrfs_insert_inode_ref(trans, root, old_dentry->d_name.name, old_dentry->d_name.len, @@ -9481,8 +9483,6 @@ static int btrfs_rename_exchange(struct inode *old_dir, btrfs_ino(old_dir), new_idx); if (ret) goto out_fail; - btrfs_pin_log_trans(dest); - dest_log_pinned = true; } /* Update inode version and ctime/mtime. */