Received: by 10.223.176.46 with SMTP id f43csp277499wra; Tue, 23 Jan 2018 20:53:54 -0800 (PST) X-Google-Smtp-Source: AH8x227meptrsxUbY3GXlqMdkVlw2w8YI8uOVE6far9o3fl7nW5EVCAAXmMs5PacSneecwUAvkHP X-Received: by 10.99.146.3 with SMTP id o3mr10158804pgd.309.1516769634120; Tue, 23 Jan 2018 20:53:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516769634; cv=none; d=google.com; s=arc-20160816; b=AsArsGDw77BA7rvjRoMubma0k0ZDrrUJ7sZibldVve8FjF6xHzMLze21IsYgbnun0h qwAstCgyOmn60Pc7cKINYxHV4w3aXq4luVxbj85OqH1oE8zDy+jCLhwe9wROWB4Z2LVO xy+iu5OqccK0n3aRjDPGtT5JiXlm6DiFqbo6pwEnVkBynObYxvpjbOBT01ocfoj713iV RYx9lOJKqepfxmezacDc2NEl+J3rgvvb98BDeG9YQ/ORlO/wSZ5UyE5QhQWomT+v6m7W cd0F8Jra8zF/U5LtiydV446QTO5cKp2DGY/UYbIvHr5w/QkvLPgrSpH7QOU1xDGdJCPU q0wQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:content-transfer-encoding :spamdiagnosticmetadata:spamdiagnosticoutput:content-language :accept-language:in-reply-to:references:message-id:date:thread-index :thread-topic:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=hdWHlZknW66b/ZNOw7/aycy6mG8llWtEjH0FPRRD4EA=; b=hoYGhpWYAD2YtYMUv5GTKfqMO74cF5HRwjh25jmg9xJp1wcgrtSxMcbI7pBo/mLqgC n/Y9SP4OYOFn8EbOfMgzNOdxOQUaug7zc0lG+QiBIjKdurM/x0XJUyh3ql7br3U7ee5+ A2U92EIdWqheyxr0yz4hKcq7ifTZjAMIaGx/5jdFs63ydDYj5rdSkvlg5Pp9aAoedwBJ CIyJJnLI6pS65soGBCNxy4HaoNchgQbwF7Rsh7pCQgv7OvgemsRMq2NRi7Y1qWQHYlJR dnUDQvehQlcUOXIqTW8d1yM1o46rTg9u2B+I94eEFOred80XVwKzqtBgR1onisUC98E4 0Y9w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@microsoft.com header.s=selector1 header.b=JgL2yqt7; 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; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=microsoft.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 2-v6si5520557plc.784.2018.01.23.20.53.40; Tue, 23 Jan 2018 20:53:54 -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=@microsoft.com header.s=selector1 header.b=JgL2yqt7; 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; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=microsoft.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932850AbeAXExQ (ORCPT + 99 others); Tue, 23 Jan 2018 23:53:16 -0500 Received: from mail-by2nam03on0132.outbound.protection.outlook.com ([104.47.42.132]:45413 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932431AbeAXEP6 (ORCPT ); Tue, 23 Jan 2018 23:15:58 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=hdWHlZknW66b/ZNOw7/aycy6mG8llWtEjH0FPRRD4EA=; b=JgL2yqt705lZCPqslkjq/N33WSd2rdnoGwLwD8QbOfle0r6049HWhGkwDArUJEMlYYREPy1nyftfMCLVnmO3x7KQllm1P8nk/QJzydSN2n8gRJMWNS1Bc5/OSTRsZRcJVYLYE+U3nXkS9Ri02uzDaXHx6zBh4ybgG4T8ZzsKPgs= Received: from DM5PR2101MB1032.namprd21.prod.outlook.com (52.132.128.13) by DM5PR2101MB1078.namprd21.prod.outlook.com (52.132.130.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.464.1; Wed, 24 Jan 2018 04:15:56 +0000 Received: from DM5PR2101MB1032.namprd21.prod.outlook.com ([fe80::6485:b98:d15e:9da7]) by DM5PR2101MB1032.namprd21.prod.outlook.com ([fe80::6485:b98:d15e:9da7%2]) with mapi id 15.20.0464.000; Wed, 24 Jan 2018 04:15:56 +0000 From: Sasha Levin To: "linux-kernel@vger.kernel.org" , "stable@vger.kernel.org" CC: Filipe Manana , David Sterba , "Sasha Levin" Subject: [PATCH AUTOSEL for 4.14 069/100] Btrfs: incremental send, fix wrong unlink path after renaming file Thread-Topic: [PATCH AUTOSEL for 4.14 069/100] Btrfs: incremental send, fix wrong unlink path after renaming file Thread-Index: AQHTlMnmaAVGmD2oz06lnP/izJybMQ== Date: Wed, 24 Jan 2018 04:15:00 +0000 Message-ID: <20180124041414.32065-69-alexander.levin@microsoft.com> References: <20180124041414.32065-1-alexander.levin@microsoft.com> In-Reply-To: <20180124041414.32065-1-alexander.levin@microsoft.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [52.168.54.252] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1;DM5PR2101MB1078;6:jsdMoXzYGX15+ofe+rnQMincw/HK2KRffrRq9hbE/fJovcMB/JdH1RNktnSFHPfEMpr/eMVHIXvkyQvje2gipUOsTBYgdfEHrZwHKqo6qo83whi5+6cqiv+uVVFLF2j6bQ0YUkFwuVVkm2Z9gcaYO8dzs5frbmyJfDJ85o6Y6Snwf11ZA5Jkc/hLNg9EpRdmenwcL0KM+wXN8UTqc0/H4Cheyl+fv2LVezJFD0VyvWCs4ezgnXQtbdKYYNVtzcJPMVV1g4WVGd3nz/gd4p527Y/W6G40qzVa6qsLE8uGDb6rnGxJAPH/nukoUIq41vqdP31HNUr4XkryQ9VEVPgzMTDWl3pdOLRgNT0cddruOIvPceFnGCva/BKvmYAn99c6;5:7rw7dCvJn5m0VNHcS5koosX4jdESKmC08biuRK5zyLHZhlnO29yQKr2gAFdnfAhmELZLEtrb2X1rqFlmtab1wJqA3ZxpEy9OIAjeW2sWpkuioEYKDaVKSAge7nsmWWfpSS5ZGk9FkGAYZ7GwkKzbajW7jwnU3Cut02BCXnxoCD8=;24:ZXG3IrkvR1Bxhsu/1EnFt4WvOw/C+ETTSGMRnxVC1kQAfMgi28UGGMNysAWmoJM1nyca8EZ2FHZ5Im+IRNr/VLS04yqru3B5CGcCwmE5LYc=;7:jhqM8FSxRTiSy74gaHRbX/wzKvqfiZPb11qoi4+hyYsjWkNP2VCUERpjabhnoEw/QePCqMwGtK+tu2sJFases0pha6sThYXG+UXrLQUaR75/d9DwqgzqDqOG0Lpb72r1TyWBEKw3frn4GUqawSCpKh4tqAwvr2fy/FE+5xapPhC7FuGz1eD+WyBNeGsWVErDP6j1IKuhoR/i0MDbX9dZ1Ks7H6zP+w0CnCbHWHlq7mJwZldYd8l2PNpcf3MhIoEA x-ms-office365-filtering-correlation-id: 2ee76ad1-3a8f-467f-6e9d-08d562e12a91 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:(7020095)(4652020)(5600026)(4604075)(3008032)(4534165)(4627221)(201703031133081)(201702281549075)(48565401081)(2017052603307)(7193020);SRVR:DM5PR2101MB1078; x-ms-traffictypediagnostic: DM5PR2101MB1078: x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(28532068793085)(89211679590171); x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(61425038)(6040501)(2401047)(5005006)(8121501046)(93006095)(93001095)(3002001)(10201501046)(3231046)(2400081)(944501161)(6055026)(61426038)(61427038)(6041288)(20161123558120)(20161123562045)(20161123564045)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011);SRVR:DM5PR2101MB1078;BCL:0;PCL:0;RULEID:;SRVR:DM5PR2101MB1078; x-forefront-prvs: 056297E276 x-forefront-antispam-report: SFV:NSPM;SFS:(10019020)(376002)(346002)(39860400002)(366004)(396003)(39380400002)(199004)(189003)(86612001)(22452003)(6436002)(106356001)(107886003)(102836004)(105586002)(305945005)(5250100002)(2501003)(14454004)(3280700002)(4326008)(7736002)(97736004)(59450400001)(6512007)(36756003)(8936002)(2950100002)(3846002)(6116002)(6506007)(86362001)(54906003)(76176011)(110136005)(2906002)(6666003)(53936002)(66066001)(72206003)(6346003)(5660300001)(8676002)(478600001)(10290500003)(68736007)(81156014)(10090500001)(1076002)(3660700001)(25786009)(316002)(2900100001)(99286004)(26005)(6486002)(81166006)(22906009)(217873001);DIR:OUT;SFP:1102;SCL:1;SRVR:DM5PR2101MB1078;H:DM5PR2101MB1032.namprd21.prod.outlook.com;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; received-spf: None (protection.outlook.com: microsoft.com does not designate permitted sender hosts) authentication-results: spf=none (sender IP is ) smtp.mailfrom=Alexander.Levin@microsoft.com; x-microsoft-antispam-message-info: G5zVyfmkpsoXzI9FL9ZAeQPhqqCpvKT/M0G9xG94z0ErLmyRQ2pZGNULldDWhmJLoZKBODAC5RbghPzzNT7Bpg== spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: microsoft.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2ee76ad1-3a8f-467f-6e9d-08d562e12a91 X-MS-Exchange-CrossTenant-originalarrivaltime: 24 Jan 2018 04:15:00.3203 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 72f988bf-86f1-41af-91ab-2d7cd011db47 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR2101MB1078 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Filipe Manana [ Upstream commit ea37d5998b50a72b9045ba60a132eeb20e1c4230 ] Under some circumstances, an incremental send operation can issue wrong paths for unlink commands related to files that have multiple hard links and some (or all) of those links were renamed between the parent and send snapshots. Consider the following example: Parent snapshot . (ino 256) |---- a/ (ino 257) | |---- b/ (ino 259) | | |---- c/ (ino 260) | | |---- f2 (ino 261) | | | |---- f2l1 (ino 261) | |---- d/ (ino 262) |---- f1l1_2 (ino 258) |---- f2l2 (ino 261) |---- f1_2 (ino 258) Send snapshot . (ino 256) |---- a/ (ino 257) | |---- f2l1/ (ino 263) | |---- b2/ (ino 259) | |---- c/ (ino 260) | | |---- d3 (ino 262) | | |---- f1l1_2 (ino 258) | | |---- f2l2_2 (ino 261) | | |---- f1_2 (ino 258) | | | |---- f2 (ino 261) | |---- f1l2 (ino 258) | |---- d (ino 261) When computing the incremental send stream the following steps happen: 1) When processing inode 261, a rename operation is issued that renames inode 262, which currently as a path of "d", to an orphan name of "o262-7-0". This is done because in the send snapshot, inode 261 has of its hard links with a path of "d" as well. 2) Two link operations are issued that create the new hard links for inode 261, whose names are "d" and "f2l2_2", at paths "/" and "o262-7-0/" respectively. 3) Still while processing inode 261, unlink operations are issued to remove the old hard links of inode 261, with names "f2l1" and "f2l2", at paths "a/" and "d/". However path "d/" does not correspond anymore to the directory inode 262 but corresponds instead to a hard link of inode 261 (link command issued in the previous step). This makes the receiver fail with a ENOTDIR error when attempting the unlink operation. The problem happens because before sending the unlink operation, we failed to detect that inode 262 was one of ancestors for inode 261 in the parent snapshot, and therefore we didn't recompute the path for inode 262 before issuing the unlink operation for the link named "f2l2" of inode 262. The detection failed because the function "is_ancestor()" only follows the first hard link it finds for an inode instead of all of its hard links (as it was originally created for being used with directories only, for which only one hard link exists). So fix this by making "is_ancestor()" follow all hard links of the input inode. A test case for fstests follows soon. Signed-off-by: Filipe Manana Signed-off-by: David Sterba Signed-off-by: Sasha Levin --- fs/btrfs/send.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++----= ---- 1 file changed, 106 insertions(+), 18 deletions(-) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 8fd195cfe81b..2c35717a3470 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -3527,7 +3527,40 @@ out: } =20 /* - * Check if ino ino1 is an ancestor of inode ino2 in the given root. + * Check if inode ino2, or any of its ancestors, is inode ino1. + * Return 1 if true, 0 if false and < 0 on error. + */ +static int check_ino_in_path(struct btrfs_root *root, + const u64 ino1, + const u64 ino1_gen, + const u64 ino2, + const u64 ino2_gen, + struct fs_path *fs_path) +{ + u64 ino =3D ino2; + + if (ino1 =3D=3D ino2) + return ino1_gen =3D=3D ino2_gen; + + while (ino > BTRFS_FIRST_FREE_OBJECTID) { + u64 parent; + u64 parent_gen; + int ret; + + fs_path_reset(fs_path); + ret =3D get_first_ref(root, ino, &parent, &parent_gen, fs_path); + if (ret < 0) + return ret; + if (parent =3D=3D ino1) + return parent_gen =3D=3D ino1_gen; + ino =3D parent; + } + return 0; +} + +/* + * Check if ino ino1 is an ancestor of inode ino2 in the given root for an= y + * possible path (in case ino2 is not a directory and has multiple hard li= nks). * Return 1 if true, 0 if false and < 0 on error. */ static int is_ancestor(struct btrfs_root *root, @@ -3536,36 +3569,91 @@ static int is_ancestor(struct btrfs_root *root, const u64 ino2, struct fs_path *fs_path) { - u64 ino =3D ino2; - bool free_path =3D false; + bool free_fs_path =3D false; int ret =3D 0; + struct btrfs_path *path =3D NULL; + struct btrfs_key key; =20 if (!fs_path) { fs_path =3D fs_path_alloc(); if (!fs_path) return -ENOMEM; - free_path =3D true; + free_fs_path =3D true; } =20 - while (ino > BTRFS_FIRST_FREE_OBJECTID) { - u64 parent; - u64 parent_gen; + path =3D alloc_path_for_send(); + if (!path) { + ret =3D -ENOMEM; + goto out; + } =20 - fs_path_reset(fs_path); - ret =3D get_first_ref(root, ino, &parent, &parent_gen, fs_path); - if (ret < 0) { - if (ret =3D=3D -ENOENT && ino =3D=3D ino2) - ret =3D 0; - goto out; + key.objectid =3D ino2; + key.type =3D BTRFS_INODE_REF_KEY; + key.offset =3D 0; + + ret =3D btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) + goto out; + + while (true) { + struct extent_buffer *leaf =3D path->nodes[0]; + int slot =3D path->slots[0]; + u32 cur_offset =3D 0; + u32 item_size; + + if (slot >=3D btrfs_header_nritems(leaf)) { + ret =3D btrfs_next_leaf(root, path); + if (ret < 0) + goto out; + if (ret > 0) + break; + continue; } - if (parent =3D=3D ino1) { - ret =3D parent_gen =3D=3D ino1_gen ? 1 : 0; - goto out; + + btrfs_item_key_to_cpu(leaf, &key, slot); + if (key.objectid !=3D ino2) + break; + if (key.type !=3D BTRFS_INODE_REF_KEY && + key.type !=3D BTRFS_INODE_EXTREF_KEY) + break; + + item_size =3D btrfs_item_size_nr(leaf, slot); + while (cur_offset < item_size) { + u64 parent; + u64 parent_gen; + + if (key.type =3D=3D BTRFS_INODE_EXTREF_KEY) { + unsigned long ptr; + struct btrfs_inode_extref *extref; + + ptr =3D btrfs_item_ptr_offset(leaf, slot); + extref =3D (struct btrfs_inode_extref *) + (ptr + cur_offset); + parent =3D btrfs_inode_extref_parent(leaf, + extref); + cur_offset +=3D sizeof(*extref); + cur_offset +=3D btrfs_inode_extref_name_len(leaf, + extref); + } else { + parent =3D key.offset; + cur_offset =3D item_size; + } + + ret =3D get_inode_info(root, parent, NULL, &parent_gen, + NULL, NULL, NULL, NULL); + if (ret < 0) + goto out; + ret =3D check_ino_in_path(root, ino1, ino1_gen, + parent, parent_gen, fs_path); + if (ret) + goto out; } - ino =3D parent; + path->slots[0]++; } + ret =3D 0; out: - if (free_path) + btrfs_free_path(path); + if (free_fs_path) fs_path_free(fs_path); return ret; } --=20 2.11.0