Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp1986934imu; Fri, 14 Dec 2018 04:07:12 -0800 (PST) X-Google-Smtp-Source: AFSGD/VRmoosYT1UJlXUgpexFJp0oHiCKqJvvRYC/EkCkNQAVjiT5bHxzUgqZye/qgtdB++RNtZu X-Received: by 2002:a63:5346:: with SMTP id t6mr2554475pgl.40.1544789232439; Fri, 14 Dec 2018 04:07:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1544789232; cv=none; d=google.com; s=arc-20160816; b=XcuMqaeT/DNxsC8VHD4EkDNcz3gy23pCmOd2LBXLOppyxjX3O+W65Shme3wuhya6tA NDFwku02rUaRqG19a6+BMGJ/rfS9Z60seLhWJgsbC7fIdwOSBCRTVKHGX0DVCKie6RfN 5UZqaUWFd4zof6/FXaEa8lyMtRvQasVwrfSKBAnEFhZk4NpVxXYEUQKcfZApLA7+gU9S rNJ7OOH3s3sUMN7flPFrFsPEUPZc4mEg3r/iSNZA9kqWB5C52xF9xqXy+GF7OKbx3liq i+xemTpnNEKKVhuKvVYNkhRtsMnqrHwRDi7Zv1kPKAPkrmE3nooMzioR2DWRQx3caJMa FjmQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=sFUg+Oo5/Zc1+r0IN2fCP9hNeY1pPcQEl2URRaV50yQ=; b=wD4pDV9hah1SKFiieL7Ah7uUly7vGHORHo6wFUH6g83esX3NShh7rnmW6IsSXa5CTU kiZys7J/tgz0g2nvZzu/+IvFpaLRb+T1b7ldRdcmhLVGIaFEarN207wMg9q1sjiJp8ie E+m1x/bY1g+kdmnzpUN2X/V3fmdQY6HuF+F4aBcrBeRSb14oPST8Zq7uXAj1ztB6fsnq o5QafC6JbgNLOll5UcBgGL6gcm93KI5U1MO5AJHo07X7tw40NuHSjhze+R/KJDEY0+KC YTqjqBlvLkUXjTp1n217g8d7I7nnhdZ0Rkg/PM667ci0I5OOUQ62wvpA5i90PfkSpAy8 7ozA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=ftXzBGFS; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e188si4128940pfa.16.2018.12.14.04.06.57; Fri, 14 Dec 2018 04:07:12 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=ftXzBGFS; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730607AbeLNME7 (ORCPT + 99 others); Fri, 14 Dec 2018 07:04:59 -0500 Received: from mail.kernel.org ([198.145.29.99]:49694 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730158AbeLNME5 (ORCPT ); Fri, 14 Dec 2018 07:04:57 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id D1E0921479; Fri, 14 Dec 2018 12:04:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1544789096; bh=TsJtzxdF4wEBNtBIdJfxWIupsotyFWexn3/I/+niUvc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ftXzBGFSWyENSeKctd/giesAORFeCnyoLIQ0qma8Mm+4l2E9S6hussDKoE7vNnIb1 0HHKF/9CXLTC+8LHCBOujyb5rT1dySK5nPyf+scftolEY1vYCrz84+AdUmXMEoBt/7 wCp64eRk8pguCyx4mxK0oA3bw4H0qpi6o0o60h/U= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Robbie Ko , Filipe Manana , David Sterba , Sasha Levin Subject: [PATCH 4.19 070/142] Btrfs: send, fix infinite loop due to directory rename dependencies Date: Fri, 14 Dec 2018 12:59:15 +0100 Message-Id: <20181214115749.857248862@linuxfoundation.org> X-Mailer: git-send-email 2.20.0 In-Reply-To: <20181214115747.053633987@linuxfoundation.org> References: <20181214115747.053633987@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.19-stable review patch. If anyone has any objections, please let me know. ------------------ [ Upstream commit a4390aee72713d9e73f1132bcdeb17d72fbbf974 ] When doing an incremental send, due to the need of delaying directory move (rename) operations we can end up in infinite loop at apply_children_dir_moves(). An example scenario that triggers this problem is described below, where directory names correspond to the numbers of their respective inodes. Parent snapshot: . |--- 261/ |--- 271/ |--- 266/ |--- 259/ |--- 260/ | |--- 267 | |--- 264/ | |--- 258/ | |--- 257/ | |--- 265/ |--- 268/ |--- 269/ | |--- 262/ | |--- 270/ |--- 272/ | |--- 263/ | |--- 275/ | |--- 274/ |--- 273/ Send snapshot: . |-- 275/ |-- 274/ |-- 273/ |-- 262/ |-- 269/ |-- 258/ |-- 271/ |-- 268/ |-- 267/ |-- 270/ |-- 259/ | |-- 265/ | |-- 272/ |-- 257/ |-- 260/ |-- 264/ |-- 263/ |-- 261/ |-- 266/ When processing inode 257 we delay its move (rename) operation because its new parent in the send snapshot, inode 272, was not yet processed. Then when processing inode 272, we delay the move operation for that inode because inode 274 is its ancestor in the send snapshot. Finally we delay the move operation for inode 274 when processing it because inode 275 is its new parent in the send snapshot and was not yet moved. When finishing processing inode 275, we start to do the move operations that were previously delayed (at apply_children_dir_moves()), resulting in the following iterations: 1) We issue the move operation for inode 274; 2) Because inode 262 depended on the move operation of inode 274 (it was delayed because 274 is its ancestor in the send snapshot), we issue the move operation for inode 262; 3) We issue the move operation for inode 272, because it was delayed by inode 274 too (ancestor of 272 in the send snapshot); 4) We issue the move operation for inode 269 (it was delayed by 262); 5) We issue the move operation for inode 257 (it was delayed by 272); 6) We issue the move operation for inode 260 (it was delayed by 272); 7) We issue the move operation for inode 258 (it was delayed by 269); 8) We issue the move operation for inode 264 (it was delayed by 257); 9) We issue the move operation for inode 271 (it was delayed by 258); 10) We issue the move operation for inode 263 (it was delayed by 264); 11) We issue the move operation for inode 268 (it was delayed by 271); 12) We verify if we can issue the move operation for inode 270 (it was delayed by 271). We detect a path loop in the current state, because inode 267 needs to be moved first before we can issue the move operation for inode 270. So we delay again the move operation for inode 270, this time we will attempt to do it after inode 267 is moved; 13) We issue the move operation for inode 261 (it was delayed by 263); 14) We verify if we can issue the move operation for inode 266 (it was delayed by 263). We detect a path loop in the current state, because inode 270 needs to be moved first before we can issue the move operation for inode 266. So we delay again the move operation for inode 266, this time we will attempt to do it after inode 270 is moved (its move operation was delayed in step 12); 15) We issue the move operation for inode 267 (it was delayed by 268); 16) We verify if we can issue the move operation for inode 266 (it was delayed by 270). We detect a path loop in the current state, because inode 270 needs to be moved first before we can issue the move operation for inode 266. So we delay again the move operation for inode 266, this time we will attempt to do it after inode 270 is moved (its move operation was delayed in step 12). So here we added again the same delayed move operation that we added in step 14; 17) We attempt again to see if we can issue the move operation for inode 266, and as in step 16, we realize we can not due to a path loop in the current state due to a dependency on inode 270. Again we delay inode's 266 rename to happen after inode's 270 move operation, adding the same dependency to the empty stack that we did in steps 14 and 16. The next iteration will pick the same move dependency on the stack (the only entry) and realize again there is still a path loop and then again the same dependency to the stack, over and over, resulting in an infinite loop. So fix this by preventing adding the same move dependency entries to the stack by removing each pending move record from the red black tree of pending moves. This way the next call to get_pending_dir_moves() will not return anything for the current parent inode. A test case for fstests, with this reproducer, follows soon. Signed-off-by: Robbie Ko Reviewed-by: Filipe Manana [Wrote changelog with example and more clear explanation] Signed-off-by: Filipe Manana Signed-off-by: David Sterba Signed-off-by: Sasha Levin --- fs/btrfs/send.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index ba8950bfd9c7..84cb6e5ef36c 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -3344,7 +3344,8 @@ static void free_pending_move(struct send_ctx *sctx, struct pending_dir_move *m) kfree(m); } -static void tail_append_pending_moves(struct pending_dir_move *moves, +static void tail_append_pending_moves(struct send_ctx *sctx, + struct pending_dir_move *moves, struct list_head *stack) { if (list_empty(&moves->list)) { @@ -3355,6 +3356,10 @@ static void tail_append_pending_moves(struct pending_dir_move *moves, list_add_tail(&moves->list, stack); list_splice_tail(&list, stack); } + if (!RB_EMPTY_NODE(&moves->node)) { + rb_erase(&moves->node, &sctx->pending_dir_moves); + RB_CLEAR_NODE(&moves->node); + } } static int apply_children_dir_moves(struct send_ctx *sctx) @@ -3369,7 +3374,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx) return 0; INIT_LIST_HEAD(&stack); - tail_append_pending_moves(pm, &stack); + tail_append_pending_moves(sctx, pm, &stack); while (!list_empty(&stack)) { pm = list_first_entry(&stack, struct pending_dir_move, list); @@ -3380,7 +3385,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx) goto out; pm = get_pending_dir_moves(sctx, parent_ino); if (pm) - tail_append_pending_moves(pm, &stack); + tail_append_pending_moves(sctx, pm, &stack); } return 0; -- 2.19.1