From patchwork Tue Jan 28 01:38:06 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Filipe Manana X-Patchwork-Id: 3544831 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.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 56FEA9F2E9 for ; Tue, 28 Jan 2014 01:39:04 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 681612011E for ; Tue, 28 Jan 2014 01:39:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7630F200F0 for ; Tue, 28 Jan 2014 01:39:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753679AbaA1Bi7 (ORCPT ); Mon, 27 Jan 2014 20:38:59 -0500 Received: from mail-wg0-f47.google.com ([74.125.82.47]:35329 "EHLO mail-wg0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751121AbaA1Bi6 (ORCPT ); Mon, 27 Jan 2014 20:38:58 -0500 Received: by mail-wg0-f47.google.com with SMTP id m15so6539285wgh.26 for ; Mon, 27 Jan 2014 17:38:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=8kOCc4nuGCfufvA61EBHrochaK8VFC8gHFmXjfovdZw=; b=YrBC/+6ndw0Wknc/AUa+d+TYOBIpTTJmOwAMId13ozLLIBMHX9BS9ZF62cxwLXp1Lq ZJHNxhhFApg8Xgba5Fv+spUFNKtorgAJJEspMaPtV6MCL3/yoZP6Tw6pxx6T1+4JGXTR Evfk4lv1jeDgDQtY69jzbtSvJDYIGNOR02SV75X2JXpctvdVfZVxKPkap1/oGURAO1cR 4Fc/TRACrM56qYVWTgYOqcLWSlfuXlUZsTyGi/o2ZbI+LzseZ81+OtAMVrO2YwqjgMr7 +KCBdAx0KnqIN+Oc3tiCQkYarPQLxFtgDTFRwOZJ3jN7icjxppl3lBQzD1ZQ61r2FIsu odgw== X-Received: by 10.194.110.135 with SMTP id ia7mr22223692wjb.5.1390873137190; Mon, 27 Jan 2014 17:38:57 -0800 (PST) Received: from storm-desktop.lan (bl9-171-228.dsl.telepac.pt. [85.242.171.228]) by mx.google.com with ESMTPSA id bm8sm15565960wjc.12.2014.01.27.17.38.54 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 27 Jan 2014 17:38:56 -0800 (PST) From: Filipe David Borba Manana To: linux-btrfs@vger.kernel.org Cc: Filipe David Borba Manana Subject: [PATCH] Btrfs: fix send file hole detection leading to data corruption Date: Tue, 28 Jan 2014 01:38:06 +0000 Message-Id: <1390873086-8591-1-git-send-email-fdmanana@gmail.com> X-Mailer: git-send-email 1.7.9.5 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-7.3 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, 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 There was a case where file hole detection was incorrect and it would cause an incremental send to override a section of a file with zeroes. This happened in the case where between the last leaf we processed which contained a file extent item for our current inode and the leaf we're currently are at (and has a file extent item for our current inode) there are only leafs containing exclusively file extent items for our current inode, and none of them was updated since the previous send operation. The file hole detection code would incorrectly consider the file range covered by these leafs as a hole. A test case for xfstests follows soon. Signed-off-by: Filipe David Borba Manana --- fs/btrfs/send.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 306f9a9..16a0c84 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -4485,6 +4485,21 @@ static int maybe_send_hole(struct send_ctx *sctx, struct btrfs_path *path, extent_end = key->offset + btrfs_file_extent_num_bytes(path->nodes[0], fi); } + + if (path->slots[0] == 0 && + sctx->cur_inode_last_extent < key->offset) { + /* + * We might have skipped entire leafs that contained only + * file extent items for our current inode. These leafs have + * a generation number smaller (older) than the one in the + * current leaf and the leaf our last extent came from, and + * are located between these 2 leafs. + */ + ret = get_last_extent(sctx, key->offset - 1); + if (ret) + return ret; + } + if (sctx->cur_inode_last_extent < key->offset) ret = send_hole(sctx, key->offset); sctx->cur_inode_last_extent = extent_end;