Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp2139108pxb; Fri, 5 Feb 2021 09:49:54 -0800 (PST) X-Google-Smtp-Source: ABdhPJwMQrNgTGnSVvxyn+xAvYHKz8PvSFnDJwct5ZUNv4mVHeXxdEEXPGDvzBUX1Q8LeEgwOtyM X-Received: by 2002:a17:907:76c5:: with SMTP id kf5mr5102791ejc.534.1612547393828; Fri, 05 Feb 2021 09:49:53 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1612547393; cv=none; d=google.com; s=arc-20160816; b=vb3cAv9RM7HtYlvNHNRTaDVcZJWmrR6KkkOoGikfAEvfBlVdMFcxEk5546IqQ9OvWG 6jDR9OycIaaK2YpZeo4VBiW7Zc/OH5jAGZci8pXOrt4I+nBGOqrpjdGgAHFpVgKDQo1a hH9nNYaihoCl2afjf2vq/Yg81aIaKhgSlQTNTPfsFLTczHiYQUi+RAPJbkU2ta+sJA+j FN9TjhQVlUeZ1bbsoGqM48iCjxUZgyc7jWRvSsrjtOWpvxtxF9AQ61Gcc/tDppjGKR42 d+16CP7KeHk+lohw8X9xQiBoNPKQlZ9wlzQaNdCvaX9+AQc1kwDtRYkYzHbmvNs8JVdF lDog== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=TZqjm/Q3k8zp4dBSXQu2gaYPLRQJ6e5bU5oA/jE7urQ=; b=gIFWpJFJvdD1Erw54g+1tHgUNoSp7zmk64oOTsDZSsADVaHGde4/q75QOlJwD5YHDS 2nrdK4PbB/aLX+Z29iz1Yn0nfF7XaEcN1Kt8baSsFAmJ9STTdznjBkcyfMxzmPLszlSx vF2/spryEAHgT9u3w3janakqxxaV2l3NyWqIdrtE5yl270vTQiBl6tw8eVnQp1ARVH5v AVatiie625YUmAdHobM/g0weIuEJouC3sJFv1MzH/JlHH61Xyh/IKVHhxbZ+57WBw9qx JUBfSPG7kAUeiAF/W1NHVnE84kRVlbyOD33LK0NrMZEp3VeRRMiZ80BlgPX3DEpkna5T cMxg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=H4WewWy2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id h24si6111839ejt.167.2021.02.05.09.49.27; Fri, 05 Feb 2021 09:49:53 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=H4WewWy2; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233436AbhBEQEs (ORCPT + 99 others); Fri, 5 Feb 2021 11:04:48 -0500 Received: from mail.kernel.org ([198.145.29.99]:53906 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233364AbhBEP7J (ORCPT ); Fri, 5 Feb 2021 10:59:09 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 3AD4C65061; Fri, 5 Feb 2021 14:12:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1612534357; bh=7Whvksf2CWksxPNtmZQr4TIH59nH+paPjkwL+Dox+B8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=H4WewWy22HSUsv1hDy9IcjeMUUll7xiVj+XzWSeVDMw9SvJeFgj0TLFlWzc7kFutE bD3tE0u3uVscCn39rFEQIxXKcNz4QrbsC06+mNWQig/4ISydWuQ72GuAga1tfMsRRo BmdYxkjCIbj3UQtbMe2BWIt4SIlTtb6eZJlLGU+0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Josef Bacik , Johannes Thumshirn , ethanwu , David Sterba Subject: [PATCH 5.4 09/32] btrfs: backref, only collect file extent items matching backref offset Date: Fri, 5 Feb 2021 15:07:24 +0100 Message-Id: <20210205140652.734340643@linuxfoundation.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210205140652.348864025@linuxfoundation.org> References: <20210205140652.348864025@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: ethanwu commit 7ac8b88ee668a5b4743ebf3e9888fabac85c334a upstream. When resolving one backref of type EXTENT_DATA_REF, we collect all references that simply reference the EXTENT_ITEM even though their (file_pos - file_extent_item::offset) are not the same as the btrfs_extent_data_ref::offset we are searching for. This patch adds additional check so that we only collect references whose (file_pos - file_extent_item::offset) == btrfs_extent_data_ref::offset. Reviewed-by: Josef Bacik Reviewed-by: Johannes Thumshirn Signed-off-by: ethanwu Signed-off-by: David Sterba Signed-off-by: Greg Kroah-Hartman --- fs/btrfs/backref.c | 63 +++++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -347,33 +347,10 @@ static int add_prelim_ref(const struct b return -ENOMEM; ref->root_id = root_id; - if (key) { + if (key) ref->key_for_search = *key; - /* - * We can often find data backrefs with an offset that is too - * large (>= LLONG_MAX, maximum allowed file offset) due to - * underflows when subtracting a file's offset with the data - * offset of its corresponding extent data item. This can - * happen for example in the clone ioctl. - * So if we detect such case we set the search key's offset to - * zero to make sure we will find the matching file extent item - * at add_all_parents(), otherwise we will miss it because the - * offset taken form the backref is much larger then the offset - * of the file extent item. This can make us scan a very large - * number of file extent items, but at least it will not make - * us miss any. - * This is an ugly workaround for a behaviour that should have - * never existed, but it does and a fix for the clone ioctl - * would touch a lot of places, cause backwards incompatibility - * and would not fix the problem for extents cloned with older - * kernels. - */ - if (ref->key_for_search.type == BTRFS_EXTENT_DATA_KEY && - ref->key_for_search.offset >= LLONG_MAX) - ref->key_for_search.offset = 0; - } else { + else memset(&ref->key_for_search, 0, sizeof(ref->key_for_search)); - } ref->inode_list = NULL; ref->level = level; @@ -424,6 +401,7 @@ static int add_all_parents(struct btrfs_ u64 disk_byte; u64 wanted_disk_byte = ref->wanted_disk_byte; u64 count = 0; + u64 data_offset; if (level != 0) { eb = path->nodes[level]; @@ -457,11 +435,15 @@ static int add_all_parents(struct btrfs_ fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item); disk_byte = btrfs_file_extent_disk_bytenr(eb, fi); + data_offset = btrfs_file_extent_offset(eb, fi); if (disk_byte == wanted_disk_byte) { eie = NULL; old = NULL; - count++; + if (ref->key_for_search.offset == key.offset - data_offset) + count++; + else + goto next; if (extent_item_pos) { ret = check_extent_in_eb(&key, eb, fi, *extent_item_pos, @@ -513,6 +495,7 @@ static int resolve_indirect_ref(struct b int root_level; int level = ref->level; int index; + struct btrfs_key search_key = ref->key_for_search; root_key.objectid = ref->root_id; root_key.type = BTRFS_ROOT_ITEM_KEY; @@ -545,13 +528,33 @@ static int resolve_indirect_ref(struct b goto out; } + /* + * We can often find data backrefs with an offset that is too large + * (>= LLONG_MAX, maximum allowed file offset) due to underflows when + * subtracting a file's offset with the data offset of its + * corresponding extent data item. This can happen for example in the + * clone ioctl. + * + * So if we detect such case we set the search key's offset to zero to + * make sure we will find the matching file extent item at + * add_all_parents(), otherwise we will miss it because the offset + * taken form the backref is much larger then the offset of the file + * extent item. This can make us scan a very large number of file + * extent items, but at least it will not make us miss any. + * + * This is an ugly workaround for a behaviour that should have never + * existed, but it does and a fix for the clone ioctl would touch a lot + * of places, cause backwards incompatibility and would not fix the + * problem for extents cloned with older kernels. + */ + if (search_key.type == BTRFS_EXTENT_DATA_KEY && + search_key.offset >= LLONG_MAX) + search_key.offset = 0; path->lowest_level = level; if (time_seq == SEQ_LAST) - ret = btrfs_search_slot(NULL, root, &ref->key_for_search, path, - 0, 0); + ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0); else - ret = btrfs_search_old_slot(root, &ref->key_for_search, path, - time_seq); + ret = btrfs_search_old_slot(root, &search_key, path, time_seq); /* root node has been locked, we can release @subvol_srcu safely here */ srcu_read_unlock(&fs_info->subvol_srcu, index);