From patchwork Sun Mar 16 20:37:26 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Filipe Manana X-Patchwork-Id: 3840291 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id DD1CDBF540 for ; Sun, 16 Mar 2014 20:37:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D2CC4201F5 for ; Sun, 16 Mar 2014 20:37:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CC20420170 for ; Sun, 16 Mar 2014 20:37:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755527AbaCPUhu (ORCPT ); Sun, 16 Mar 2014 16:37:50 -0400 Received: from mail-wg0-f51.google.com ([74.125.82.51]:56371 "EHLO mail-wg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754253AbaCPUht (ORCPT ); Sun, 16 Mar 2014 16:37:49 -0400 Received: by mail-wg0-f51.google.com with SMTP id k14so3822810wgh.34 for ; Sun, 16 Mar 2014 13:37:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=XjgkUfNBZmm6WzW270g7S32JiCCza2cKlwkDo5YZcFY=; b=Hfc0WTCwPYMzvpifKZa7FMChXodElO6P23cinmAX0PyG/VdkTijFZW+Xl4ecCKdjWm dRLFPMIz20xhRNBOwL3fLgyJtfbBMxUk3qsee12oM29HBTede/DTRPQ7W7gtXR4lRl4R DDLPo041jh+CnJraNs3QfbadlPTrI2Y74KgT7onPnTTiRvsQDM6Y3jPBvvs+9O9W+in/ A9zvcRNZqKJO8UdTTCLdAUDQZbdmgWQ/h4lnfo7fF/GaFuxPqpEj0sbcUXqzgjhTDemL w9ntKzOBqEVHdq5elEi2iGnkmrgjcTO9SxcPKfnwIM2KdgwLlxt6QjdCldz7RWRhwqhu 7yKg== X-Received: by 10.194.174.42 with SMTP id bp10mr641263wjc.57.1395002268376; Sun, 16 Mar 2014 13:37:48 -0700 (PDT) Received: from debian-vm3.lan (bl10-140-160.dsl.telepac.pt. [85.243.140.160]) by mx.google.com with ESMTPSA id lz3sm18322137wic.1.2014.03.16.13.37.42 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 16 Mar 2014 13:37:47 -0700 (PDT) From: Filipe David Borba Manana To: linux-btrfs@vger.kernel.org Cc: Filipe David Borba Manana Subject: [PATCH v3] Btrfs: fix incremental send's decision to delay a dir move/rename Date: Sun, 16 Mar 2014 20:37:26 +0000 Message-Id: <1395002246-3840-1-git-send-email-fdmanana@gmail.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1394983430-20440-1-git-send-email-fdmanana@gmail.com> References: <1394983430-20440-1-git-send-email-fdmanana@gmail.com> Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham 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 It's possible to change the parent/child relationship between directories in such a way that if a child directory has a higher inode number than its parent, it doesn't necessarily means the child rename/move operation can be performed immediately. The parent migth have its own rename/move operation delayed, therefore in this case the child needs to have its rename/move operation delayed too, and be performed after its new parent's rename/move. Steps to reproduce the issue: $ umount /mnt $ mkfs.btrfs -f /dev/sdd $ mount /dev/sdd /mnt $ mkdir /mnt/A $ mkdir /mnt/B $ mkdir /mnt/C $ mv /mnt/C /mnt/A $ mv /mnt/B /mnt/A/C $ mkdir /mnt/A/C/D $ btrfs subvolume snapshot -r /mnt /mnt/snap1 $ btrfs send /mnt/snap1 -f /tmp/base.send $ mv /mnt/A/C/D /mnt/A/D2 $ mv /mnt/A/C/B /mnt/A/D2/B2 $ mv /mnt/A/C /mnt/A/D2/B2/C2 $ btrfs subvolume snapshot -r /mnt /mnt/snap2 $ btrfs send -p /mnt/snap1 /mnt/snap2 -f /tmp/incremental.send The incremental send caused the kernel code to enter an infinite loop when building the path string for directory C after its references are processed. The necessary conditions here are that C has an inode number higher than both A and B, and B as an higher inode number higher than A, and D has the highest inode number, that is: inode_number(A) < inode_number(B) < inode_number(C) < inode_number(D) The same issue could happen if after the first snapshot there's any number of intermediary parent directories between A2 and B2, and between B2 and C2. A test case for xfstests follows, covering this simple case and more advanced ones, with files and hard links created inside the directories. Signed-off-by: Filipe David Borba Manana --- V2: Right version of the patch. Previously sent came from the wrong vm. V3: The condition needed to check already existed, so just moved it to the top, instead of adding it again. fs/btrfs/send.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 6463691..d869079 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -3184,12 +3184,12 @@ static int wait_for_parent_move(struct send_ctx *sctx, struct fs_path *path_after = NULL; int len1, len2; - if (parent_ref->dir <= sctx->cur_ino) - return 0; - if (is_waiting_for_move(sctx, ino)) return 1; + if (parent_ref->dir <= sctx->cur_ino) + return 0; + ret = get_inode_info(sctx->parent_root, ino, NULL, &old_gen, NULL, NULL, NULL, NULL); if (ret == -ENOENT)