From patchwork Sat Apr 29 20:19:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227079 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C0803C77B7C for ; Sat, 29 Apr 2023 20:20:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229894AbjD2UUK (ORCPT ); Sat, 29 Apr 2023 16:20:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45064 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229900AbjD2UUI (ORCPT ); Sat, 29 Apr 2023 16:20:08 -0400 Received: from mail-yb1-xb33.google.com (mail-yb1-xb33.google.com [IPv6:2607:f8b0:4864:20::b33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 306D6E77 for ; Sat, 29 Apr 2023 13:20:07 -0700 (PDT) Received: by mail-yb1-xb33.google.com with SMTP id 3f1490d57ef6-b9da6374fa2so838203276.0 for ; Sat, 29 Apr 2023 13:20:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799606; x=1685391606; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ApFbhI/fHYAer2NanadPAfLYIZhU2eINRXfKeznF/So=; b=y9yiz/HMBfJo799nGYVhml+S5AcmSySsfHaYvv32B+GTpomvcjO+Nz1d2iYrD/OkB5 p3Ml9CXsf5gmGSfU/cx1Wf+KlEvH6ljyADDJ1/699d8MsKqmJEiHTzmW/Qx2LtmGv267 CMuYhZ7g0GQBDmK9nujr93HLYD3jRbDwlGsqBL5BzPkaRHl1UESH5ClhPNuJytB6a4bE OGyJ6+aTQITsz7DGxL6hJR7DmNMUXyFGnW1puwXrdTazeUET/EjZFTqyv9TPnMu2xeMJ JCauR8xSIGIDR6J8zBNS8vjXTKFvRWRv833F5w/JzuSvlzxjOh2UioF8Sk0QIILpeVah uTrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799606; x=1685391606; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ApFbhI/fHYAer2NanadPAfLYIZhU2eINRXfKeznF/So=; b=b/OK4bpG76l31HJpcYi7apjpJTiMT5QlSrRL2FLNPdIJx3bIvD4XhZMZC1XvdLpALu B68+q/+Ntd1+5CIabPVBQOuK3wZgN3PxshvtcYo7lXYvUwuctvkjlDSdYknJoq37uyGt pvnW3AjGkJAaKdQdjoFYXnpVXbo9GWwjSmHOrWp68xeXP5O6tNA2xCI8cVDgHcyyBy1h 6yJhtSAsi9g8Xh3aClC0VTRSTbsTrRFOVHt4deM6cGULLzPRW2XjcceJlqx15NxWIpHu uY9bLDlPSr2TlLHZETmo58wv6C326OjeqysezUZdSazU97uISd1jYgQeh179uaJakBDs UU0w== X-Gm-Message-State: AC+VfDxHHxO5F6xOLlQ9FGfuaHMeFRrtGOC1HfnkbZrqhgGTugBg6Lpq QU+FTzyrFSqltV+X2NZD8hRIk9x+h0OPPXjfr8jD9w== X-Google-Smtp-Source: ACHHUZ7QJU7wAVzHHQDcICU7h/SzTDnoL0jEgVPRgbPD+1S2rrqf+p1s08ymEykmY8skZpoYKMWbZw== X-Received: by 2002:a25:ab50:0:b0:b98:d45e:7bd4 with SMTP id u74-20020a25ab50000000b00b98d45e7bd4mr7783756ybi.13.1682799606122; Sat, 29 Apr 2023 13:20:06 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id z82-20020a256555000000b00b9a82c1b070sm1465676ybb.27.2023.04.29.13.20.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:05 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 01/26] btrfs-progs: stop using add_root_to_dirty_list in check Date: Sat, 29 Apr 2023 16:19:32 -0400 Message-Id: <767d1929fdc767e2603ffe16699acb838b533f96.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This is used to make sure the root is updated in the tree_root when we re-init the root, however this function is static in the kernel and doesn't need to be exported for any reason. Simply update the root item and then update it in the tree_root instead of adding it to the dirty list. Signed-off-by: Josef Bacik --- check/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/check/main.c b/check/main.c index 8714c213..d9c54deb 100644 --- a/check/main.c +++ b/check/main.c @@ -9163,8 +9163,12 @@ static int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans, free_extent_buffer(root->node); root->node = c; - add_root_to_dirty_list(root); - return 0; + + btrfs_set_root_bytenr(&root->root_item, c->start); + btrfs_set_root_generation(&root->root_item, trans->transid); + + return btrfs_update_root(trans, gfs_info->tree_root, &root->root_key, + &root->root_item); } static int reset_block_groups(void) From patchwork Sat Apr 29 20:19:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227081 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8F6E3C77B7F for ; Sat, 29 Apr 2023 20:20:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229900AbjD2UUL (ORCPT ); Sat, 29 Apr 2023 16:20:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45076 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229975AbjD2UUJ (ORCPT ); Sat, 29 Apr 2023 16:20:09 -0400 Received: from mail-yb1-xb2f.google.com (mail-yb1-xb2f.google.com [IPv6:2607:f8b0:4864:20::b2f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5DD64E7A for ; Sat, 29 Apr 2023 13:20:08 -0700 (PDT) Received: by mail-yb1-xb2f.google.com with SMTP id 3f1490d57ef6-b9a7e639656so1970255276.0 for ; Sat, 29 Apr 2023 13:20:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799607; x=1685391607; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=90TVpregLfTN8aIVCSeAhQNQKYWfvkrvrWKSEVNGrho=; b=HduhfxSzxERqtCrYmRRuV7+JuquIRPY0sI5rFjAd2yZHrCnUDERtpRuFgOeUQCmSVg yL0PyJLA2il1LcP+KRV0txLoRL4Sl/SE/0obO+R6txhimDtSOvIDCvMaX98rI7ZJRSzr Ju3d+gxDTooS5JE4YbVGJbxh1TXc7sE/eAg/6lQhBhHuY+Ow3YKVmI5g0H/3HzI6nbM2 1UuZX4HCqtYYLCnBzRZsWpb6LhOUZvZWFPS8qvBKU+qSh2J/hVhyv0pl+o55SmJOz8o0 HDa7tQ2cNwz/tFQR+qTPD6GP0w9ce27RnTAvsVbSZeXLVuO2QsTFRAla35mRvxMU7fxT GyrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799607; x=1685391607; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=90TVpregLfTN8aIVCSeAhQNQKYWfvkrvrWKSEVNGrho=; b=Y2yZmoEa8DYIh0H1Y2J5l98f0gtYg+Z9PM838V7X8knuClHiOo8zGZeyLBl3wf80GT qlIIUkoSE6jb6nABOR6snr5RXY47FiDEc5kI/gWzjDLCLhvNaGqMdvw6TpXRdfE3qNGo NbvdIdtkutCr1RKbaXyoXFKNM6X8WKYv57PDsIkpSHoZrsbkeFx6bmSRBMQ6A1CfhQJb cTCy9RwcO19H9/zsVzhakVrwDVUHQWx32fkwmGwjcCOQPyJpbExgzZYfW+NJn9C1JI7S 3Uu53ixMNriqZ0Nza60FL8J0dt0LsVBLx6elj20Y+xLsdWvr981KswbYAU4zGteF7xUB 6hhg== X-Gm-Message-State: AC+VfDyMVsItCiK2hYa28TbXXIDOhLuJ+oW2f/iTtph4KtqNor74U6VO w5P4myTEq8fno0xtxTLIxLGBUesUqt3dhmXoaHYfQA== X-Google-Smtp-Source: ACHHUZ5JUdx87BEIciFIxm56nnWxuaCqqla/JponFEliOk4jYLnNImAnOK0YAnZIo89Ntq9cgwZXtw== X-Received: by 2002:a25:f801:0:b0:b9d:9fbe:e83d with SMTP id u1-20020a25f801000000b00b9d9fbee83dmr2460828ybd.29.1682799607277; Sat, 29 Apr 2023 13:20:07 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id c16-20020a5b0150000000b00b96ae6e1f57sm5844312ybp.41.2023.04.29.13.20.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:06 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 02/26] btrfs-progs: remove useless add_root_to_dirty_list call in mkfs Date: Sat, 29 Apr 2023 16:19:33 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org We are calling this when creating the UUID tree, however when we create the tree it inserts the root item into the tree_root, so this call is superfluous. Signed-off-by: Josef Bacik --- mkfs/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mkfs/main.c b/mkfs/main.c index 4856cf96..418c721c 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -789,7 +789,6 @@ static int create_uuid_tree(struct btrfs_trans_handle *trans) goto out; } - add_root_to_dirty_list(root); fs_info->uuid_root = root; ret = btrfs_uuid_tree_add(trans, fs_info->fs_root->root_item.uuid, BTRFS_UUID_KEY_SUBVOL, From patchwork Sat Apr 29 20:19:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227080 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A173FC7EE23 for ; Sat, 29 Apr 2023 20:20:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230118AbjD2UUM (ORCPT ); Sat, 29 Apr 2023 16:20:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45088 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229972AbjD2UUK (ORCPT ); Sat, 29 Apr 2023 16:20:10 -0400 Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 69E87E70 for ; Sat, 29 Apr 2023 13:20:09 -0700 (PDT) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-54f6f0dae19so11448437b3.0 for ; Sat, 29 Apr 2023 13:20:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799608; x=1685391608; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=9wwspeZVlYxQaBnSE+MC74amhy/TEKZm3/Ci9zzPf7A=; b=a9ex1YaYxpA/JLjkXPwSASbKIJXUkUHLE3ia7t7/pFjkwfkKid+Cnf5eeKdTssijTf l38SzBRuI2CDhJXoN7BsW9r6CxR3cp4ASjAGUlOrY76RJeZz3m70bZiH8+S5QUrU9/Va zcwqOohfkvGsHagXS3UPRCzJmCA1CwOefY1HmrTakEB84/454wcnjCMc8iHF5/c1NDXN YTTmSbucBplH+Bfga/xZ32jBJIxviQ1jUU/kvYnkjX8UdwI/qf4AaXnUCdlDjTIN+tGq H9JWdNVIUVA3F9ySDw1a31/LRmF5rq5IvfXnDYXMqZQl3I4a2tVpnWeSsKydJMm286if EOrg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799608; x=1685391608; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9wwspeZVlYxQaBnSE+MC74amhy/TEKZm3/Ci9zzPf7A=; b=f/X5H15gUwBN7urGqfVzEIyhk128u4tHzkxPLFg5p5kE9kr37LU3HFphZhhRVzfAXr 4KYrBJYckoiUKzai1ip6IzwDcUhmU85b2H6onsAn8YrHc0Ktn5eUeWVrbHPuehtkB5Ki YxzavWiIjc+qPIgTnz8a/3ZwKXKdr2x71HD6nTRr/NDT7zUqaOEiSdnuO6ldAu9j53sX FaMJrt7/20xrbJ/6iu6jYObuGnNtaUHhGB90JVrkqXkZ8hxwSK53CNSsAN4jt8SsMBfe D3RaF34Tt0kLz7nGh1EZobJX4dBPKExlhA2fBM0iMfP6PcAnsjvFzGhl7zgXye7TsxMP efFw== X-Gm-Message-State: AC+VfDyMlKaSFoX4COrsd4eN5mrGrk9LbiMI1Mxej+iCacPVUZkSVSA8 gww/P/5KsyJzW2wWfNCK6n/yGGGLiZ+7nMD1Rz89mA== X-Google-Smtp-Source: ACHHUZ5bKMo+M2KKzufa6Z+kKKju8NpYGOaI/ECV3N6Wz+YDjcguJ9VRuZ7+dZCuUEPvWfZdK3Ex7Q== X-Received: by 2002:a0d:d88b:0:b0:54f:32a5:efde with SMTP id a133-20020a0dd88b000000b0054f32a5efdemr7797570ywe.10.1682799608323; Sat, 29 Apr 2023 13:20:08 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id w9-20020a817b09000000b0055a0c417bc6sm136748ywc.109.2023.04.29.13.20.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:08 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 03/26] btrfs-progs: remove add_root_to_dirty_list call when creating free space tree Date: Sat, 29 Apr 2023 16:19:34 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Since we insert the free space tree item into the tree_root when we create the tree we don't need to call add_root_to_dirty_list. Signed-off-by: Josef Bacik --- kernel-shared/free-space-tree.c | 1 - 1 file changed, 1 deletion(-) diff --git a/kernel-shared/free-space-tree.c b/kernel-shared/free-space-tree.c index 4064b7cb..a8a0a6ec 100644 --- a/kernel-shared/free-space-tree.c +++ b/kernel-shared/free-space-tree.c @@ -1522,7 +1522,6 @@ int btrfs_create_free_space_tree(struct btrfs_fs_info *fs_info) ret = btrfs_global_root_insert(fs_info, free_space_root); if (ret) goto abort; - add_root_to_dirty_list(free_space_root); do { block_group = btrfs_lookup_first_block_group(fs_info, start); From patchwork Sat Apr 29 20:19:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227082 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E973AC77B7C for ; Sat, 29 Apr 2023 20:20:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229972AbjD2UUN (ORCPT ); Sat, 29 Apr 2023 16:20:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229975AbjD2UUM (ORCPT ); Sat, 29 Apr 2023 16:20:12 -0400 Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BB2FE6C for ; Sat, 29 Apr 2023 13:20:10 -0700 (PDT) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-5562c93f140so10856687b3.1 for ; Sat, 29 Apr 2023 13:20:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799609; x=1685391609; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=LnN241K7LXD/Glp4haAL2w2w1cE1ZjHjvJ9h+WX3H+c=; b=CtzhjkZvYcJXgHrUDIWpnGLrc5AP5If7ZSVhz+hE7DHfoL91GrTpqSreFweDFuHrVk M1hBe8bkiFvHhNJbzM2YS5numYymt5OeDYuqRQ82yg4/QNi+Rvh6V2odYtwnMoL4asqZ HHRpljZ2hJ9Fe1kSjF+EM9DMjbooEnIPxQixZVTEduCi4AosrK7LoC45murjEUVz75DA jZwVGQTKI1FbmtFce6Jgi/pEgsYY2RKDog6NM4t2t+hZkVPTvGGkciWo3TjUpkEO9A39 pdyAvNR4UfrNuPvMpWZs/kaN+OAdjDrWmY9opXj1e6dmGfPMR1mDt26yjFwv6dR51rHo 8Arg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799609; x=1685391609; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LnN241K7LXD/Glp4haAL2w2w1cE1ZjHjvJ9h+WX3H+c=; b=KHgvu5V2W0aGE7uRZh//wMbJZroiB11f9H6qaN/p7ltpgGqjps9gzxAWBuBmFDNYfB q3/xIFj0BFktU1aydCdQeKhAKcynZw6pnabjSPJnoCNmj3fumhsRTSXtofmq0yQBW+36 It/XBlxYSuXv2oIxvacq7zf4b49hG+xUYz9UtFcVZ8/Wy8AaMvqByAYYYnWHBr2o27gj +z+TvxNqokeMDGkUJf4BzsGzkafxLR399/hJE7h94eL0nOkSHWyyvu9295FXhuIkOi9V xKwqsQoID9ZrWHxz+G7JaTyfkbO5LLAkEMlRycQbUA4+zxKsCgkm9C1dWmnCEEs1pCxv XFFA== X-Gm-Message-State: AC+VfDzFAKXHZtJcGEVgVzHPfZwzgM3ddGjE29Xy1Vox+9Tj+N7mBeF2 F2rG3U6/WZ5SHkhmFG9D5K9Gdi9W6c64RPhLygZIRA== X-Google-Smtp-Source: ACHHUZ6+2ylilZcP1stE9O9q8oIgPZy7OuAK8l6FdAZ0WN/U9CacgI/b3ZWbNONorR1sdALzvjXgGg== X-Received: by 2002:a0d:e64a:0:b0:54f:8171:38db with SMTP id p71-20020a0de64a000000b0054f817138dbmr7925250ywe.32.1682799609392; Sat, 29 Apr 2023 13:20:09 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id u188-20020a8160c5000000b00556aa81f615sm3697148ywb.68.2023.04.29.13.20.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:09 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 04/26] btrfs-progs: make add_root_to_dirty_list static and unexport it Date: Sat, 29 Apr 2023 16:19:35 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Now that there are no users of this helper outside of ctree.c, unexport it and make it static. Signed-off-by: Josef Bacik --- kernel-shared/ctree.c | 2 +- kernel-shared/ctree.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index d5a1f90b..3cb3378e 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -119,7 +119,7 @@ void btrfs_release_path(struct btrfs_path *p) memset(p, 0, sizeof(*p)); } -void add_root_to_dirty_list(struct btrfs_root *root) +static void add_root_to_dirty_list(struct btrfs_root *root) { if (test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state) && list_empty(&root->dirty_list)) { diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 5eba9c14..ce050cec 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -988,7 +988,6 @@ int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path, u64 iobjectid, u64 ioff, u8 key_type, struct btrfs_key *found_key); void btrfs_release_path(struct btrfs_path *p); -void add_root_to_dirty_list(struct btrfs_root *root); struct btrfs_path *btrfs_alloc_path(void); void btrfs_free_path(struct btrfs_path *p); void btrfs_init_path(struct btrfs_path *p); From patchwork Sat Apr 29 20:19:36 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227083 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CBC10C77B60 for ; Sat, 29 Apr 2023 20:20:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230166AbjD2UUO (ORCPT ); Sat, 29 Apr 2023 16:20:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45194 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229498AbjD2UUN (ORCPT ); Sat, 29 Apr 2023 16:20:13 -0400 Received: from mail-yw1-x112a.google.com (mail-yw1-x112a.google.com [IPv6:2607:f8b0:4864:20::112a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7B451210A for ; Sat, 29 Apr 2023 13:20:11 -0700 (PDT) Received: by mail-yw1-x112a.google.com with SMTP id 00721157ae682-552a6357d02so16102387b3.3 for ; Sat, 29 Apr 2023 13:20:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799610; x=1685391610; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=zFTqikvgjo5fVhqkz4RgFb15k/CN+mj8A4rT4aIo58c=; b=c7i4S6ZOw1YXBJNKNohMeXGjm+IK8bjhhJTu42gjPuZialSoNnciNbAa+kTC0SM5Rz tSpBckov0QACWqb0gsmEbuAL9IgkA0WO5WzqPoVamSUZnUnLOiDycj8Kh+zo0AO0Mo2Z 6qseuKDTyXTch62wQW+24PBURIA/5Z3xZXoytGkKH3fySRYAG06Wv6H4ysVxomTRiF+t z4gEcWfLSPVnS+nlGaIEwwDdXulCueGzwrTjgyWfgaPtkTgMB8zEsBf2KRvGAeSuA5BQ JHR3cTgKpr2qoTDfCHzPJfOfBumZ8mOfSO+FW6Xrq2YcCdRPQqRvyznycrG9vgziOeb5 M9rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799610; x=1685391610; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zFTqikvgjo5fVhqkz4RgFb15k/CN+mj8A4rT4aIo58c=; b=JTUUQoGRi+gZbVy63sOrAc/r5f41+MruwrE434CY9mCTuC1ubiezLp5Xc3h+2ImyuE alGBCtl47ElTAlgHEU14UX/zEXBCGhHw6RkOrhnZbBGTcs6SlkhZw/UV9HXBCNzLHUp+ fTZs0agBdZboOnH7D9RKoFyWRwR8MKtt6U/mYl6p1TyHOp8kUJwpi2C/ABscFt2XdGHb KOhhqRKwMW7wCc0jKKzFBLupMN2zdPP3m3d3Zrw/Q+GpWIhLtqjG7isylHLYMTGsJAqo sGinTtIvid7YmTpwxBzk6R5sV/3/uGTx0LbIJh53rgeuotoaAr63OlrbS/xr7f4rStYh cXEw== X-Gm-Message-State: AC+VfDybHJo5eoXHUv1K7YQwWg+nCI5mgBEFwlyKQWrWv+uR/s8EkdrQ 1N2wIoyM9li4Og+rNmu0c8L7v3WC2AGjEF2zOBmL+w== X-Google-Smtp-Source: ACHHUZ66qvKNEavufDIhWbTnVAU3/KIjSRgothi4QlunhmC4UfSudXqGT1Zg7300aSyLgdYE5DD9Mg== X-Received: by 2002:a0d:db93:0:b0:541:85e1:3a87 with SMTP id d141-20020a0ddb93000000b0054185e13a87mr7642823ywe.33.1682799610375; Sat, 29 Apr 2023 13:20:10 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id v5-20020a814805000000b0054fba955474sm6259085ywa.17.2023.04.29.13.20.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:10 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 05/26] btrfs-progs: pass btrfs_trans_handle through btrfs_clear_buffer_dirty Date: Sat, 29 Apr 2023 16:19:36 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This is the calling convention in the kernel because we track dirty blocks per transaction instead of globally in the fs_info. Simply mirror what we do in the kernel to make it easier to sync ctree.c locally. Signed-off-by: Josef Bacik --- cmds/rescue.c | 2 +- kernel-shared/ctree.c | 12 ++++++------ kernel-shared/disk-io.c | 2 +- kernel-shared/extent-tree.c | 2 +- kernel-shared/extent_io.c | 3 ++- kernel-shared/extent_io.h | 4 +++- kernel-shared/transaction.c | 4 ++-- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/cmds/rescue.c b/cmds/rescue.c index 5551374d..75a4192f 100644 --- a/cmds/rescue.c +++ b/cmds/rescue.c @@ -340,7 +340,7 @@ static int clear_uuid_tree(struct btrfs_fs_info *fs_info) if (ret < 0) goto out; list_del(&uuid_root->dirty_list); - ret = btrfs_clear_buffer_dirty(uuid_root->node); + ret = btrfs_clear_buffer_dirty(trans, uuid_root->node); if (ret < 0) goto out; ret = btrfs_free_tree_block(trans, btrfs_root_id(uuid_root), diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 3cb3378e..b127dcf9 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -434,7 +434,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, ret = btrfs_dec_ref(trans, root, buf, 1); BUG_ON(ret); } - btrfs_clear_buffer_dirty(buf); + btrfs_clear_buffer_dirty(trans, buf); } return 0; } @@ -760,7 +760,7 @@ static int balance_level(struct btrfs_trans_handle *trans, root->node = child; add_root_to_dirty_list(root); path->nodes[level] = NULL; - btrfs_clear_buffer_dirty(mid); + btrfs_clear_buffer_dirty(trans, mid); /* once for the path */ free_extent_buffer(mid); @@ -814,7 +814,7 @@ static int balance_level(struct btrfs_trans_handle *trans, u64 bytenr = right->start; u32 blocksize = right->len; - btrfs_clear_buffer_dirty(right); + btrfs_clear_buffer_dirty(trans, right); free_extent_buffer(right); right = NULL; wret = btrfs_del_ptr(root, path, level + 1, pslot + 1); @@ -861,7 +861,7 @@ static int balance_level(struct btrfs_trans_handle *trans, /* we've managed to empty the middle node, drop it */ u64 bytenr = mid->start; u32 blocksize = mid->len; - btrfs_clear_buffer_dirty(mid); + btrfs_clear_buffer_dirty(trans, mid); free_extent_buffer(mid); mid = NULL; wret = btrfs_del_ptr(root, path, level + 1, pslot); @@ -2834,7 +2834,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, if (leaf == root->node) { btrfs_set_header_level(leaf, 0); } else { - btrfs_clear_buffer_dirty(leaf); + btrfs_clear_buffer_dirty(trans, leaf); wret = btrfs_del_leaf(trans, root, path, leaf); BUG_ON(ret); if (wret) @@ -2870,7 +2870,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, } if (btrfs_header_nritems(leaf) == 0) { - btrfs_clear_buffer_dirty(leaf); + btrfs_clear_buffer_dirty(trans, leaf); path->slots[1] = slot; ret = btrfs_del_leaf(trans, root, path, leaf); BUG_ON(ret); diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 536b7119..3e0c3534 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -2318,7 +2318,7 @@ int btrfs_delete_and_free_root(struct btrfs_trans_handle *trans, return ret; list_del(&root->dirty_list); - ret = btrfs_clear_buffer_dirty(root->node); + ret = btrfs_clear_buffer_dirty(trans, root->node); if (ret) return ret; ret = btrfs_free_tree_block(trans, btrfs_root_id(root), root->node, 0, 1); diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index 062ff4a7..bbce9587 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -1899,7 +1899,7 @@ static int pin_down_bytes(struct btrfs_trans_handle *trans, u64 bytenr, if (header_owner != BTRFS_TREE_LOG_OBJECTID && header_transid == trans->transid && !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN)) { - btrfs_clear_buffer_dirty(buf); + btrfs_clear_buffer_dirty(trans, buf); free_extent_buffer(buf); return 1; } diff --git a/kernel-shared/extent_io.c b/kernel-shared/extent_io.c index 105b5ec8..e38bb1ed 100644 --- a/kernel-shared/extent_io.c +++ b/kernel-shared/extent_io.c @@ -585,7 +585,8 @@ int set_extent_buffer_dirty(struct extent_buffer *eb) return 0; } -int btrfs_clear_buffer_dirty(struct extent_buffer *eb) +int btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, + struct extent_buffer *eb) { struct extent_io_tree *tree = &eb->fs_info->dirty_buffers; if (eb->flags & EXTENT_BUFFER_DIRTY) { diff --git a/kernel-shared/extent_io.h b/kernel-shared/extent_io.h index a1cda3a5..f573a4e2 100644 --- a/kernel-shared/extent_io.h +++ b/kernel-shared/extent_io.h @@ -54,6 +54,7 @@ static inline int le_test_bit(int nr, const u8 *addr) } struct btrfs_fs_info; +struct btrfs_trans_handle; struct extent_buffer { struct cache_extent cache_node; @@ -125,7 +126,8 @@ void memset_extent_buffer(const struct extent_buffer *eb, char c, int extent_buffer_test_bit(const struct extent_buffer *eb, unsigned long start, unsigned long nr); int set_extent_buffer_dirty(struct extent_buffer *eb); -int btrfs_clear_buffer_dirty(struct extent_buffer *eb); +int btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, + struct extent_buffer *eb); int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 logical, u64 *len, int mirror); int write_data_to_disk(struct btrfs_fs_info *info, void *buf, u64 offset, diff --git a/kernel-shared/transaction.c b/kernel-shared/transaction.c index f99bc684..1e1ec85b 100644 --- a/kernel-shared/transaction.c +++ b/kernel-shared/transaction.c @@ -161,7 +161,7 @@ again: goto cleanup; } start += eb->len; - btrfs_clear_buffer_dirty(eb); + btrfs_clear_buffer_dirty(trans, eb); free_extent_buffer(eb); } } @@ -184,7 +184,7 @@ cleanup: eb = find_first_extent_buffer(fs_info, start); BUG_ON(!eb || eb->start != start); start += eb->len; - btrfs_clear_buffer_dirty(eb); + btrfs_clear_buffer_dirty(trans, eb); free_extent_buffer(eb); } } From patchwork Sat Apr 29 20:19:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227084 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 16289C77B60 for ; Sat, 29 Apr 2023 20:20:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230016AbjD2UUU (ORCPT ); Sat, 29 Apr 2023 16:20:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45398 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230155AbjD2UUT (ORCPT ); Sat, 29 Apr 2023 16:20:19 -0400 Received: from mail-yw1-x112f.google.com (mail-yw1-x112f.google.com [IPv6:2607:f8b0:4864:20::112f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F0E4F26B7 for ; Sat, 29 Apr 2023 13:20:12 -0700 (PDT) Received: by mail-yw1-x112f.google.com with SMTP id 00721157ae682-54f8e823e47so16267317b3.2 for ; Sat, 29 Apr 2023 13:20:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799611; x=1685391611; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=/15BqUhxLLzxK50oeHbFym1ijxF6oOk1k4nxskxbyYQ=; b=gqu7l3XM6vyKx3u9g0QkaU5wW99hFAiXH3ywqY3Cp5Q13NONW4UWmwkL3+XqPdgh8I oHFAUIjB8wpt3Dfshtm9Im3sAcBR6ctljV96dRUt7gSMARI8KlkZHj09YvtgX7LSgHdF AIkJeHbUt6+9+HAoqrH1YTTyC3vM7U+kDrHCncWZ+I8/53fUcy9VO+sVmvVWFTrW3ApR 6rlY1wn0Kl+3nWsH7A3IPUXSP3+SCKJJhVJduQyqWrxx1zyU/m/ZYRvb2Ls9TJoPSWTP Hxo7PBFqzkI41n635HFeSqS+CQ8LZVeAArZDWtddBLusC+M35fAK8eHPW9q5bvh02MbK /avA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799611; x=1685391611; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/15BqUhxLLzxK50oeHbFym1ijxF6oOk1k4nxskxbyYQ=; b=ghTUYz0oZPC2Jmi/VvdRG6GwDLeRLI3evpE1mo8yjQqXhARnL+fTwKYGmD4r7+t/r1 D2OuW3JVDsQIEATpKZj9tY4D2Ff4bYW1Aww6Lj6PTRxrW7yJHt9G3Me7L1VaCdeaY4fw NATvThBVoIp2PmOlp8KQVp5XZOHRLc/P8yp786iMOOS1FxXSiIq63194mr/8DrlU6q5U dd/yd9haCKRwyjp4hUb8vT7+tc9xDGKE9mk08cnCGEWXVhpEJYVPefZDYgxWfzteQM9b VTrAGhjJOBF75XjBL8LGV6rjCXlf8qJN6Rkf1zqtCxhlnI3iOobykyjQY9zFKGmvQS51 Ho/g== X-Gm-Message-State: AC+VfDxYi/c20ord/rFpr3sBQMcs8hmkcd31C1s9lCF3uETPzm6qh4J/ rCxz50df9k4F1yBjtcyARUOTg4P8pKRnG9e3ZGZrUQ== X-Google-Smtp-Source: ACHHUZ5HijgcSNYNen8rb73EkhIY+3gHcuC0N06/CrIR0rdzOzaM4LoHXElxyUR84s8Zu5kkn96Zlw== X-Received: by 2002:a0d:f801:0:b0:55a:7c7:7b45 with SMTP id i1-20020a0df801000000b0055a07c77b45mr742243ywf.30.1682799611438; Sat, 29 Apr 2023 13:20:11 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id e204-20020a8169d5000000b0054605c23114sm596516ywc.66.2023.04.29.13.20.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:11 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 06/26] btrfs-progs: update read_node_slot to match the kernel definition Date: Sat, 29 Apr 2023 16:19:37 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In the kernel this is called btrfs_read_node_slot, and it doesn't take a btrfs_fs_info. Update the btrfs-progs version to match the kernel and update all of the callers. Signed-off-by: Josef Bacik --- cmds/restore.c | 5 ++--- kernel-shared/ctree.c | 32 +++++++++++++++----------------- kernel-shared/ctree.h | 4 ++-- kernel-shared/print-tree.c | 2 +- 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/cmds/restore.c b/cmds/restore.c index 9fe7b4d2..31cad31f 100644 --- a/cmds/restore.c +++ b/cmds/restore.c @@ -240,7 +240,6 @@ static int next_leaf(struct btrfs_root *root, struct btrfs_path *path) int offset = 1; struct extent_buffer *c; struct extent_buffer *next = NULL; - struct btrfs_fs_info *fs_info = root->fs_info; again: for (; level < BTRFS_MAX_LEVEL; level++) { @@ -267,7 +266,7 @@ again: continue; } - next = read_node_slot(fs_info, c, slot); + next = btrfs_read_node_slot(c, slot); if (extent_buffer_uptodate(next)) break; offset++; @@ -281,7 +280,7 @@ again: path->slots[level] = 0; if (!level) break; - next = read_node_slot(fs_info, next, 0); + next = btrfs_read_node_slot(next, 0); if (!extent_buffer_uptodate(next)) goto again; } diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index b127dcf9..cbf735de 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -681,9 +681,10 @@ int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key, slot); } -struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info, - struct extent_buffer *parent, int slot) +struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent, + int slot) { + struct btrfs_fs_info *fs_info = parent->fs_info; struct extent_buffer *ret; int level = btrfs_header_level(parent); @@ -752,7 +753,7 @@ static int balance_level(struct btrfs_trans_handle *trans, return 0; /* promote the child to a root */ - child = read_node_slot(fs_info, mid, 0); + child = btrfs_read_node_slot(mid, 0); BUG_ON(!extent_buffer_uptodate(child)); ret = btrfs_cow_block(trans, root, child, mid, 0, &child); BUG_ON(ret); @@ -776,7 +777,7 @@ static int balance_level(struct btrfs_trans_handle *trans, BTRFS_NODEPTRS_PER_BLOCK(fs_info) / 4) return 0; - left = read_node_slot(fs_info, parent, pslot - 1); + left = btrfs_read_node_slot(parent, pslot - 1); if (extent_buffer_uptodate(left)) { wret = btrfs_cow_block(trans, root, left, parent, pslot - 1, &left); @@ -785,7 +786,7 @@ static int balance_level(struct btrfs_trans_handle *trans, goto enospc; } } - right = read_node_slot(fs_info, parent, pslot + 1); + right = btrfs_read_node_slot(parent, pslot + 1); if (extent_buffer_uptodate(right)) { wret = btrfs_cow_block(trans, root, right, parent, pslot + 1, &right); @@ -937,7 +938,7 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, if (!parent) return 1; - left = read_node_slot(fs_info, parent, pslot - 1); + left = btrfs_read_node_slot(parent, pslot - 1); /* first, try to make some room in the middle buffer */ if (extent_buffer_uptodate(left)) { @@ -978,7 +979,7 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, } free_extent_buffer(left); } - right= read_node_slot(fs_info, parent, pslot + 1); + right= btrfs_read_node_slot(parent, pslot + 1); /* * then try to empty the right most buffer into the middle @@ -1230,7 +1231,7 @@ again: reada_for_search(fs_info, p, level, slot, key->objectid); - b = read_node_slot(fs_info, b, slot); + b = btrfs_read_node_slot(b, slot); if (!extent_buffer_uptodate(b)) return -EIO; } else { @@ -1789,7 +1790,6 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root struct extent_buffer *right; struct extent_buffer *upper; struct btrfs_disk_key disk_key; - struct btrfs_fs_info *fs_info = root->fs_info; int slot; u32 i; int free_space; @@ -1810,7 +1810,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root if (slot >= btrfs_header_nritems(upper) - 1) return 1; - right = read_node_slot(fs_info, upper, slot + 1); + right = btrfs_read_node_slot(upper, slot + 1); if (!extent_buffer_uptodate(right)) { if (IS_ERR(right)) return PTR_ERR(right); @@ -1938,7 +1938,6 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root struct btrfs_disk_key disk_key; struct extent_buffer *right = path->nodes[0]; struct extent_buffer *left; - struct btrfs_fs_info *fs_info = root->fs_info; int slot; int i; int free_space; @@ -1962,7 +1961,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root return 1; } - left = read_node_slot(fs_info, path->nodes[1], slot - 1); + left = btrfs_read_node_slot(path->nodes[1], slot - 1); free_space = btrfs_leaf_free_space(left); if (free_space < data_size) { free_extent_buffer(left); @@ -2898,7 +2897,6 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) int level = 1; struct extent_buffer *c; struct extent_buffer *next = NULL; - struct btrfs_fs_info *fs_info = root->fs_info; while(level < BTRFS_MAX_LEVEL) { if (!path->nodes[level]) @@ -2914,7 +2912,7 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) } slot--; - next = read_node_slot(fs_info, c, slot); + next = btrfs_read_node_slot(c, slot); if (!extent_buffer_uptodate(next)) { if (IS_ERR(next)) return PTR_ERR(next); @@ -2934,7 +2932,7 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) path->slots[level] = slot; if (!level) break; - next = read_node_slot(fs_info, next, slot); + next = btrfs_read_node_slot(next, slot); if (!extent_buffer_uptodate(next)) { if (IS_ERR(next)) return PTR_ERR(next); @@ -2977,7 +2975,7 @@ int btrfs_next_sibling_tree_block(struct btrfs_fs_info *fs_info, if (path->reada) reada_for_search(fs_info, path, level, slot, 0); - next = read_node_slot(fs_info, c, slot); + next = btrfs_read_node_slot(c, slot); if (!extent_buffer_uptodate(next)) return -EIO; break; @@ -3000,7 +2998,7 @@ int btrfs_next_sibling_tree_block(struct btrfs_fs_info *fs_info, break; if (path->reada) reada_for_search(fs_info, path, level, 0, 0); - next = read_node_slot(fs_info, next, 0); + next = btrfs_read_node_slot(next, 0); if (!extent_buffer_uptodate(next)) return -EIO; } diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index ce050cec..edf74fcc 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -948,8 +948,8 @@ int btrfs_convert_one_bg(struct btrfs_trans_handle *trans, u64 bytenr); int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2); int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot); -struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info, - struct extent_buffer *parent, int slot); +struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent, + int slot); int btrfs_previous_item(struct btrfs_root *root, struct btrfs_path *path, u64 min_objectid, int type); diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c index 6cdfdef7..594c524f 100644 --- a/kernel-shared/print-tree.c +++ b/kernel-shared/print-tree.c @@ -1487,7 +1487,7 @@ static int search_leftmost_tree_block(struct btrfs_fs_info *fs_info, struct extent_buffer *eb; path->slots[i] = 0; - eb = read_node_slot(fs_info, path->nodes[i], 0); + eb = btrfs_read_node_slot(path->nodes[i], 0); if (!extent_buffer_uptodate(eb)) { ret = -EIO; goto out; From patchwork Sat Apr 29 20:19:38 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227085 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D75EC77B7C for ; Sat, 29 Apr 2023 20:20:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230193AbjD2UUW (ORCPT ); Sat, 29 Apr 2023 16:20:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45408 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230154AbjD2UUT (ORCPT ); Sat, 29 Apr 2023 16:20:19 -0400 Received: from mail-yw1-x1136.google.com (mail-yw1-x1136.google.com [IPv6:2607:f8b0:4864:20::1136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D92032691 for ; Sat, 29 Apr 2023 13:20:13 -0700 (PDT) Received: by mail-yw1-x1136.google.com with SMTP id 00721157ae682-54fe08015c1so18007657b3.3 for ; Sat, 29 Apr 2023 13:20:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799613; x=1685391613; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=K0Km+kdo4/+kYbh2Lff56rojPceL5zhqMqbab36ZINQ=; b=ymtbujn37gxudYBa96WJ1afmSS7JJOrLIts11NwT7zbIVj5SIQinR3naELFWGocPRK xRFXZ5/Wbj9gX9VqRR1jbKOURWqjswX5g9cArFdgY7dW3B45h8WPwCdZn5lEzgcfDcnH DlWjZQvvRY7DlFalTPLe7QHwcIi8iOMFnSP6TucJQWLyOzDPpdt8hOCxaJBscyOx72Kc qQM2A4uL6bwpWLLAQ4BbQCsP+Kc+dfUwgd82JjIMmVEjETOj0+GNsFR0HlRa5O3kZ968 0S79KCTbCQ7qwRucz+KBNVSyxIZWLfg+Sspx2PgYA/rmC2hLuSSjm9T0Onkf8vT+z/tp lU9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799613; x=1685391613; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=K0Km+kdo4/+kYbh2Lff56rojPceL5zhqMqbab36ZINQ=; b=M9VinxlCcnII4NYxLjepRfXrUAS22twvcgJjB38Vbtqbz8tG7jrDDra7St5ECJxxWC 1jBehaauWtOwji9fcE0oisj0byBh5OqqIt0iPjiaJmOlYEAXeCU5AOV1LfOJj6G2j3kj eqGmpxr2oLA+CCbJQD7Et9KNa0XPbGzzekeaTrvm1gCf05pzfGv6WTtIhKn+8yl8DigZ aDqnXlfU2hj6f4oC2JTWlmhhU6Eze6DeXAYBq/EbyzpA7scJMDsdqy0XRn2gewQv+2AS eWx8xT6VDhoyEtuqoyD1r5xPN/wE6Z4YxmNY4xdOZn9M+G0PcajDY62YM3mTnRausoee 7U9g== X-Gm-Message-State: AC+VfDwr8yUrYCIHIwHBYiLEs5xnqrbd0xqxkzTW294YZLPKpMdwuZZr AQ8xx7zwG4GGNzCbkIHhjbmGIdin0TnnXgYEGU2h9g== X-Google-Smtp-Source: ACHHUZ4Ju5FOhI7Fte9UG+osTCl32EHIG3vxWwTKBPAqYfQiB4whlREg4D2VzMMDwgMZmGvRVx0QuA== X-Received: by 2002:a81:9e0e:0:b0:559:f7d4:661b with SMTP id m14-20020a819e0e000000b00559f7d4661bmr1717186ywj.14.1682799612574; Sat, 29 Apr 2023 13:20:12 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id r127-20020a0dcf85000000b0054f0baa196asm6231104ywd.107.2023.04.29.13.20.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:12 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 07/26] btrfs-progs: update btrfs_bin_search to match the kernel definition Date: Sat, 29 Apr 2023 16:19:38 -0400 Message-Id: <1fa6d5af71efdf44f11efe5f0d1631e46f9e3d41.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This was updated to include a first_slot argument, update it to match the kernel definition to make it easier to sync ctree.c. Signed-off-by: Josef Bacik --- check/main.c | 2 +- kernel-shared/ctree.c | 6 +++--- kernel-shared/ctree.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/check/main.c b/check/main.c index d9c54deb..a6485db5 100644 --- a/check/main.c +++ b/check/main.c @@ -6524,7 +6524,7 @@ static int run_next_block(struct btrfs_root *root, * technically unreferenced and don't need to be worried about. */ if (ri != NULL && ri->drop_level && level > ri->drop_level) { - ret = btrfs_bin_search(buf, &ri->drop_key, &i); + ret = btrfs_bin_search(buf, 0, &ri->drop_key, &i); if (ret && i > 0) i--; } diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index cbf735de..2e7b6c9a 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -664,8 +664,8 @@ static int generic_bin_search(struct extent_buffer *eb, unsigned long p, * simple bin_search frontend that does the right thing for * leaves vs nodes */ -int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key, - int *slot) +int btrfs_bin_search(struct extent_buffer *eb, int first_slot, + const struct btrfs_key *key, int *slot) { if (btrfs_header_level(eb) == 0) return generic_bin_search(eb, @@ -1196,7 +1196,7 @@ again: ret = check_block(fs_info, p, level); if (ret) return -1; - ret = btrfs_bin_search(b, key, &slot); + ret = btrfs_bin_search(b, 0, key, &slot); if (level != 0) { if (ret && slot > 0) slot -= 1; diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index edf74fcc..d5797d09 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -982,8 +982,8 @@ int btrfs_search_slot_for_read(struct btrfs_root *root, const struct btrfs_key *key, struct btrfs_path *p, int find_higher, int return_any); -int btrfs_bin_search(struct extent_buffer *eb, const struct btrfs_key *key, - int *slot); +int btrfs_bin_search(struct extent_buffer *eb, int first_slot, + const struct btrfs_key *key, int *slot); int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path, u64 iobjectid, u64 ioff, u8 key_type, struct btrfs_key *found_key); From patchwork Sat Apr 29 20:19:39 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227087 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61BFBC77B7F for ; Sat, 29 Apr 2023 20:20:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230226AbjD2UUX (ORCPT ); Sat, 29 Apr 2023 16:20:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45388 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230214AbjD2UUV (ORCPT ); Sat, 29 Apr 2023 16:20:21 -0400 Received: from mail-yb1-xb2f.google.com (mail-yb1-xb2f.google.com [IPv6:2607:f8b0:4864:20::b2f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2430D271C for ; Sat, 29 Apr 2023 13:20:15 -0700 (PDT) Received: by mail-yb1-xb2f.google.com with SMTP id 3f1490d57ef6-b97ec4bbc5aso784557276.3 for ; Sat, 29 Apr 2023 13:20:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799614; x=1685391614; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=XzgAoXnHiCe7K9J9y1gABU4TzASdEaVMvWOIksRyrpM=; b=5BcyLe21QuqTl5owzaPJG1cdwHnrKhf2BFuv63lmCf9bzqDwxcAj68ZpLD1B0QQpKK nXW6nt+P4iB4KsflKzg1+kiEiSGiXFiZ7Zg1fG0tCNp8SOrFG4LfzVjbk+my3bQIoZZP wOzVWUuCtqAACiaTjxLX3lt0Hx5md/PcB4J7FN+qopdSJbbFg6/b6GGAYSZX1qbBk4y5 6/Dx8eClUdIRrM7oli6Ei2KCdNbAuhjqiPIDOEiQN3789uY6FZqMeEq//gmNS+QYm9Jn YeGoHfUTRjbAzeVaf1ZGgMf8XSnd1X4o6KeG1d2RlCv3ucshzYPniKjbb5ojniNwBaBs Ea6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799614; x=1685391614; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=XzgAoXnHiCe7K9J9y1gABU4TzASdEaVMvWOIksRyrpM=; b=CXDZ/Idy5lLgAOHokB4KvnENzRPOCWAZ6kAaFweBvOzIci9bFuQ8nejsOB3vw5gXMh BYEqcAC6y72EuMO95rU6RMBs/WWTc9UpYEio9mqp8ULaxYWDM4mgY4GeQ5M4IYtOcU3C gj1MxpCCbXc8o+8INOW8KtY/G94QW956l5btA5Gy6lzPJDHxTLW1SyxPa2i1FBg49KIL JvyJGHi2tWZT34BJlLPxGLfSe+6Ioxi+k+v8IZddHrCloa0MFNFzD1daCg2LYF+xxutm gAs0ypb7xrFIbkOG3TTFOpUoc+Dlv2+H/XhgDNnvd9w99oa0o+tHG4712L6MbcbCSGTC cyHw== X-Gm-Message-State: AC+VfDzjybgt8hgws08cjwSKrpMChOZalnvAglw3FG25nio7/D0LSkzU sq+UUHP7/ln6iV8IrnSFsup7WN0av6MvdVL3hSgfEg== X-Google-Smtp-Source: ACHHUZ7dU4FP8RJYfH/wGGyP0/Mv9Rcpl+xErc1cu898RQRbWJdgnaqrpLHS7UP3FK+sA2D4dTHAJQ== X-Received: by 2002:a05:6902:1248:b0:b8d:a9e9:be74 with SMTP id t8-20020a056902124800b00b8da9e9be74mr9547805ybu.38.1682799613663; Sat, 29 Apr 2023 13:20:13 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id t124-20020a0dd182000000b0054f9dc9c7f2sm5463127ywd.44.2023.04.29.13.20.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:13 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 08/26] btrfs-progs: update btrfs_set_item_key_safe to match kernel definition Date: Sat, 29 Apr 2023 16:19:39 -0400 Message-Id: <83d99b43f200e65bd4ff9719da3128ca21a14424.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In the kernel we just pass the btrfs_fs_info, and we const'ify the new_key. Update the btrfs-progs definition to make syncing ctree.c easier. Signed-off-by: Josef Bacik --- kernel-shared/ctree.c | 12 +++++------- kernel-shared/ctree.h | 5 +++-- kernel-shared/file-item.c | 3 +-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 2e7b6c9a..94aa45a3 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -1355,8 +1355,9 @@ void btrfs_fixup_low_keys( struct btrfs_path *path, struct btrfs_disk_key *key, * This function isn't completely safe. It's the caller's responsibility * that the new key won't break the order */ -int btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path, - struct btrfs_key *new_key) +void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, + const struct btrfs_key *new_key) { struct btrfs_disk_key disk_key; struct extent_buffer *eb; @@ -1366,13 +1367,11 @@ int btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path, slot = path->slots[0]; if (slot > 0) { btrfs_item_key(eb, &disk_key, slot - 1); - if (btrfs_comp_keys(&disk_key, new_key) >= 0) - return -1; + BUG_ON(btrfs_comp_keys(&disk_key, new_key) >= 0); } if (slot < btrfs_header_nritems(eb) - 1) { btrfs_item_key(eb, &disk_key, slot + 1); - if (btrfs_comp_keys(&disk_key, new_key) <= 0) - return -1; + BUG_ON(btrfs_comp_keys(&disk_key, new_key) <= 0); } btrfs_cpu_key_to_disk(&disk_key, new_key); @@ -1380,7 +1379,6 @@ int btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path, btrfs_mark_buffer_dirty(eb); if (slot == 0) btrfs_fixup_low_keys(path, &disk_key, 1); - return 0; } /* diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index d5797d09..e54d3bc3 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -1055,8 +1055,9 @@ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_leaf_free_space(struct extent_buffer *leaf); void btrfs_fixup_low_keys(struct btrfs_path *path, struct btrfs_disk_key *key, int level); -int btrfs_set_item_key_safe(struct btrfs_root *root, struct btrfs_path *path, - struct btrfs_key *new_key); +void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, + const struct btrfs_key *new_key); void btrfs_set_item_key_unsafe(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_key *new_key); diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c index 9f8a3296..87f80bfe 100644 --- a/kernel-shared/file-item.c +++ b/kernel-shared/file-item.c @@ -389,8 +389,7 @@ static noinline int truncate_one_csum(struct btrfs_root *root, BUG_ON(ret); key->offset = end_byte; - ret = btrfs_set_item_key_safe(root, path, key); - BUG_ON(ret); + btrfs_set_item_key_safe(root->fs_info, path, key); } else { BUG(); } From patchwork Sat Apr 29 20:19:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227086 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2A24BC7EE24 for ; Sat, 29 Apr 2023 20:20:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230253AbjD2UUY (ORCPT ); Sat, 29 Apr 2023 16:20:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45388 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229532AbjD2UUV (ORCPT ); Sat, 29 Apr 2023 16:20:21 -0400 Received: from mail-yw1-x1131.google.com (mail-yw1-x1131.google.com [IPv6:2607:f8b0:4864:20::1131]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EAA372D48 for ; Sat, 29 Apr 2023 13:20:15 -0700 (PDT) Received: by mail-yw1-x1131.google.com with SMTP id 00721157ae682-54fc6949475so16190377b3.3 for ; Sat, 29 Apr 2023 13:20:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799615; x=1685391615; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=4TCKTtVCWVNpQUsqkDAwp0VyD518nvd6nSe8DMgbRa0=; b=eV+XjpPZfhSfqZeMPKC0w7hMzbPQfDORIYo3JUC0fHeDUOabgSFR3/EW1BzNOaeVqM I4UjozVW1RgqWNnFH8Bi9f6pkZchWgGPAgVYXSSmqVJxyNIYXhJ5Mmu4dUgaVwI91dCg Fio7IJraZWScbO8Fw7iHUMAuXz5yuAhSIP15I6b8xhhlgT9xAychLnVAE6AzR4oUo0rz wxnRZMsB9O2m2fKy4Hv0MsGHLoxhpySNVBh1nUefZ0mNNry2n9Kpc6d/z7yNlRwgr1Ha E5DgZ3YigJEUifxIQXktVq6q4cHus34RAAjPnNKUcaTDJSLZdTmeHV/3nVAMVl9oVwPq ZXdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799615; x=1685391615; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4TCKTtVCWVNpQUsqkDAwp0VyD518nvd6nSe8DMgbRa0=; b=DaHo02XsfrBQ7KrYwQJ3Y0hk8mzBF9qH9yT5a4g7u05sxBZiHxwSuyOwcgnrAByv2k FrtlIvK42fLf0r0Tk9Ev3LPbJUhxhMXMEFoDmh+VzRLnTnVJ27CYbrR8cyTm46I2sCSd z/eqDky2AV+CuY47VRFRngyUFmtHzD2f3/wBSUhYJ/0Vgm0WqY6xhG+w02b+yY7kUkIH C9t0YZOXMKr3EHKmNl0K4Cx6pTFDHeED/t+74aRxo/Tg+fN6cdJyPpj6NYWoXc9lbwVu aoLMaW+fAgRFNANZqhxv8ujJFw9rQAlLwLSctnI6TwuoFixO8mq48207sqwGXnenjYwh xe1Q== X-Gm-Message-State: AC+VfDwqZy2Qx4HNhzRPs3/plMBczqDSHjXSshByCKLJCqPIZqE+MD5B b1vm+zNpQs8/y9a1A+UEaELW6Gp1ax4hsh9VSa9vNA== X-Google-Smtp-Source: ACHHUZ4dkuUEnB86ieas55WKLEuzhNNT2Wam9H0dGMp8QgieGVb4Cbhi2qh8SKJw5SASYAVEukzM7w== X-Received: by 2002:a0d:d946:0:b0:54f:9e41:df5a with SMTP id b67-20020a0dd946000000b0054f9e41df5amr8676214ywe.15.1682799614737; Sat, 29 Apr 2023 13:20:14 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id n207-20020a0dcbd8000000b00555df877a4csm6221969ywd.102.2023.04.29.13.20.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:14 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 09/26] btrfs-progs: update btrfs_print_leaf to match the kernel definition Date: Sat, 29 Apr 2023 16:19:40 -0400 Message-Id: <58cd7cf8ddd1bb5616a7405e06a6ed96736cfe14.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In the kernel we have btrfs_print_leaf(eb) instead of btrfs_print_leaf(eb, mode). In fact in all of the kernel-shared sources we're just using the default mode. Fix this to have a __btrfs_print_leaf() which handles the mode for the user space utilities that want the different behavior, and then change btrfs_print_leaf() to just be the normal default style. Signed-off-by: Josef Bacik --- cmds/inspect-dump-tree.c | 2 +- kernel-shared/ctree.c | 16 ++++++++-------- kernel-shared/extent-tree.c | 8 ++++---- kernel-shared/print-tree.c | 4 ++-- kernel-shared/print-tree.h | 7 ++++++- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/cmds/inspect-dump-tree.c b/cmds/inspect-dump-tree.c index 7c524b04..5385208d 100644 --- a/cmds/inspect-dump-tree.c +++ b/cmds/inspect-dump-tree.c @@ -52,7 +52,7 @@ static void print_extents(struct extent_buffer *eb) return; if (btrfs_is_leaf(eb)) { - btrfs_print_leaf(eb, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(eb); return; } diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 94aa45a3..a23128ee 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -2418,7 +2418,7 @@ split: ret = 0; if (btrfs_leaf_free_space(leaf) < 0) { - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); BUG(); } kfree(buf); @@ -2510,7 +2510,7 @@ int btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) ret = 0; if (btrfs_leaf_free_space(leaf) < 0) { - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); BUG(); } return ret; @@ -2534,7 +2534,7 @@ int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, data_end = leaf_data_end(leaf); if (btrfs_leaf_free_space(leaf) < data_size) { - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); BUG(); } slot = path->slots[0]; @@ -2542,7 +2542,7 @@ int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, BUG_ON(slot < 0); if (slot >= nritems) { - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); printk("slot %d too large, nritems %u\n", slot, nritems); BUG_ON(1); } @@ -2569,7 +2569,7 @@ int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, ret = 0; if (btrfs_leaf_free_space(leaf) < 0) { - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); BUG(); } return ret; @@ -2617,7 +2617,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, data_end = leaf_data_end(leaf); if (btrfs_leaf_free_space(leaf) < total_size) { - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); printk("not enough freespace need %u have %d\n", total_size, btrfs_leaf_free_space(leaf)); BUG(); @@ -2630,7 +2630,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, unsigned int old_data = btrfs_item_data_end(leaf, slot); if (old_data < data_end) { - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); printk("slot %d old_data %u data_end %u\n", slot, old_data, data_end); BUG_ON(1); @@ -2676,7 +2676,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, } if (btrfs_leaf_free_space(leaf) < 0) { - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); BUG(); } diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index bbce9587..fa83d152 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -937,7 +937,7 @@ again: printf("Size is %u, needs to be %u, slot %d\n", (unsigned)item_size, (unsigned)sizeof(*ei), path->slots[0]); - btrfs_print_leaf(leaf, BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(leaf); return -EINVAL; } @@ -1428,7 +1428,7 @@ again: } if (ret != 0) { - btrfs_print_leaf(path->nodes[0], BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(path->nodes[0]); printk("failed to find block number %llu\n", (unsigned long long)bytenr); BUG(); @@ -2034,7 +2034,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, printk(KERN_ERR "umm, got %d back from search" ", was looking for %llu\n", ret, (unsigned long long)bytenr); - btrfs_print_leaf(path->nodes[0], BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(path->nodes[0]); } BUG_ON(ret); extent_slot = path->slots[0]; @@ -2048,7 +2048,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, (unsigned long long)owner_objectid, (unsigned long long)owner_offset); printf("path->slots[0]: %d path->nodes[0]:\n", path->slots[0]); - btrfs_print_leaf(path->nodes[0], BTRFS_PRINT_TREE_DEFAULT); + btrfs_print_leaf(path->nodes[0]); ret = -EIO; goto fail; } diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c index 594c524f..ff2a8097 100644 --- a/kernel-shared/print-tree.c +++ b/kernel-shared/print-tree.c @@ -1294,7 +1294,7 @@ static void print_header_info(struct extent_buffer *eb, unsigned int mode) fflush(stdout); } -void btrfs_print_leaf(struct extent_buffer *eb, unsigned int mode) +void __btrfs_print_leaf(struct extent_buffer *eb, unsigned int mode) { struct btrfs_disk_key disk_key; u32 leaf_data_size = BTRFS_LEAF_DATA_SIZE(eb->fs_info); @@ -1607,7 +1607,7 @@ void btrfs_print_tree(struct extent_buffer *eb, unsigned int mode) nr = btrfs_header_nritems(eb); if (btrfs_is_leaf(eb)) { - btrfs_print_leaf(eb, mode); + __btrfs_print_leaf(eb, mode); return; } /* We are crossing eb boundary, this node must be corrupted */ diff --git a/kernel-shared/print-tree.h b/kernel-shared/print-tree.h index 80fb6ef7..c1e75d1e 100644 --- a/kernel-shared/print-tree.h +++ b/kernel-shared/print-tree.h @@ -34,7 +34,12 @@ enum { }; void btrfs_print_tree(struct extent_buffer *eb, unsigned int mode); -void btrfs_print_leaf(struct extent_buffer *eb, unsigned int mode); +void __btrfs_print_leaf(struct extent_buffer *eb, unsigned int mode); + +static inline void btrfs_print_leaf(struct extent_buffer *eb) +{ + __btrfs_print_leaf(eb, BTRFS_PRINT_TREE_DEFAULT); +} void btrfs_print_key(struct btrfs_disk_key *disk_key); void print_chunk_item(struct extent_buffer *eb, struct btrfs_chunk *chunk); From patchwork Sat Apr 29 20:19:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227088 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 35B43C7EE23 for ; Sat, 29 Apr 2023 20:20:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230266AbjD2UUY (ORCPT ); Sat, 29 Apr 2023 16:20:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45424 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229498AbjD2UUW (ORCPT ); Sat, 29 Apr 2023 16:20:22 -0400 Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 21FDFE7D for ; Sat, 29 Apr 2023 13:20:17 -0700 (PDT) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-54fe08015c1so18008307b3.3 for ; Sat, 29 Apr 2023 13:20:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799616; x=1685391616; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=zxCB5jzJZfUqDLthb+eGYPVJhFCz/EAHRvt4mRIkTZ4=; b=IKE++ve3PkkKV7Pw6niKzsMsMfNkKarO2fBVRFYnF6oqTKk0eOwiUWBfTt2AYdzEhM rs/coDa8WGwTB5zmO2qxzEqC4g5WNer3EvjKEVlh6Q5x+y8355SnyVkSW7mtv9tQVOKV X9bbqVlEJ6Y353WIn+C0b6aRx8A0j3aLO3o67+Ilj9Vb/yFNPsk92vHfDJvc7T7dOedT 4kyYG8ZJl5CtjUO88j7bbEDqFjA12e169fDThA5GlG3vC0BZbQTE6eQaZjLlEP8s0r8C 2IfqXtQ9nUe4ChMGqmBOJaOypVJ7ZwVyY6oyCZPc7vEbDieXm9aev+dEiKMlnZEDrlOO CEqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799616; x=1685391616; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zxCB5jzJZfUqDLthb+eGYPVJhFCz/EAHRvt4mRIkTZ4=; b=AWUvKuAanNlbo2A/Uzdrgte8UXv4AgNQ6Z+8tVmfdencalI1m4uqED2MVfuAo6iPdq kw9TAZcE3LGSMZVLKbBgGikDTarI5OHO8FrQ+ERMbWde6jR7OP6IEh+hDuwLeLobFmZH N0gnIo4dQDbbVfRJ9/kDVm4+TZ0gJQPOWeROGZa2sRfQhHLP2uoZa8PagAo+VY96RyiL 1pk1GkUHkxg6CUPUzolrxVcJPvY0R1MTaFs6LILMnXpcmr2uFA0qs9AusMJZBQadkuLD LxQ4PFWUVHwIDu9iNPe4i0FaGVMZNs8hMRWvxRBf8rlBmjGq0FYBOcwOunhyGzKG2Nv9 qnkg== X-Gm-Message-State: AC+VfDz102mOU7MGp2vOiLIauVBB8Ul69AKoS/cL7KNdqpfhYxTanyI1 T53UdsoPXPSlVeJuO8gd6FHCmwnCVuOKRFIE7npvAg== X-Google-Smtp-Source: ACHHUZ7PTAyapVGLWU4Kg8AH6mTgd9KN9MYlyiWsJ4zfRwcNaNWNBQlKqtV25gAyARskaJ/fPZ3Cpg== X-Received: by 2002:a0d:f5c7:0:b0:552:9689:72ed with SMTP id e190-20020a0df5c7000000b00552968972edmr6162331ywf.30.1682799615780; Sat, 29 Apr 2023 13:20:15 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id e133-20020a81698b000000b00545a08184e9sm6265352ywc.121.2023.04.29.13.20.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:15 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 10/26] btrfs-progs: update btrfs_truncate_item to match the kernel definition Date: Sat, 29 Apr 2023 16:19:41 -0400 Message-Id: <5e7702db922b116e91f7481526e60245913cb5c0.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This is void in the kernel, and this makes sense in btrfs-progs as it stands currently as it doesn't actually return an error if there's a problem, it simply BUG()'s. Update this to be a void and update the callers to make it easier to sync ctree.c. Signed-off-by: Josef Bacik --- kernel-shared/ctree.c | 7 ++----- kernel-shared/ctree.h | 2 +- kernel-shared/extent-tree.c | 4 +--- kernel-shared/file-item.c | 7 ++----- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index a23128ee..d78a3258 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -2425,9 +2425,8 @@ split: return ret; } -int btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) +void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) { - int ret = 0; int slot; struct extent_buffer *leaf; u32 nritems; @@ -2442,7 +2441,7 @@ int btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) old_size = btrfs_item_size(leaf, slot); if (old_size == new_size) - return 0; + return; nritems = btrfs_header_nritems(leaf); data_end = leaf_data_end(leaf); @@ -2508,12 +2507,10 @@ int btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) btrfs_set_item_size(leaf, slot, new_size); btrfs_mark_buffer_dirty(leaf); - ret = 0; if (btrfs_leaf_free_space(leaf) < 0) { btrfs_print_leaf(leaf); BUG(); } - return ret; } int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index e54d3bc3..18562f3b 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -969,7 +969,7 @@ int btrfs_create_root(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 objectid); int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, u32 data_size); -int btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end); +void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end); int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index fa83d152..718a4fc9 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -1129,7 +1129,6 @@ static int update_inline_extent_backref(struct btrfs_trans_handle *trans, u32 item_size; int size; int type; - int ret; u64 refs; leaf = path->nodes[0]; @@ -1169,8 +1168,7 @@ static int update_inline_extent_backref(struct btrfs_trans_handle *trans, memmove_extent_buffer(leaf, ptr, ptr + size, end - ptr - size); item_size -= size; - ret = btrfs_truncate_item(path, item_size, 1); - BUG_ON(ret); + btrfs_truncate_item(path, item_size, 1); } btrfs_mark_buffer_dirty(leaf); return 0; diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c index 87f80bfe..6e0f7381 100644 --- a/kernel-shared/file-item.c +++ b/kernel-shared/file-item.c @@ -356,7 +356,6 @@ static noinline int truncate_one_csum(struct btrfs_root *root, u64 csum_end; u64 end_byte = bytenr + len; u32 blocksize = root->fs_info->sectorsize; - int ret; leaf = path->nodes[0]; csum_end = btrfs_item_size(leaf, path->slots[0]) / csum_size; @@ -372,8 +371,7 @@ static noinline int truncate_one_csum(struct btrfs_root *root, */ u32 new_size = (bytenr - key->offset) / blocksize; new_size *= csum_size; - ret = btrfs_truncate_item(path, new_size, 1); - BUG_ON(ret); + btrfs_truncate_item(path, new_size, 1); } else if (key->offset >= bytenr && csum_end > end_byte && end_byte > key->offset) { /* @@ -385,8 +383,7 @@ static noinline int truncate_one_csum(struct btrfs_root *root, u32 new_size = (csum_end - end_byte) / blocksize; new_size *= csum_size; - ret = btrfs_truncate_item(path, new_size, 0); - BUG_ON(ret); + btrfs_truncate_item(path, new_size, 0); key->offset = end_byte; btrfs_set_item_key_safe(root->fs_info, path, key); From patchwork Sat Apr 29 20:19:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227090 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CFB4EC77B7C for ; Sat, 29 Apr 2023 20:20:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230286AbjD2UUZ (ORCPT ); Sat, 29 Apr 2023 16:20:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45388 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230154AbjD2UUW (ORCPT ); Sat, 29 Apr 2023 16:20:22 -0400 Received: from mail-yw1-x112a.google.com (mail-yw1-x112a.google.com [IPv6:2607:f8b0:4864:20::112a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8025EE79 for ; Sat, 29 Apr 2023 13:20:17 -0700 (PDT) Received: by mail-yw1-x112a.google.com with SMTP id 00721157ae682-552a6357d02so16103547b3.3 for ; Sat, 29 Apr 2023 13:20:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799617; x=1685391617; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=+wC886aHfGuvdaCyaZNXNQMxkeCfR8OL3zOMiZCs4JM=; b=cJxrFrFRt1U+58iqqFaIj/u7vmLPqGd4UX+LyIaaHVfgoyT7rGy0omn2VZ/Ad/E4P9 W5TK2MRcSVb51NaefDKzQbfqHI5XOPpRHIBSi8kIsdI9etlwgyBioNu5Obi0v7SFlGFG hD9WwJW3O0+JwH90FNc0ujsvb6B2XJfRWczlCi0Je57iHAoe/illYKAOcVrueozwApgg VuVmD1P/q7F6hEqK1yS1Pu82KCo3kC0pfc1VmzNSIUUhADUkqTIQD2lJHd+SV8BbKzoi 97/bq7AVZJ5SzYzdqm7CvZDaO52qmPxLV0mxMtDTokwkp+c4Dp0o9phgAXXqgH1NQ8WV JUuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799617; x=1685391617; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+wC886aHfGuvdaCyaZNXNQMxkeCfR8OL3zOMiZCs4JM=; b=DnJLrsQihRHT624B8g5ppZcHoSG3yae5TSFiJGbIYEC61CaPoEZq2jYdfWVX9TdkdM cKQcv3qDvzbc8QIwPy4V5GoYOtPyjrDpQ9eIEPeNxZWsh40pJG2k9eY744mxVmge/4Pv /J2qLjFH8Xirt+hp5oWpI63lS6GS7Gsi3Bj6E9VD5NTp2DS56/WbFmR/RjgV3C2DnF5n DvTiQhfboOpAe/jQPzoipE8+7AWsNVAtzP/TTGsnuqLU8kQ0X4uk32yKvwQJ04HZBD+G 3tlTKMr9363bw06f/REnM9nCoFcnEesakB947j1+TAGSjFfdfzvE709HWQuYygon9Qnl HRew== X-Gm-Message-State: AC+VfDwUACExOzuEfh8D26+Rpna1MBjqHQ7ht9MILQJiEIoVFdNaP7cU ZPBFoSpoIzXNiNCx7ijlNgyJ2nK0n+mlHtuCitjgCA== X-Google-Smtp-Source: ACHHUZ66N9a5OiQ6W/Sdo4r5ciynuNdnra3N2V9u1aexSJbMWglGIZ8GSCtNcGURSzfcJCfZHbCYKQ== X-Received: by 2002:a81:494f:0:b0:556:300c:d653 with SMTP id w76-20020a81494f000000b00556300cd653mr7260690ywa.40.1682799616862; Sat, 29 Apr 2023 13:20:16 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id h190-20020a0dc5c7000000b00545a08184f8sm6307901ywd.136.2023.04.29.13.20.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:16 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 11/26] btrfs-progs: update btrfs_extend_item to match the kernel definition Date: Sat, 29 Apr 2023 16:19:42 -0400 Message-Id: <1b63fa6b0e4b05bc514f122af669ec6e34198030.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Similar to btrfs_truncate_item(), this is void in the kernel as the failure case is simply BUG_ON(). Additionally there is no root parameter as it's not used in the function at all. Make these changes and update the callers. Signed-off-by: Josef Bacik --- kernel-shared/ctree.c | 8 ++------ kernel-shared/ctree.h | 3 +-- kernel-shared/dir-item.c | 4 ++-- kernel-shared/extent-tree.c | 4 +--- kernel-shared/file-item.c | 3 +-- kernel-shared/inode-item.c | 5 ++--- tune/change-csum.c | 3 +-- 7 files changed, 10 insertions(+), 20 deletions(-) diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index d78a3258..97164cb8 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -2513,10 +2513,8 @@ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) } } -int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, - u32 data_size) +void btrfs_extend_item(struct btrfs_path *path, u32 data_size) { - int ret = 0; int slot; struct extent_buffer *leaf; u32 nritems; @@ -2564,12 +2562,10 @@ int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, btrfs_set_item_size(leaf, slot, old_size + data_size); btrfs_mark_buffer_dirty(leaf); - ret = 0; if (btrfs_leaf_free_space(leaf) < 0) { btrfs_print_leaf(leaf); BUG(); } - return ret; } /* @@ -3218,7 +3214,7 @@ int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type, * ret == -EEXIST case, An item with that type already exists. * Extend the item and store the new subvol_id at the end. */ - btrfs_extend_item(uuid_root, path, sizeof(subvol_id_le)); + btrfs_extend_item(path, sizeof(subvol_id_le)); eb = path->nodes[0]; slot = path->slots[0]; offset = btrfs_item_ptr_offset(eb, slot); diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 18562f3b..b3e73e35 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -967,8 +967,7 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, struct extent_buffer **cow_ret, u64 new_root_objectid); int btrfs_create_root(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 objectid); -int btrfs_extend_item(struct btrfs_root *root, struct btrfs_path *path, - u32 data_size); +void btrfs_extend_item(struct btrfs_path *path, u32 data_size); void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end); int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, diff --git a/kernel-shared/dir-item.c b/kernel-shared/dir-item.c index ef49441c..def7ea81 100644 --- a/kernel-shared/dir-item.c +++ b/kernel-shared/dir-item.c @@ -40,8 +40,8 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle di = btrfs_match_dir_item_name(root, path, name, name_len); if (di) return ERR_PTR(-EEXIST); - ret = btrfs_extend_item(root, path, data_size); - WARN_ON(ret > 0); + btrfs_extend_item(path, data_size); + ret = 0; } if (ret < 0) return ERR_PTR(ret); diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index 718a4fc9..ba853110 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -1040,7 +1040,6 @@ static int setup_inline_extent_backref(struct btrfs_root *root, u64 refs; int size; int type; - int ret; leaf = path->nodes[0]; ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); @@ -1049,8 +1048,7 @@ static int setup_inline_extent_backref(struct btrfs_root *root, type = extent_ref_type(parent, owner); size = btrfs_extent_inline_ref_size(type); - ret = btrfs_extend_item(root, path, size); - BUG_ON(ret); + btrfs_extend_item(path, size); ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item); refs = btrfs_extent_refs(leaf, ei); diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c index 6e0f7381..fd6756e9 100644 --- a/kernel-shared/file-item.c +++ b/kernel-shared/file-item.c @@ -293,8 +293,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, diff = diff - btrfs_item_size(leaf, path->slots[0]); if (diff != csum_size) goto insert; - ret = btrfs_extend_item(root, path, diff); - BUG_ON(ret); + btrfs_extend_item(path, diff); goto csum; } diff --git a/kernel-shared/inode-item.c b/kernel-shared/inode-item.c index 891ae40a..d0705267 100644 --- a/kernel-shared/inode-item.c +++ b/kernel-shared/inode-item.c @@ -78,8 +78,7 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans, goto out; old_size = btrfs_item_size(path->nodes[0], path->slots[0]); - ret = btrfs_extend_item(root, path, ins_len); - BUG_ON(ret); + btrfs_extend_item(path, ins_len); ref = btrfs_item_ptr(path->nodes[0], path->slots[0], struct btrfs_inode_ref); ref = (struct btrfs_inode_ref *)((unsigned long)ref + old_size); @@ -352,7 +351,7 @@ int btrfs_insert_inode_extref(struct btrfs_trans_handle *trans, name, name_len, NULL)) goto out; - btrfs_extend_item(root, path, ins_len); + btrfs_extend_item(path, ins_len); ret = 0; } diff --git a/tune/change-csum.c b/tune/change-csum.c index a1131686..49624c6f 100644 --- a/tune/change-csum.c +++ b/tune/change-csum.c @@ -232,8 +232,7 @@ static int csum_file_block(struct btrfs_trans_handle *trans, diff = diff - btrfs_item_size(leaf, path->slots[0]); if (diff != csum_size) goto insert; - ret = btrfs_extend_item(csum_root, path, diff); - BUG_ON(ret); + btrfs_extend_item(path, diff); goto csum; } From patchwork Sat Apr 29 20:19:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227091 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF7D3C77B60 for ; Sat, 29 Apr 2023 20:20:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230304AbjD2UU1 (ORCPT ); Sat, 29 Apr 2023 16:20:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45390 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230233AbjD2UUW (ORCPT ); Sat, 29 Apr 2023 16:20:22 -0400 Received: from mail-yb1-xb2d.google.com (mail-yb1-xb2d.google.com [IPv6:2607:f8b0:4864:20::b2d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 61B10E6C for ; Sat, 29 Apr 2023 13:20:19 -0700 (PDT) Received: by mail-yb1-xb2d.google.com with SMTP id 3f1490d57ef6-b9963a72fbfso1617069276.3 for ; Sat, 29 Apr 2023 13:20:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799618; x=1685391618; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Dm8q7SUBUDB21B7eyxwEHX1UIP4GtnLiwtYMGR3+Xfg=; b=meNlIk0upwOzdosFvn4XPqLrGFaSADKt+lwGwrnqcJKWb4Rys2LnN5QRj+wBv/ZwqZ 5gSGke5BTwYdn5G2bFnZR/0Wa0GgtiSCNSrNKw44HDOu48b/T8JOEznhjQXIMJgsz7If xI69YiPPoscDtTkGhYV4/MfBSuC9AWhVB0T2nnMSJlBWvDWjmohq7U9KqqeS721oyGyO Ul2OBTAd4aZyaNZMuhZCnCA8uCPi0DLzhE51Dr3l+n1Jafgow+8Jbpj/F9RA6kOn7/yz H0qYqdhzeg8Luia57A/InTal6xGiCpUSds14X8R2UiR6TRB0WxcWaXcP64MGvgUz2EaJ E69w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799618; x=1685391618; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Dm8q7SUBUDB21B7eyxwEHX1UIP4GtnLiwtYMGR3+Xfg=; b=l66voi4HWZcQI+ZFrZvCfkNuDw2HBgATHtjjYvLy7b8VKbBhS+NdU1yF45zI/a+hHa 6RiG0GipKtTnjPJrKuslCNcS2rsvY/p6Gl3wQpyZhPkYrSknbafuJ6YVV3+gpXz30MYN Ez1eSPXiMkM8ooii/z5LsnNMYyD039mbs8tM9lePEHvTL06shkQSaSisiEfD3o5GIHcA Kzs8V3r6GKIoxOpTJ8F6k4dEmEei+EXvxw1kQSceRqoj5z2325jxN+lmMPij3PQ1ji/4 92DLiLdFtS4AAhfq3teJMAqNbT6oebKx7yJmf4nXy9N9NAd/Y7AX4uH8uqgZ3jqoKweY CerA== X-Gm-Message-State: AC+VfDxO+LpTqOR3W46K7aJ5Pd77D5EmY0nSQqtqczdD9FYayWngTtw3 y/d8zJl0R8zmlUkgRs+VDkhzEviA5usdFLEWfoh5EA== X-Google-Smtp-Source: ACHHUZ78W8cOS+ttg4kB+e9g6v4XfX2b0knS39mVQ42iIg6cSHNzGy5Ztlxel3zOd9PRw6D5+A/zhQ== X-Received: by 2002:a25:3497:0:b0:b9d:c27c:344a with SMTP id b145-20020a253497000000b00b9dc27c344amr1144415yba.16.1682799618340; Sat, 29 Apr 2023 13:20:18 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id i3-20020a258b03000000b00b8c08669033sm5807746ybl.40.2023.04.29.13.20.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:17 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 12/26] btrfs-progs: sync memcpy_extent_buffer from the kernel Date: Sat, 29 Apr 2023 16:19:43 -0400 Message-Id: <1d11e9325887ccea1978e6c34868539b373fd252.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org We use this in ctree.c in the kernel, so sync this helper into btrfs-progs to make sync'ing ctree.c easier. Signed-off-by: Josef Bacik --- kernel-shared/extent_io.c | 6 ++++++ kernel-shared/extent_io.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/kernel-shared/extent_io.c b/kernel-shared/extent_io.c index e38bb1ed..fbf45e9d 100644 --- a/kernel-shared/extent_io.c +++ b/kernel-shared/extent_io.c @@ -630,6 +630,12 @@ void copy_extent_buffer_full(const struct extent_buffer *dst, copy_extent_buffer(dst, src, 0, 0, src->len); } +void memcpy_extent_buffer(const struct extent_buffer *dst, unsigned long dst_offset, + unsigned long src_offset, unsigned long len) +{ + memcpy((void *)dst->data + dst_offset, dst->data + src_offset, len); +} + void memmove_extent_buffer(const struct extent_buffer *dst, unsigned long dst_offset, unsigned long src_offset, unsigned long len) { diff --git a/kernel-shared/extent_io.h b/kernel-shared/extent_io.h index f573a4e2..544d5710 100644 --- a/kernel-shared/extent_io.h +++ b/kernel-shared/extent_io.h @@ -118,6 +118,9 @@ void copy_extent_buffer(const struct extent_buffer *dst, unsigned long len); void copy_extent_buffer_full(const struct extent_buffer *dst, const struct extent_buffer *src); +void memcpy_extent_buffer(const struct extent_buffer *dst, + unsigned long dst_offset, unsigned long src_offset, + unsigned long len); void memmove_extent_buffer(const struct extent_buffer *dst, const unsigned long dst_offset, unsigned long src_offset, unsigned long len); From patchwork Sat Apr 29 20:19:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227089 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 49541C77B7F for ; Sat, 29 Apr 2023 20:20:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230289AbjD2UU0 (ORCPT ); Sat, 29 Apr 2023 16:20:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45456 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230248AbjD2UUX (ORCPT ); Sat, 29 Apr 2023 16:20:23 -0400 Received: from mail-yb1-xb2e.google.com (mail-yb1-xb2e.google.com [IPv6:2607:f8b0:4864:20::b2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BB50AE75 for ; Sat, 29 Apr 2023 13:20:20 -0700 (PDT) Received: by mail-yb1-xb2e.google.com with SMTP id 3f1490d57ef6-b9d87dffadfso839969276.3 for ; Sat, 29 Apr 2023 13:20:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799619; x=1685391619; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=dI+tMtCS1cRg9bCuzsW79Nd+86IuOy0IUtwtsNBAgDw=; b=Xb2nYgJ0eRaLiDzn1WsZc+ryRmoIM0T01I1vxhfgbdeCPykqCUoLDMmtvfYc5Ar+ba oLTYS3m2z+ONtmG8b0MhKRX2Uut/hmqITDdf47JKHJ3DoVMOqcWytRe1iIHlpHWx1HJa cftwPNayIgR34ojk5SEi+qYxXMD8CaZLOP0AFcEfXBdqc0En3jcfn2FqIU7yzLvfG5R9 4BKND+E0L+NUSuAH2JHqEn6wB9WgLEWXaZeh6sWyM6+HHWmlk/c52nrzI/vBDwCfaRAE FImLjOtUsPPomwQdhOIhwiY6MlWu3IFIHUZku4nIP269js8/+TyPo596PFgNjCc9VeON T8YA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799619; x=1685391619; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dI+tMtCS1cRg9bCuzsW79Nd+86IuOy0IUtwtsNBAgDw=; b=NOQYkt7T5XzEMuoCw1UfqD8zu52MsaZxkREasnTDkTuNXk5ABc363I8ClLZYJ6pR5j Pd5NxGw+B7l/Omxv8s4wMbJPjfW5EOlSJoXX+NqrmMob8s/XX61esK/qH7q43PZkBV9/ GXBNXwTtBEtiMDYinrXzaEbmrT1rDYznm3/IPYMNl1i7y2qEGkEgHdwcFisvcckdvpLJ +QQ60QMI995qxS/9UOEXxbA19iH/aUJw51mRkyIoNdCyXOcY2WhhQtJ7hMdLTnBUAym0 CPYR0qubIUatQZT0s434h9rnD5tPBFjP5808y8ZJVc/WzMAcEyoMmMm0PZJlVspBdmKU 8Tkw== X-Gm-Message-State: AC+VfDzF3QL0EUZKb4ZHCKfhfM4YiQ3Fu6Il3hbdIkB2Ah5CP1pPskam Nq/f8YMeJvQ+y/r2GQJvR3XwEnY3psF9J0nR/oUTZQ== X-Google-Smtp-Source: ACHHUZ7SVw7Q/pG6Z7CVCmtBDgxIhXcusC+9vjnKJ9EEM9ppkdhFpVFFuU0xHZpmzgnWhRFU5ZmzAg== X-Received: by 2002:a25:1fc1:0:b0:b8f:4e38:4560 with SMTP id f184-20020a251fc1000000b00b8f4e384560mr7574525ybf.2.1682799619454; Sat, 29 Apr 2023 13:20:19 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 62-20020a250c41000000b00b8f6ec5a955sm5861111ybm.49.2023.04.29.13.20.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:19 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 13/26] btrfs-progs: change how we check supported csum type Date: Sat, 29 Apr 2023 16:19:44 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In the kernel we have a basic btrfs_supported_super_csum() helper in disk-io.c to validate the csum type. Update progs to do the same thing that the kernel does and then drop the btrfs_super_num_csums() helper as it doesn't exist upstream and is no longer used. Signed-off-by: Josef Bacik --- kernel-shared/ctree.c | 5 ----- kernel-shared/ctree.h | 1 - kernel-shared/disk-io.c | 15 ++++++++++++++- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 97164cb8..0bd24646 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -65,11 +65,6 @@ const char *btrfs_super_csum_name(u16 csum_type) return btrfs_csums[csum_type].name; } -size_t btrfs_super_num_csums(void) -{ - return ARRAY_SIZE(btrfs_csums); -} - u16 btrfs_csum_type_size(u16 csum_type) { return btrfs_csums[csum_type].size; diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index b3e73e35..cab8f71b 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -1064,7 +1064,6 @@ void btrfs_set_item_key_unsafe(struct btrfs_root *root, u16 btrfs_super_csum_size(const struct btrfs_super_block *s); const char *btrfs_super_csum_name(u16 csum_type); u16 btrfs_csum_type_size(u16 csum_type); -size_t btrfs_super_num_csums(void); /* root-item.c */ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 3e0c3534..b7a98c4c 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -1713,6 +1713,19 @@ struct btrfs_root *open_ctree_fd(int fp, const char *path, u64 sb_bytenr, return info->fs_root; } +static bool btrfs_supported_super_csum(u16 csum_type) +{ + switch (csum_type) { + case BTRFS_CSUM_TYPE_CRC32: + case BTRFS_CSUM_TYPE_XXHASH: + case BTRFS_CSUM_TYPE_SHA256: + case BTRFS_CSUM_TYPE_BLAKE2: + return true; + default: + return false; + } +} + /* * Check if the super is valid: * - nodesize/sectorsize - minimum, maximum, alignment @@ -1737,7 +1750,7 @@ int btrfs_check_super(struct btrfs_super_block *sb, unsigned sbflags) } csum_type = btrfs_super_csum_type(sb); - if (csum_type >= btrfs_super_num_csums()) { + if (!btrfs_supported_super_csum(csum_type)) { error("unsupported checksum algorithm %u", csum_type); return -EIO; } From patchwork Sat Apr 29 20:19:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227097 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4A7A3C77B60 for ; Sat, 29 Apr 2023 20:20:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230335AbjD2UUc (ORCPT ); Sat, 29 Apr 2023 16:20:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45584 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230294AbjD2UU1 (ORCPT ); Sat, 29 Apr 2023 16:20:27 -0400 Received: from mail-yw1-x1135.google.com (mail-yw1-x1135.google.com [IPv6:2607:f8b0:4864:20::1135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 65FEC1BE4 for ; Sat, 29 Apr 2023 13:20:22 -0700 (PDT) Received: by mail-yw1-x1135.google.com with SMTP id 00721157ae682-54fb89e1666so11092357b3.3 for ; Sat, 29 Apr 2023 13:20:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799621; x=1685391621; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=76S56nP4DMda0iGG1/z6BB9douJHO42ye9WAN6HkNZk=; b=SQYWj9nCzs4zzGdxxm9b4Ea4np2hCEKG1tn0F1F6XUH+LT3rGSjozHa4kJHY99UD1n wTLeWdz9ldSLLbmW0kKQi1fYNyrJ+jieEg9ZJxW1Zsl+UhvFk+PjxIXjnUEZ/wPl8rtY Pa0HBtt9zEvtjD5xpeE9ExKv64j0VVEVD/7cAf5t/Xl85cu8DJSIcXbfUnN+WG5tZB6T Tq5t3orxrQdVmG8Y5YkwyWhp9DlpAxjdtGEU9qAPrVL/sgfYhjNAa3mfqbzyRVdIcbkE GfcH8yD/wWa0FEZANYd5pbKD0nBYFuDjLjFz+C0eXpSO9lp130DKbXiT6JgT7LPhGzbD GEug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799621; x=1685391621; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=76S56nP4DMda0iGG1/z6BB9douJHO42ye9WAN6HkNZk=; b=a0l6dV7vmUHOq+CoaI68rJfo+xn+fTxjnPRyjnsxw1soPevZgNPe04DS+cuqH42zgV qk8Lj6EK6D2DphHzTOVB5p+bNCuxhsVfgAb4TUYcIS6M2aaWvrCncXXp3aRAsOV0GApx WM4iyA1sPDDGleKojyAMAx8+N5xlEG/s7gxxKL7NVwBVifNU3uBrYOPsCiA9JlatXnnx ujfx8WS/O+zhPq20EnxWP6hu332q9kwurtsJLrzF3ds2sCRbMt4n3T/H2e7634PJhAKz z6TkE5624K47ms74f4+YWwp9mOgqW++jxRmUwSDQjFLG7DgWNSBBvfMFap1JWWFJH2P4 lkzw== X-Gm-Message-State: AC+VfDwYlcTRwtmX+sWPzpf0StxmNcdGTe6bQ0y6dN+eUvVIm/E/gEhK EMZpA3oBg263XI4uVHGM30k2HN0Q0suArDb4XnppXg== X-Google-Smtp-Source: ACHHUZ7/vrtMAKFvRgKgpjL9urRv1HcFKdGIJ8fmPK114PW4MBCDAf7l+NIvZ+IHx8otck/qQADskg== X-Received: by 2002:a0d:d1c3:0:b0:559:ea93:2d6d with SMTP id t186-20020a0dd1c3000000b00559ea932d6dmr2544782ywd.20.1682799620633; Sat, 29 Apr 2023 13:20:20 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id w3-20020a814903000000b00559d1eabc3csm734723ywa.79.2023.04.29.13.20.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:20 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 14/26] btrfs-progs: drop btrfs_init_path Date: Sat, 29 Apr 2023 16:19:45 -0400 Message-Id: <1eb283a636c767a73453e302f093f9f3c4d37c71.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This simply zero's out the path, and this is used everywhere we use a stack path. Drop this usage and simply init the path's to empty instead of using a function to do the memset. Signed-off-by: Josef Bacik --- check/clear-cache.c | 10 +--- check/main.c | 94 ++++++++++---------------------- check/mode-common.c | 35 ++++-------- check/mode-lowmem.c | 84 +++++++++------------------- check/qgroup-verify.c | 14 ++--- check/repair.c | 3 +- cmds/inspect-dump-tree.c | 3 +- cmds/inspect-tree-stats.c | 3 +- cmds/rescue-chunk-recover.c | 13 ++--- cmds/restore.c | 21 +++---- convert/main.c | 9 +-- convert/source-fs.c | 4 +- image/main.c | 13 ++--- kernel-shared/ctree.c | 5 -- kernel-shared/ctree.h | 1 - kernel-shared/extent-tree.c | 3 +- kernel-shared/file.c | 3 +- kernel-shared/free-space-cache.c | 4 +- kernel-shared/inode.c | 5 +- kernel-shared/print-tree.c | 3 +- kernel-shared/volumes.c | 6 +- mkfs/main.c | 15 ++--- mkfs/rootdir.c | 10 +--- quick-test.c | 6 +- tune/change-csum.c | 9 +-- tune/change-uuid.c | 6 +- 26 files changed, 116 insertions(+), 266 deletions(-) diff --git a/check/clear-cache.c b/check/clear-cache.c index 031379ce..17b9c93b 100644 --- a/check/clear-cache.c +++ b/check/clear-cache.c @@ -129,11 +129,9 @@ close_out: static int check_free_space_tree(struct btrfs_root *root) { struct btrfs_key key = { 0 }; - struct btrfs_path path; + struct btrfs_path path = {}; int ret = 0; - btrfs_init_path(&path); - while (1) { struct btrfs_block_group *bg; u64 cur_start = key.objectid; @@ -447,7 +445,6 @@ out: int truncate_free_ino_items(struct btrfs_root *root) { - struct btrfs_path path; struct btrfs_key key = { .objectid = BTRFS_FREE_INO_OBJECTID, .type = (u8)-1, .offset = (u64)-1 }; @@ -465,9 +462,9 @@ int truncate_free_ino_items(struct btrfs_root *root) struct btrfs_file_extent_item *fi; struct btrfs_root *csum_root; struct btrfs_key found_key; + struct btrfs_path path = {}; u8 found_type; - btrfs_init_path(&path); ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); if (ret < 0) { btrfs_abort_transaction(trans, ret); @@ -548,14 +545,13 @@ out: int clear_ino_cache_items(void) { int ret; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; key.objectid = BTRFS_FS_TREE_OBJECTID; key.type = BTRFS_ROOT_ITEM_KEY; key.offset = 0; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, gfs_info->tree_root, &key, &path, 0, 0); if (ret < 0) return ret; diff --git a/check/main.c b/check/main.c index a6485db5..5e4f5827 100644 --- a/check/main.c +++ b/check/main.c @@ -889,7 +889,7 @@ static void maybe_free_inode_rec(struct cache_tree *inode_cache, static int check_orphan_item(struct btrfs_root *root, u64 ino) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int ret; @@ -897,7 +897,6 @@ static int check_orphan_item(struct btrfs_root *root, u64 ino) key.type = BTRFS_ORPHAN_ITEM_KEY; key.offset = ino; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); btrfs_release_path(&path); if (ret > 0) @@ -1325,14 +1324,12 @@ static int leave_shared_node(struct btrfs_root *root, static int is_child_root(struct btrfs_root *root, u64 parent_root_id, u64 child_root_id) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct extent_buffer *leaf; int has_parent = 0; int ret; - btrfs_init_path(&path); - key.objectid = parent_root_id; key.type = BTRFS_ROOT_REF_KEY; key.offset = child_root_id; @@ -2107,7 +2104,7 @@ static int add_missing_dir_index(struct btrfs_root *root, struct inode_record *rec, struct inode_backref *backref) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_trans_handle *trans; struct btrfs_dir_item *dir_item; struct extent_buffer *leaf; @@ -2125,7 +2122,6 @@ static int add_missing_dir_index(struct btrfs_root *root, fprintf(stderr, "repairing missing dir index item for inode %llu\n", (unsigned long long)rec->ino); - btrfs_init_path(&path); key.objectid = backref->dir; key.type = BTRFS_DIR_INDEX_KEY; key.offset = backref->index; @@ -2169,7 +2165,7 @@ static int delete_dir_index(struct btrfs_root *root, { struct btrfs_trans_handle *trans; struct btrfs_dir_item *di; - struct btrfs_path path; + struct btrfs_path path = {}; int ret = 0; trans = btrfs_start_transaction(root, 1); @@ -2181,7 +2177,6 @@ static int delete_dir_index(struct btrfs_root *root, BTRFS_DIR_INDEX_KEY, (unsigned long long)backref->index, (unsigned long long)root->objectid); - btrfs_init_path(&path); di = btrfs_lookup_dir_index_item(trans, root, &path, backref->dir, backref->index, backref->name, backref->namelen, -1); @@ -2535,14 +2530,13 @@ out: */ static int find_normal_file_extent(struct btrfs_root *root, u64 ino) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_key found_key; struct btrfs_file_extent_item *fi; u8 type; int ret = 0; - btrfs_init_path(&path); key.objectid = ino; key.type = BTRFS_EXTENT_DATA_KEY; key.offset = 0; @@ -2755,11 +2749,9 @@ static int repair_mismatch_dir_hash(struct btrfs_trans_handle *trans, static int btrfs_delete_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key) { - struct btrfs_path path; + struct btrfs_path path = {}; int ret = 0; - btrfs_init_path(&path); - ret = btrfs_search_slot(trans, root, key, &path, -1, 1); if (ret) { if (ret > 0) @@ -2779,7 +2771,7 @@ static int find_file_extent_offset_by_bytenr(struct btrfs_root *root, u64 owner, u64 bytenr, u64 *offset_ret) { int ret = 0; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_key found_key; struct btrfs_file_extent_item *fi; @@ -2787,8 +2779,6 @@ static int find_file_extent_offset_by_bytenr(struct btrfs_root *root, u64 disk_bytenr; int slot; - btrfs_init_path(&path); - key.objectid = owner; key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; @@ -2960,7 +2950,7 @@ static int repair_inode_gen_original(struct btrfs_trans_handle *trans, static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) { struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; int ret = 0; /* unaligned extent recs always lead to csum missing error, clean it */ @@ -2993,7 +2983,6 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec) if (IS_ERR(trans)) return PTR_ERR(trans); - btrfs_init_path(&path); if (!ret && rec->errors & I_ERR_MISMATCH_DIR_HASH) ret = repair_mismatch_dir_hash(trans, root, rec); if (!ret && rec->errors & I_ERR_INVALID_IMODE) @@ -3539,7 +3528,7 @@ static int repair_btree(struct btrfs_root *root, struct cache_tree *corrupt_blocks) { struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_corrupt_block *corrupt; struct cache_extent *cache; struct btrfs_key key; @@ -3557,7 +3546,6 @@ static int repair_btree(struct btrfs_root *root, fprintf(stderr, "Error starting transaction: %m\n"); return ret; } - btrfs_init_path(&path); cache = first_cache_extent(corrupt_blocks); while (cache) { corrupt = container_of(cache, struct btrfs_corrupt_block, @@ -3625,7 +3613,7 @@ static int check_fs_root(struct btrfs_root *root, int wret; int level; u64 super_generation; - struct btrfs_path path; + struct btrfs_path path = {}; struct shared_node root_node; struct root_record *rec; struct btrfs_root_item *root_item = &root->root_item; @@ -3668,7 +3656,6 @@ static int check_fs_root(struct btrfs_root *root, rec->found_root_item = 1; } - btrfs_init_path(&path); memset(&root_node, 0, sizeof(root_node)); cache_tree_init(&root_node.root_cache); cache_tree_init(&root_node.inode_cache); @@ -3804,7 +3791,7 @@ skip_walking: static int check_fs_roots(struct cache_tree *root_cache) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct walk_control wc; struct extent_buffer *leaf, *tree_node; @@ -3822,7 +3809,6 @@ static int check_fs_roots(struct cache_tree *root_cache) reset_cached_block_groups(); memset(&wc, 0, sizeof(wc)); cache_tree_init(&wc.shared); - btrfs_init_path(&path); again: key.offset = 0; @@ -4212,7 +4198,7 @@ static int check_owner_ref(struct btrfs_root *root, struct tree_backref *back; struct btrfs_root *ref_root; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *parent; int level; int found = 0; @@ -4252,7 +4238,6 @@ static int check_owner_ref(struct btrfs_root *root, else btrfs_node_key_to_cpu(buf, &key, 0); - btrfs_init_path(&path); path.lowest_level = level + 1; ret = btrfs_search_slot(NULL, ref_root, &key, &path, 0, 0); if (ret < 0) @@ -4510,7 +4495,7 @@ static int try_to_fix_bad_block(struct btrfs_root *root, struct ulist *roots; struct ulist_node *node; struct btrfs_root *search_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct ulist_iterator iter; struct btrfs_key root_key, key; int ret; @@ -4523,7 +4508,6 @@ static int try_to_fix_bad_block(struct btrfs_root *root, if (ret) return -EIO; - btrfs_init_path(&path); ULIST_ITER_INIT(&iter); /* * If we found no roots referencing to this tree block, there is no @@ -5768,12 +5752,11 @@ static int check_extent_exists(struct btrfs_root *root, u64 bytenr, u64 num_bytes) { struct btrfs_root *extent_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_key key; int ret; - btrfs_init_path(&path); key.objectid = bytenr; key.type = BTRFS_EXTENT_ITEM_KEY; key.offset = (u64)-1; @@ -5909,7 +5892,7 @@ out: static int check_csum_root(struct btrfs_root *root) { - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_key key; u64 last_data_end = 0; @@ -5930,7 +5913,6 @@ static int check_csum_root(struct btrfs_root *root) return -ENOENT; } - btrfs_init_path(&path); key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; key.type = BTRFS_EXTENT_CSUM_KEY; key.offset = 0; @@ -7376,14 +7358,12 @@ static int delete_duplicate_records(struct btrfs_root *root, { struct btrfs_trans_handle *trans; LIST_HEAD(delete_list); - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_record *tmp, *good, *n; int nr_del = 0; int ret = 0, err; struct btrfs_key key; - btrfs_init_path(&path); - good = rec; /* Find the record that covers all of the duplicates. */ list_for_each_entry(tmp, &rec->dups, list) { @@ -7479,7 +7459,7 @@ static int __find_possible_backrefs(struct btrfs_root *root, u64 *bytes_ret) { int ret = 0; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_key found_key; struct btrfs_file_extent_item *fi; @@ -7487,8 +7467,6 @@ static int __find_possible_backrefs(struct btrfs_root *root, u64 backref_offset, disk_bytenr; int slot; - btrfs_init_path(&path); - key.objectid = owner; key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; @@ -7642,7 +7620,7 @@ static int fixup_extent_refs(struct cache_tree *extent_cache, { struct btrfs_trans_handle *trans = NULL; int ret; - struct btrfs_path path; + struct btrfs_path path = {}; struct cache_extent *cache; struct extent_backref *back, *tmp; int allocated = 0; @@ -7651,7 +7629,6 @@ static int fixup_extent_refs(struct cache_tree *extent_cache, if (rec->flag_block_full_backref) flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; - btrfs_init_path(&path); if (rec->refs != rec->extent_item_refs && !rec->metadata) { /* * Sometimes the backrefs themselves are so broken they don't @@ -7727,7 +7704,7 @@ static int fixup_extent_flags(struct extent_record *rec) { struct btrfs_trans_handle *trans; struct btrfs_root *root = btrfs_extent_root(gfs_info, rec->start); - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_extent_item *ei; struct btrfs_key key; u64 flags; @@ -7750,7 +7727,6 @@ retry: if (IS_ERR(trans)) return PTR_ERR(trans); - btrfs_init_path(&path); ret = btrfs_search_slot(trans, root, &key, &path, 0, 1); if (ret < 0) { btrfs_release_path(&path); @@ -7797,14 +7773,13 @@ static int prune_one_block(struct btrfs_trans_handle *trans, { struct btrfs_root *extent_root; int ret; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *eb; u64 found; int slot; int nritems; int level = corrupt->level + 1; - btrfs_init_path(&path); again: extent_root = btrfs_extent_root(gfs_info, corrupt->key.objectid); /* we want to stop at the parent to our busted block */ @@ -7983,7 +7958,7 @@ static int record_unaligned_extent_rec(struct extent_record *rec) static int repair_extent_item_generation(struct extent_record *rec) { struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_extent_item *ei; struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, @@ -8003,7 +7978,6 @@ static int repair_extent_item_generation(struct extent_record *rec) error_msg(ERROR_MSG_START_TRANS, "%m"); return ret; } - btrfs_init_path(&path); ret = btrfs_search_slot(trans, extent_root, &key, &path, 0, 1); /* Not possible */ if (ret == 0) @@ -8728,7 +8702,7 @@ static int check_block_groups(struct block_group_tree *bg_cache) static int parse_tree_roots(struct list_head *normal_trees, struct list_head *dropping_trees) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_key found_key; struct btrfs_root_item ri; @@ -8736,7 +8710,6 @@ static int parse_tree_roots(struct list_head *normal_trees, int slot; int ret = 0; - btrfs_init_path(&path); key.offset = 0; key.objectid = 0; key.type = BTRFS_ROOT_ITEM_KEY; @@ -8801,15 +8774,13 @@ out: */ static int check_dev_extents(void) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_root *dev_root = gfs_info->dev_root; int ret; u64 prev_devid = 0; u64 prev_dev_ext_end = 0; - btrfs_init_path(&path); - key.objectid = 1; key.type = BTRFS_DEV_EXTENT_KEY; key.offset = 0; @@ -9174,14 +9145,13 @@ static int btrfs_fsck_reinit_root(struct btrfs_trans_handle *trans, static int reset_block_groups(void) { struct btrfs_block_group *cache; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_chunk *chunk; struct btrfs_key key; int ret; u64 start; - btrfs_init_path(&path); key.objectid = 0; key.type = BTRFS_CHUNK_ITEM_KEY; key.offset = 0; @@ -9245,14 +9215,13 @@ static int reset_block_groups(void) static int reset_balance(struct btrfs_trans_handle *trans) { struct btrfs_root *root = gfs_info->tree_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_key key; int del_slot, del_nr = 0; int ret; int found = 0; - btrfs_init_path(&path); key.objectid = BTRFS_BALANCE_OBJECTID; key.type = BTRFS_BALANCE_ITEM_KEY; key.offset = 0; @@ -9351,12 +9320,11 @@ static int reinit_global_roots(struct btrfs_trans_handle *trans, u64 objectid) .type = BTRFS_ROOT_ITEM_KEY, .offset = 0, }; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_root *tree_root = gfs_info->tree_root; struct btrfs_root *root; int ret; - btrfs_init_path(&path); while (1) { ret = btrfs_search_slot(NULL, tree_root, &key, &path, 0, 0); if (ret) { @@ -9509,7 +9477,7 @@ again: static int delete_bad_item(struct btrfs_root *root, struct bad_item *bad) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_trans_handle *trans; struct btrfs_key key; int ret; @@ -9531,7 +9499,6 @@ static int delete_bad_item(struct btrfs_root *root, struct bad_item *bad) if (IS_ERR(trans)) return PTR_ERR(trans); - btrfs_init_path(&path); ret = btrfs_search_slot(trans, root, &bad->key, &path, -1, 1); if (ret) { if (ret > 0) @@ -9583,7 +9550,7 @@ static int build_roots_info_cache(void) int ret = 0; struct btrfs_key key; struct extent_buffer *leaf; - struct btrfs_path path; + struct btrfs_path path = {}; if (!roots_info_cache) { roots_info_cache = malloc(sizeof(*roots_info_cache)); @@ -9592,7 +9559,6 @@ static int build_roots_info_cache(void) cache_tree_init(roots_info_cache); } - btrfs_init_path(&path); key.objectid = 0; key.type = BTRFS_EXTENT_ITEM_KEY; key.offset = 0; @@ -9799,7 +9765,7 @@ static int maybe_repair_root_item(struct btrfs_path *path, */ static int repair_root_items(void) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct extent_buffer *leaf; struct btrfs_trans_handle *trans = NULL; @@ -9810,8 +9776,6 @@ static int repair_root_items(void) if (btrfs_fs_incompat(gfs_info, EXTENT_TREE_V2)) return 0; - btrfs_init_path(&path); - ret = build_roots_info_cache(); if (ret) goto out; diff --git a/check/mode-common.c b/check/mode-common.c index a38d2afc..a4644d63 100644 --- a/check/mode-common.c +++ b/check/mode-common.c @@ -52,10 +52,9 @@ static int check_prealloc_data_ref(u64 disk_bytenr, u64 offset = btrfs_extent_data_ref_offset(eb, dref); struct btrfs_root *root; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; int ret; - btrfs_init_path(&path); key.objectid = rootid; key.type = BTRFS_ROOT_ITEM_KEY; key.offset = (u64)-1; @@ -190,7 +189,7 @@ int check_prealloc_extent_written(u64 disk_bytenr, u64 num_bytes) { struct btrfs_root *extent_root = btrfs_extent_root(gfs_info, disk_bytenr); - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int ret; struct btrfs_extent_item *ei; @@ -202,7 +201,6 @@ int check_prealloc_extent_written(u64 disk_bytenr, u64 num_bytes) key.type = BTRFS_EXTENT_ITEM_KEY; key.offset = num_bytes; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0); if (ret > 0) { fprintf(stderr, @@ -303,7 +301,7 @@ int count_csum_range(u64 start, u64 len, u64 *found) { struct btrfs_root *csum_root = btrfs_csum_root(gfs_info, start); struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; int ret; size_t size; @@ -311,8 +309,6 @@ int count_csum_range(u64 start, u64 len, u64 *found) u64 csum_end; u16 csum_size = gfs_info->csum_size; - btrfs_init_path(&path); - key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; key.offset = start; key.type = BTRFS_EXTENT_CSUM_KEY; @@ -416,7 +412,6 @@ static int get_highest_inode(struct btrfs_trans_handle *trans, struct btrfs_key key, found_key; int ret; - btrfs_init_path(path); key.objectid = BTRFS_LAST_FREE_OBJECTID; key.offset = -1; key.type = BTRFS_INODE_ITEM_KEY; @@ -654,10 +649,9 @@ int delete_corrupted_dir_item(struct btrfs_trans_handle *trans, u32 namelen) { struct btrfs_dir_item *di_item; - struct btrfs_path path; + struct btrfs_path path = {}; int ret; - btrfs_init_path(&path); ret = btrfs_search_slot(trans, root, di_key, &path, 0, 1); if (ret > 0) { error("key (%llu %u %llu) doesn't exist in root %llu", @@ -736,7 +730,7 @@ static int find_file_type_dir_index(struct btrfs_root *root, u64 ino, u64 dirid, u64 index, const char *name, u32 name_len, u32 *imode_ret) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_key location; struct btrfs_dir_item *di; @@ -746,7 +740,6 @@ static int find_file_type_dir_index(struct btrfs_root *root, u64 ino, u64 dirid, u32 len; int ret; - btrfs_init_path(&path); key.objectid = dirid; key.offset = index; key.type = BTRFS_DIR_INDEX_KEY; @@ -788,7 +781,7 @@ static int find_file_type_dir_item(struct btrfs_root *root, u64 ino, u64 dirid, const char *name, u32 name_len, u32 *imode_ret) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_key location; struct btrfs_dir_item *di; @@ -800,7 +793,6 @@ static int find_file_type_dir_item(struct btrfs_root *root, u64 ino, u64 dirid, u32 len; int ret; - btrfs_init_path(&path); key.objectid = dirid; key.offset = btrfs_name_hash(name, name_len); key.type = BTRFS_DIR_INDEX_KEY; @@ -1056,7 +1048,7 @@ int check_repair_free_space_inode(struct btrfs_path *path) int recow_extent_buffer(struct btrfs_root *root, struct extent_buffer *eb) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_trans_handle *trans; struct btrfs_key key; int ret; @@ -1077,7 +1069,6 @@ int recow_extent_buffer(struct btrfs_root *root, struct extent_buffer *eb) if (IS_ERR(trans)) return PTR_ERR(trans); - btrfs_init_path(&path); path.lowest_level = btrfs_header_level(eb); if (path.lowest_level) btrfs_node_key_to_cpu(eb, &key, 0); @@ -1100,7 +1091,7 @@ int get_extent_item_generation(u64 bytenr, u64 *gen_ret) { struct btrfs_root *root = btrfs_extent_root(gfs_info, bytenr); struct btrfs_extent_item *ei; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int ret; @@ -1108,7 +1099,6 @@ int get_extent_item_generation(u64 bytenr, u64 *gen_ret) key.type = BTRFS_METADATA_ITEM_KEY; key.offset = (u64)-1; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); /* Not possible */ if (ret == 0) @@ -1232,7 +1222,7 @@ static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans, struct btrfs_root *cur_root) { struct btrfs_root *csum_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct extent_buffer *node; struct btrfs_file_extent_item *fi; @@ -1247,7 +1237,6 @@ static int fill_csum_tree_from_one_fs_root(struct btrfs_trans_handle *trans, if (!buf) return -ENOMEM; - btrfs_init_path(&path); key.objectid = 0; key.offset = 0; key.type = 0; @@ -1339,7 +1328,7 @@ out: static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_root *tree_root = gfs_info->tree_root; struct btrfs_root *cur_root; struct extent_buffer *node; @@ -1347,7 +1336,6 @@ static int fill_csum_tree_from_fs(struct btrfs_trans_handle *trans) int slot = 0; int ret = 0; - btrfs_init_path(&path); key.objectid = BTRFS_FS_TREE_OBJECTID; key.offset = 0; key.type = BTRFS_ROOT_ITEM_KEY; @@ -1486,14 +1474,13 @@ static int fill_csum_tree_from_extent(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root) { struct btrfs_root *csum_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_extent_item *ei; struct extent_buffer *leaf; char *buf; struct btrfs_key key; int ret; - btrfs_init_path(&path); key.objectid = 0; key.type = BTRFS_EXTENT_ITEM_KEY; key.offset = 0; diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 1614c065..a5116631 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -281,7 +281,7 @@ static int modify_block_groups_cache(u64 flags, int cache) { struct btrfs_root *root = btrfs_block_group_root(gfs_info); struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_block_group *bg_cache; struct btrfs_block_group_item *bi; struct btrfs_block_group_item bg_item; @@ -293,7 +293,6 @@ static int modify_block_groups_cache(u64 flags, int cache) key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; key.offset = 0; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) { errno = -ret; @@ -430,7 +429,7 @@ err: */ static int is_chunk_almost_full(u64 start) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_root *root = btrfs_block_group_root(gfs_info); struct btrfs_block_group_item *bi; @@ -446,7 +445,6 @@ static int is_chunk_almost_full(u64 start) key.type = BTRFS_BLOCK_GROUP_ITEM_KEY; key.offset = (u64)-1; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (!ret) ret = -EIO; @@ -637,7 +635,7 @@ static int repair_tree_block_ref(struct btrfs_root *root, { struct btrfs_trans_handle *trans = NULL; struct btrfs_root *extent_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_extent_item *ei; struct btrfs_tree_block_info *bi; struct btrfs_key key; @@ -660,7 +658,6 @@ static int repair_tree_block_ref(struct btrfs_root *root, WARN_ON(level > BTRFS_MAX_LEVEL); WARN_ON(level < 0); - btrfs_init_path(&path); bytenr = btrfs_header_bytenr(node); owner = btrfs_header_owner(node); generation = btrfs_header_generation(node); @@ -820,7 +817,7 @@ static int find_dir_index(struct btrfs_root *root, u64 dirid, u64 location_id, u64 *index_ret, char *namebuf, u32 name_len, u8 file_type) { - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *node; struct btrfs_dir_item *di; struct btrfs_key key; @@ -842,7 +839,6 @@ static int find_dir_index(struct btrfs_root *root, u64 dirid, u64 location_id, key.offset = (u64)-1; key.type = BTRFS_DIR_INDEX_KEY; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) return ret; @@ -919,7 +915,7 @@ static int find_dir_item(struct btrfs_root *root, struct btrfs_key *key, struct btrfs_key *location_key, char *name, u32 namelen, u8 file_type) { - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *node; struct btrfs_dir_item *di; struct btrfs_key location; @@ -942,7 +938,6 @@ static int find_dir_item(struct btrfs_root *root, struct btrfs_key *key, return ret; } - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, key, &path, 0, 0); if (ret) { ret = key->type == BTRFS_DIR_ITEM_KEY ? DIR_ITEM_MISSING : @@ -1338,7 +1333,7 @@ static int find_inode_ref(struct btrfs_root *root, struct btrfs_key *key, char *name, int namelen, u64 *index_ret) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_inode_ref *ref; struct btrfs_inode_extref *extref; struct extent_buffer *node; @@ -1355,7 +1350,6 @@ static int find_inode_ref(struct btrfs_root *root, struct btrfs_key *key, UASSERT(index_ret); - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, key, &path, 0, 0); if (ret) { ret = INODE_REF_MISSING; @@ -1415,7 +1409,6 @@ extref: goto out; btrfs_release_path(&path); - btrfs_init_path(&path); dir_id = key->offset; key->type = BTRFS_INODE_EXTREF_KEY; @@ -1498,14 +1491,13 @@ static int repair_inode_item_missing(struct btrfs_root *root, u64 ino, { struct btrfs_key key; struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; int ret; key.objectid = ino; key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - btrfs_init_path(&path); trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) { ret = -EIO; @@ -1564,14 +1556,13 @@ static int lowmem_delete_corrupted_dir_item(struct btrfs_root *root, static int try_repair_imode(struct btrfs_root *root, u64 ino) { struct btrfs_inode_item *iitem; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int ret; key.objectid = ino; key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret > 0) @@ -2188,7 +2179,7 @@ static int __count_dir_isize(struct btrfs_root *root, u64 ino, int type, u64 *size_ret) { struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; u32 len; struct btrfs_dir_item *di; int ret; @@ -2202,7 +2193,6 @@ static int __count_dir_isize(struct btrfs_root *root, u64 ino, int type, key.type = type; key.offset = (u64)-1; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) { ret = -EIO; @@ -2518,11 +2508,10 @@ out: static bool has_orphan_item(struct btrfs_root *root, u64 ino) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int ret; - btrfs_init_path(&path); key.objectid = BTRFS_ORPHAN_OBJECTID; key.type = BTRFS_ORPHAN_ITEM_KEY; key.offset = ino; @@ -3019,7 +3008,7 @@ static int check_tree_block_ref(struct btrfs_root *root, { struct btrfs_key key; struct btrfs_root *extent_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_extent_item *ei; struct btrfs_extent_inline_ref *iref; struct extent_buffer *leaf; @@ -3038,7 +3027,6 @@ static int check_tree_block_ref(struct btrfs_root *root, int strict = 1; int parent = 0; - btrfs_init_path(&path); key.objectid = bytenr; if (btrfs_fs_incompat(gfs_info, SKINNY_METADATA)) key.type = BTRFS_METADATA_ITEM_KEY; @@ -3239,7 +3227,7 @@ static int repair_extent_data_item(struct btrfs_root *root, struct btrfs_key fi_key; struct btrfs_key key; struct btrfs_extent_item *ei; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_root *extent_root; struct extent_buffer *eb; u64 size; @@ -3291,7 +3279,6 @@ static int repair_extent_data_item(struct btrfs_root *root, key.type = BTRFS_EXTENT_ITEM_KEY; key.offset = num_bytes; - btrfs_init_path(&path); extent_root = btrfs_extent_root(gfs_info, key.objectid); ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0); if (ret < 0) { @@ -3374,7 +3361,7 @@ static int check_extent_data_item(struct btrfs_root *root, { struct btrfs_file_extent_item *fi; struct extent_buffer *eb = pathp->nodes[0]; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_root *extent_root; struct btrfs_key fi_key; struct btrfs_key dbref_key; @@ -3440,7 +3427,6 @@ static int check_extent_data_item(struct btrfs_root *root, owner = btrfs_header_owner(eb); /* Check the extent item of the file extent in extent tree */ - btrfs_init_path(&path); dbref_key.objectid = btrfs_file_extent_disk_bytenr(eb, fi); dbref_key.type = BTRFS_EXTENT_ITEM_KEY; dbref_key.offset = btrfs_file_extent_disk_num_bytes(eb, fi); @@ -3567,7 +3553,7 @@ static int check_block_group_item(struct extent_buffer *eb, int slot) struct btrfs_root *chunk_root = gfs_info->chunk_root; struct btrfs_block_group_item *bi; struct btrfs_block_group_item bg_item; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key bg_key; struct btrfs_key chunk_key; struct btrfs_key extent_key; @@ -3592,7 +3578,6 @@ static int check_block_group_item(struct extent_buffer *eb, int slot) chunk_key.type = BTRFS_CHUNK_ITEM_KEY; chunk_key.offset = bg_key.objectid; - btrfs_init_path(&path); /* Search for the referencer chunk */ ret = btrfs_search_slot(NULL, chunk_root, &chunk_key, &path, 0, 0); if (ret) { @@ -3618,7 +3603,6 @@ static int check_block_group_item(struct extent_buffer *eb, int slot) extent_key.type = 0; extent_key.offset = 0; - btrfs_init_path(&path); extent_root = btrfs_extent_root(gfs_info, extent_key.objectid); ret = btrfs_search_slot(NULL, extent_root, &extent_key, &path, 0, 0); if (ret < 0) @@ -3697,7 +3681,7 @@ static int query_tree_block_level(u64 bytenr) { struct btrfs_root *extent_root; struct extent_buffer *eb; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_extent_item *ei; u64 flags; @@ -3711,8 +3695,6 @@ static int query_tree_block_level(u64 bytenr) key.type = BTRFS_METADATA_ITEM_KEY; key.offset = (u64)-1; - btrfs_init_path(&path); - extent_root = btrfs_extent_root(gfs_info, bytenr); ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0); if (ret < 0) @@ -3775,7 +3757,7 @@ static int check_tree_block_backref(u64 root_id, u64 bytenr, int level) { struct btrfs_root *root; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *eb; struct extent_buffer *node; u32 nodesize = btrfs_super_nodesize(gfs_info->super_copy); @@ -3821,7 +3803,6 @@ static int check_tree_block_backref(u64 root_id, u64 bytenr, int level) free_extent_buffer(eb); - btrfs_init_path(&path); path.lowest_level = level; /* Search with the first key, to ensure we can reach it */ ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); @@ -3947,7 +3928,7 @@ static int check_extent_data_backref(u64 root_id, u64 objectid, u64 offset, struct btrfs_root *root; struct btrfs_root *extent_root; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_file_extent_item *fi; u32 found_count = 0; @@ -3959,7 +3940,6 @@ static int check_extent_data_backref(u64 root_id, u64 objectid, u64 offset, key.type = BTRFS_EXTENT_ITEM_KEY; key.offset = (u64)-1; - btrfs_init_path(&path); extent_root = btrfs_extent_root(gfs_info, bytenr); ret = btrfs_search_slot(NULL, extent_root, &key, &path, 0, 0); if (ret < 0) @@ -3977,7 +3957,6 @@ static int check_extent_data_backref(u64 root_id, u64 objectid, u64 offset, key.objectid = root_id; key.type = BTRFS_ROOT_ITEM_KEY; key.offset = (u64)-1; - btrfs_init_path(&path); root = btrfs_read_fs_root(gfs_info, &key); if (IS_ERR(root)) @@ -4445,7 +4424,7 @@ static int check_dev_extent_item(struct extent_buffer *eb, int slot) { struct btrfs_root *chunk_root = gfs_info->chunk_root; struct btrfs_dev_extent *ptr; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key chunk_key; struct btrfs_key devext_key; struct btrfs_chunk *chunk; @@ -4464,7 +4443,6 @@ static int check_dev_extent_item(struct extent_buffer *eb, int slot) chunk_key.type = BTRFS_CHUNK_ITEM_KEY; chunk_key.offset = btrfs_dev_extent_chunk_offset(eb, ptr); - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, chunk_root, &chunk_key, &path, 0, 0); if (ret) goto out; @@ -4508,7 +4486,7 @@ static int check_dev_item(struct extent_buffer *eb, int slot, { struct btrfs_root *dev_root = gfs_info->dev_root; struct btrfs_dev_item *dev_item; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_dev_extent *ptr; struct btrfs_device *dev; @@ -4537,7 +4515,6 @@ static int check_dev_item(struct extent_buffer *eb, int slot, key.type = BTRFS_DEV_EXTENT_KEY; key.offset = 0; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, dev_root, &key, &path, 0, 0); if (ret < 0) { btrfs_item_key_to_cpu(eb, &key, slot); @@ -4681,7 +4658,7 @@ out: static int check_chunk_item(struct extent_buffer *eb, int slot) { struct btrfs_root *dev_root = gfs_info->dev_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key chunk_key; struct btrfs_key devext_key; struct btrfs_chunk *chunk; @@ -4711,7 +4688,6 @@ static int check_chunk_item(struct extent_buffer *eb, int slot) } type = btrfs_chunk_type(eb, chunk); - btrfs_init_path(&path); ret = find_block_group_item(&path, chunk_key.offset, length, type); if (ret < 0) err |= REFERENCER_MISSING; @@ -4720,7 +4696,6 @@ static int check_chunk_item(struct extent_buffer *eb, int slot) stripe_len = btrfs_stripe_length(gfs_info, eb, chunk); for (i = 0; i < num_stripes; i++) { btrfs_release_path(&path); - btrfs_init_path(&path); devext_key.objectid = btrfs_stripe_devid_nr(eb, chunk, i); devext_key.type = BTRFS_DEV_EXTENT_KEY; devext_key.offset = btrfs_stripe_offset_nr(eb, chunk, i); @@ -5117,12 +5092,10 @@ static int repair_fs_first_inode(struct btrfs_root *root, int err) { struct btrfs_trans_handle *trans; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; int filetype = BTRFS_FT_DIR; int ret = 0; - btrfs_init_path(&path); - if (err & INODE_REF_MISSING) { key.objectid = BTRFS_FIRST_FREE_OBJECTID; key.type = BTRFS_INODE_REF_KEY; @@ -5178,7 +5151,7 @@ out: */ static int check_fs_first_inode(struct btrfs_root *root) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_inode_item *ii; u64 index; @@ -5196,7 +5169,6 @@ static int check_fs_first_inode(struct btrfs_root *root) BTRFS_FIRST_FREE_OBJECTID) return 0; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) goto out; @@ -5250,7 +5222,7 @@ out: */ static int check_btrfs_root(struct btrfs_root *root, int check_all) { - struct btrfs_path path; + struct btrfs_path path = {}; struct node_refs nrefs; struct btrfs_root_item *root_item = &root->root_item; u64 super_generation = btrfs_super_generation(gfs_info->super_copy); @@ -5273,7 +5245,6 @@ static int check_btrfs_root(struct btrfs_root *root, int check_all) level = btrfs_header_level(root->node); - btrfs_init_path(&path); if (btrfs_root_generation(root_item) > super_generation + 1) { error( @@ -5358,7 +5329,7 @@ static int check_fs_root(struct btrfs_root *root) static int check_root_ref(struct btrfs_root *root, struct btrfs_key *ref_key, struct extent_buffer *node, int slot) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_root_ref *ref; struct btrfs_root_ref *backref; @@ -5395,7 +5366,6 @@ static int check_root_ref(struct btrfs_root *root, struct btrfs_key *ref_key, key.type = BTRFS_ROOT_BACKREF_KEY + BTRFS_ROOT_REF_KEY - ref_key->type; key.offset = ref_key->objectid; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret) { err |= ROOT_REF_MISSING; @@ -5450,14 +5420,13 @@ int check_fs_roots_lowmem(void) { struct btrfs_root *tree_root = gfs_info->tree_root; struct btrfs_root *cur_root = NULL; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct extent_buffer *node; int slot; int ret; int err = 0; - btrfs_init_path(&path); key.objectid = BTRFS_FS_TREE_OBJECTID; key.offset = 0; key.type = BTRFS_ROOT_ITEM_KEY; @@ -5556,7 +5525,7 @@ out: */ int check_chunks_and_extents_lowmem(void) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key old_key; struct btrfs_key key; struct btrfs_root *root; @@ -5572,7 +5541,6 @@ int check_chunks_and_extents_lowmem(void) ret = check_btrfs_root(root, 1); err |= ret; - btrfs_init_path(&path); key.objectid = BTRFS_EXTENT_TREE_OBJECTID; key.offset = 0; key.type = BTRFS_ROOT_ITEM_KEY; diff --git a/check/qgroup-verify.c b/check/qgroup-verify.c index 1a62009b..0c08eae8 100644 --- a/check/qgroup-verify.c +++ b/check/qgroup-verify.c @@ -938,7 +938,7 @@ static int load_quota_info(struct btrfs_fs_info *info) int ret; struct btrfs_root *root = info->quota_root; struct btrfs_root *tmproot; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_key root_key; struct btrfs_disk_key disk_key; @@ -954,8 +954,6 @@ loop: * items. The 2nd pass picks up relation items and glues them to their * respective count structures. */ - btrfs_init_path(&path); - key.offset = 0; key.objectid = search_relations ? 0 : BTRFS_QGROUP_RELATION_KEY; key.type = 0; @@ -1164,13 +1162,11 @@ static int scan_extents(struct btrfs_fs_info *info, int ret, i, nr, level; struct btrfs_root *root = btrfs_extent_root(info, start); struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_disk_key disk_key; struct extent_buffer *leaf; u64 bytenr = 0, num_bytes = 0; - btrfs_init_path(&path); - key.objectid = start; key.type = 0; key.offset = 0; @@ -1562,7 +1558,7 @@ static int repair_qgroup_info(struct btrfs_fs_info *info, int ret; struct btrfs_root *root = info->quota_root; struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_qgroup_info_item *info_item; struct btrfs_key key; @@ -1575,7 +1571,6 @@ static int repair_qgroup_info(struct btrfs_fs_info *info, if (IS_ERR(trans)) return PTR_ERR(trans); - btrfs_init_path(&path); key.objectid = 0; key.type = BTRFS_QGROUP_INFO_KEY; key.offset = count->qgroupid; @@ -1619,7 +1614,7 @@ static int repair_qgroup_status(struct btrfs_fs_info *info, bool silent) int ret; struct btrfs_root *root = info->quota_root; struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_qgroup_status_item *status_item; @@ -1630,7 +1625,6 @@ static int repair_qgroup_status(struct btrfs_fs_info *info, bool silent) if (IS_ERR(trans)) return PTR_ERR(trans); - btrfs_init_path(&path); key.objectid = 0; key.type = BTRFS_QGROUP_STATUS_KEY; key.offset = 0; diff --git a/check/repair.c b/check/repair.c index b73f9518..c5afbaa1 100644 --- a/check/repair.c +++ b/check/repair.c @@ -172,12 +172,11 @@ static int populate_used_from_extent_root(struct btrfs_root *root, { struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *leaf; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int slot; int ret; - btrfs_init_path(&path); key.offset = 0; key.objectid = 0; key.type = BTRFS_EXTENT_ITEM_KEY; diff --git a/cmds/inspect-dump-tree.c b/cmds/inspect-dump-tree.c index 5385208d..f5f344c3 100644 --- a/cmds/inspect-dump-tree.c +++ b/cmds/inspect-dump-tree.c @@ -310,7 +310,7 @@ static int cmd_inspect_dump_tree(const struct cmd_struct *cmd, { struct btrfs_root *root; struct btrfs_fs_info *info; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_root_item ri; struct extent_buffer *leaf; @@ -545,7 +545,6 @@ static int cmd_inspect_dump_tree(const struct cmd_struct *cmd, } tree_root_scan = info->tree_root; - btrfs_init_path(&path); again: if (!extent_buffer_uptodate(tree_root_scan->node)) goto no_node; diff --git a/cmds/inspect-tree-stats.c b/cmds/inspect-tree-stats.c index 716aa008..080547c1 100644 --- a/cmds/inspect-tree-stats.c +++ b/cmds/inspect-tree-stats.c @@ -314,7 +314,7 @@ static int calc_root_size(struct btrfs_root *tree_root, struct btrfs_key *key, int find_inline) { struct btrfs_root *root; - struct btrfs_path path; + struct btrfs_path path = {}; struct rb_node *n; struct timeval start, end, diff = {0}; struct root_stats stat; @@ -329,7 +329,6 @@ static int calc_root_size(struct btrfs_root *tree_root, struct btrfs_key *key, return 1; } - btrfs_init_path(&path); memset(&stat, 0, sizeof(stat)); level = btrfs_header_level(root->node); stat.lowest_bytenr = btrfs_header_bytenr(root->node); diff --git a/cmds/rescue-chunk-recover.c b/cmds/rescue-chunk-recover.c index 52119d98..f30612d1 100644 --- a/cmds/rescue-chunk-recover.c +++ b/cmds/rescue-chunk-recover.c @@ -556,7 +556,7 @@ static int check_chunk_by_metadata(struct recover_control *rc, int ret; int i; int slot; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_root *dev_root; struct stripe *stripe; @@ -564,8 +564,6 @@ static int check_chunk_by_metadata(struct recover_control *rc, struct btrfs_block_group_item *bg_ptr; struct extent_buffer *l; - btrfs_init_path(&path); - if (bg_only) goto bg_check; @@ -985,7 +983,7 @@ static int block_group_remove_all_extent_items(struct btrfs_trans_handle *trans, { struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; u64 start = bg->objectid; u64 end = bg->objectid + bg->offset; @@ -995,7 +993,6 @@ static int block_group_remove_all_extent_items(struct btrfs_trans_handle *trans, int i; int del_s, del_nr; - btrfs_init_path(&path); root = btrfs_extent_root(fs_info, start); key.objectid = start; @@ -1384,14 +1381,13 @@ static int rebuild_block_group(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info = root->fs_info; struct chunk_record *chunk_rec; struct btrfs_key search_key; - struct btrfs_path path; + struct btrfs_path path = {}; u64 used = 0; int ret = 0; if (list_empty(&rc->rebuild_chunks)) return 0; - btrfs_init_path(&path); list_for_each_entry(chunk_rec, &rc->rebuild_chunks, list) { search_key.objectid = chunk_rec->offset; search_key.type = BTRFS_EXTENT_ITEM_KEY; @@ -1968,7 +1964,7 @@ static int rebuild_raid_data_chunk_stripes(struct recover_control *rc, int i; int ret = 0; int slot; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key prev_key; struct btrfs_key key; struct btrfs_root *csum_root; @@ -1988,7 +1984,6 @@ static int rebuild_raid_data_chunk_stripes(struct recover_control *rc, LIST_HEAD(unordered); LIST_HEAD(candidates); - btrfs_init_path(&path); list_splice_init(&chunk->dextents, &candidates); again: if (list_is_last(candidates.next, &candidates)) diff --git a/cmds/restore.c b/cmds/restore.c index 31cad31f..6490eb9c 100644 --- a/cmds/restore.c +++ b/cmds/restore.c @@ -474,7 +474,7 @@ static int set_file_xattrs(struct btrfs_root *root, u64 inode, int fd, const char *file_name) { struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_dir_item *di; u32 name_len = 0; @@ -485,7 +485,6 @@ static int set_file_xattrs(struct btrfs_root *root, u64 inode, char *data = NULL; int ret = 0; - btrfs_init_path(&path); key.objectid = inode; key.type = BTRFS_XATTR_ITEM_KEY; key.offset = 0; @@ -571,11 +570,10 @@ out: static int copy_metadata(struct btrfs_root *root, int fd, struct btrfs_key *key) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_inode_item *inode_item; int ret; - btrfs_init_path(&path); ret = btrfs_lookup_inode(NULL, root, &path, key, 0); if (ret == 0) { struct btrfs_timespec *bts; @@ -620,7 +618,7 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, const char *file) { struct extent_buffer *leaf; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_file_extent_item *fi; struct btrfs_inode_item *inode_item; struct btrfs_timespec *bts; @@ -632,7 +630,6 @@ static int copy_file(struct btrfs_root *root, int fd, struct btrfs_key *key, struct timespec times[2]; bool times_ok = false; - btrfs_init_path(&path); ret = btrfs_lookup_inode(NULL, root, &path, key, 0); if (ret == 0) { inode_item = btrfs_item_ptr(path.nodes[0], path.slots[0], @@ -798,7 +795,7 @@ static int overwrite_ok(const char * path) static int copy_symlink(struct btrfs_root *root, struct btrfs_key *key, const char *file) { - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_file_extent_item *extent_item; struct btrfs_inode_item *inode_item; @@ -821,7 +818,6 @@ static int copy_symlink(struct btrfs_root *root, struct btrfs_key *key, } } - btrfs_init_path(&path); key->type = BTRFS_EXTENT_DATA_KEY; key->offset = 0; ret = btrfs_search_slot(NULL, root, key, &path, 0, 0); @@ -913,7 +909,7 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, const char *output_rootdir, const char *in_dir, const regex_t *mreg) { - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_dir_item *dir_item; struct btrfs_key found_key, location; @@ -924,7 +920,6 @@ static int search_dir(struct btrfs_root *root, struct btrfs_key *key, int fd; u8 type; - btrfs_init_path(&path); key->offset = 0; key->type = BTRFS_DIR_INDEX_KEY; ret = btrfs_search_slot(NULL, root, key, &path, 0, 0); @@ -1159,7 +1154,7 @@ static int do_list_roots(struct btrfs_root *root) struct btrfs_key key; struct btrfs_key found_key; struct btrfs_disk_key disk_key; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_root_item ri; unsigned long offset; @@ -1168,7 +1163,6 @@ static int do_list_roots(struct btrfs_root *root) root = root->fs_info->tree_root; - btrfs_init_path(&path); key.offset = 0; key.objectid = 0; key.type = BTRFS_ROOT_ITEM_KEY; @@ -1287,13 +1281,12 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, static int find_first_dir(struct btrfs_root *root, u64 *objectid) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key found_key; struct btrfs_key key; int ret = -1; int i; - btrfs_init_path(&path); key.objectid = 0; key.type = BTRFS_DIR_INDEX_KEY; key.offset = 0; diff --git a/convert/main.c b/convert/main.c index 941b5ce3..78c8d76e 100644 --- a/convert/main.c +++ b/convert/main.c @@ -790,7 +790,7 @@ static int create_image(struct btrfs_root *root, { struct btrfs_inode_item buf; struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct cache_extent *cache; struct cache_tree used_tmp; @@ -807,7 +807,6 @@ static int create_image(struct btrfs_root *root, return PTR_ERR(trans); cache_tree_init(&used_tmp); - btrfs_init_path(&path); ret = btrfs_find_free_objectid(trans, root, BTRFS_FIRST_FREE_OBJECTID, &ino); @@ -1448,7 +1447,7 @@ static int check_convert_image(struct btrfs_root *image_root, u64 ino, u64 total_size, char *reserved_ranges[]) { struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_fs_info *fs_info = image_root->fs_info; u64 checked_bytes = 0; int ret; @@ -1457,7 +1456,6 @@ static int check_convert_image(struct btrfs_root *image_root, u64 ino, key.offset = 0; key.type = BTRFS_EXTENT_DATA_KEY; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, image_root, &key, &path, 0, 0); /* * It's possible that some fs doesn't store any (including sb) @@ -1613,7 +1611,7 @@ static int do_rollback(const char *devname) struct btrfs_root *image_root; struct btrfs_fs_info *fs_info; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_dir_item *dir; struct btrfs_inode_item *inode_item; struct btrfs_root_ref *root_ref_item; @@ -1673,7 +1671,6 @@ static int do_rollback(const char *devname) key.objectid = CONV_IMAGE_SUBVOL_OBJECTID; key.type = BTRFS_ROOT_BACKREF_KEY; key.offset = BTRFS_FS_TREE_OBJECTID; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, &path, 0, 0); if (ret > 0) { error("unable to find source fs image subvolume, is it deleted?"); diff --git a/convert/source-fs.c b/convert/source-fs.c index f600b2c3..d206fab6 100644 --- a/convert/source-fs.c +++ b/convert/source-fs.c @@ -228,7 +228,7 @@ int record_file_blocks(struct blk_iterate_data *data, int ret = 0; struct btrfs_root *root = data->root; struct btrfs_root *convert_root = data->convert_root; - struct btrfs_path path; + struct btrfs_path path = {}; u32 sectorsize = root->fs_info->sectorsize; u64 file_pos = file_block * sectorsize; u64 old_disk_bytenr = disk_block * sectorsize; @@ -241,8 +241,6 @@ int record_file_blocks(struct blk_iterate_data *data, data->objectid, data->inode, file_pos, 0, num_bytes); - btrfs_init_path(&path); - /* * Search real disk bytenr from convert root */ diff --git a/image/main.c b/image/main.c index 856e313f..32f82705 100644 --- a/image/main.c +++ b/image/main.c @@ -1020,7 +1020,7 @@ static int create_metadump(const char *input, FILE *out, int num_threads, int walk_trees, bool dump_data) { struct btrfs_root *root; - struct btrfs_path path; + struct btrfs_path path = {}; struct metadump_struct metadump; int ret; int err = 0; @@ -1048,8 +1048,6 @@ static int create_metadump(const char *input, FILE *out, int num_threads, goto out; } - btrfs_init_path(&path); - if (walk_trees) { ret = copy_tree_blocks(root, root->fs_info->chunk_root->node, &metadump, 1); @@ -2392,7 +2390,7 @@ static int fixup_device_size(struct btrfs_trans_handle *trans, struct btrfs_dev_item *dev_item; struct btrfs_dev_extent *dev_ext; struct btrfs_device *dev; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_root *root = fs_info->chunk_root; struct btrfs_key key; @@ -2403,7 +2401,6 @@ static int fixup_device_size(struct btrfs_trans_handle *trans, dev_item = &fs_info->super_copy->dev_item; - btrfs_init_path(&path); devid = btrfs_stack_device_id(dev_item); key.objectid = devid; @@ -2568,7 +2565,7 @@ static int remove_all_dev_extents(struct btrfs_trans_handle *trans) { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_root *root = fs_info->dev_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct extent_buffer *leaf; int slot; @@ -2577,7 +2574,6 @@ static int remove_all_dev_extents(struct btrfs_trans_handle *trans) key.objectid = 1; key.type = BTRFS_DEV_EXTENT_KEY; key.offset = 0; - btrfs_init_path(&path); ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); if (ret < 0) { @@ -2944,7 +2940,7 @@ static int update_disk_super_on_device(struct btrfs_fs_info *info, { struct btrfs_key key; struct extent_buffer *leaf; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_dev_item *dev_item; struct btrfs_super_block disk_super; char dev_uuid[BTRFS_UUID_SIZE]; @@ -2958,7 +2954,6 @@ static int update_disk_super_on_device(struct btrfs_fs_info *info, key.type = BTRFS_DEV_ITEM_KEY; key.offset = cur_devid; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, info->chunk_root, &key, &path, 0, 0); if (ret) { error("search key failed: %d", ret); diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 0bd24646..9ade5fca 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -83,11 +83,6 @@ u64 btrfs_extref_hash(u64 parent_objectid, const char *name, int len) return (u64)crc32c(parent_objectid, name, len); } -inline void btrfs_init_path(struct btrfs_path *p) -{ - memset(p, 0, sizeof(*p)); -} - struct btrfs_path *btrfs_alloc_path(void) { struct btrfs_path *path; diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index cab8f71b..3ff11dd0 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -989,7 +989,6 @@ int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path, void btrfs_release_path(struct btrfs_path *p); struct btrfs_path *btrfs_alloc_path(void); void btrfs_free_path(struct btrfs_path *p); -void btrfs_init_path(struct btrfs_path *p); int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int slot, int nr); diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index ba853110..c2ff94f5 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -3463,7 +3463,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_block_group *block_group; - struct btrfs_path path; + struct btrfs_path path = {}; int ret = 0; block_group = btrfs_lookup_block_group(fs_info, bytenr); @@ -3485,7 +3485,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, */ btrfs_pin_extent(fs_info, bytenr, len); - btrfs_init_path(&path); /* delete block group item and chunk item */ ret = remove_block_group_item(trans, &path, block_group); btrfs_release_path(&path); diff --git a/kernel-shared/file.c b/kernel-shared/file.c index 100ea31c..de5ecfea 100644 --- a/kernel-shared/file.c +++ b/kernel-shared/file.c @@ -187,7 +187,7 @@ int btrfs_read_file(struct btrfs_root *root, u64 ino, u64 start, int len, { struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_inode_item *ii; u64 isize; @@ -203,7 +203,6 @@ int btrfs_read_file(struct btrfs_root *root, u64 ino, u64 start, int len, return -EINVAL; } - btrfs_init_path(&path); key.objectid = ino; key.offset = start; key.type = BTRFS_EXTENT_DATA_KEY; diff --git a/kernel-shared/free-space-cache.c b/kernel-shared/free-space-cache.c index 7bd76e39..e27c1b62 100644 --- a/kernel-shared/free-space-cache.c +++ b/kernel-shared/free-space-cache.c @@ -910,7 +910,7 @@ int btrfs_clear_free_space_cache(struct btrfs_trans_handle *trans, { struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_root *tree_root = fs_info->tree_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; struct btrfs_disk_key location; struct btrfs_free_space_header *sc_header; @@ -919,8 +919,6 @@ int btrfs_clear_free_space_cache(struct btrfs_trans_handle *trans, int slot; int ret; - btrfs_init_path(&path); - key.objectid = BTRFS_FREE_SPACE_OBJECTID; key.type = 0; key.offset = bg->start; diff --git a/kernel-shared/inode.c b/kernel-shared/inode.c index 1430cf33..d4018406 100644 --- a/kernel-shared/inode.c +++ b/kernel-shared/inode.c @@ -585,7 +585,7 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *new_root = NULL; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_inode_item *inode_item; struct extent_buffer *leaf; struct btrfs_key key; @@ -600,7 +600,6 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, if (len == 0 || len > BTRFS_NAME_LEN) return NULL; - btrfs_init_path(&path); key.objectid = dirid; key.type = BTRFS_DIR_INDEX_KEY; key.offset = (u64)-1; @@ -705,7 +704,6 @@ struct btrfs_root *btrfs_mksubvol(struct btrfs_root *root, new_root = NULL; } fail: - btrfs_init_path(&path); return new_root; } @@ -737,7 +735,6 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, search_key.offset = 0; search_key.type = 0; - btrfs_init_path(path); start_found = 0; ret = btrfs_search_slot(trans, root, &search_key, path, 0, 0); if (ret < 0) diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c index ff2a8097..9e9eb43a 100644 --- a/kernel-shared/print-tree.c +++ b/kernel-shared/print-tree.c @@ -1501,7 +1501,7 @@ out: static void bfs_print_children(struct extent_buffer *root_eb, unsigned int mode) { struct btrfs_fs_info *fs_info = root_eb->fs_info; - struct btrfs_path path; + struct btrfs_path path = {}; int root_level = btrfs_header_level(root_eb); int cur_level; int ret; @@ -1513,7 +1513,6 @@ static void bfs_print_children(struct extent_buffer *root_eb, unsigned int mode) mode |= BTRFS_PRINT_TREE_BFS; mode &= ~(BTRFS_PRINT_TREE_DFS); - btrfs_init_path(&path); /* For path */ extent_buffer_get(root_eb); path.nodes[root_level] = root_eb; diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c index fff49a06..2ae4cc27 100644 --- a/kernel-shared/volumes.c +++ b/kernel-shared/volumes.c @@ -2664,7 +2664,7 @@ static int check_dev_extent_beyond_bytenr(struct btrfs_fs_info *fs_info, u64 physical) { struct btrfs_root *root = fs_info->dev_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_dev_extent *dext; struct btrfs_key key; u64 dext_len; @@ -2675,7 +2675,6 @@ static int check_dev_extent_beyond_bytenr(struct btrfs_fs_info *fs_info, key.type = BTRFS_DEV_EXTENT_KEY; key.offset = (u64)-1; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) return ret; @@ -2714,7 +2713,7 @@ static int reset_device_item_total_bytes(struct btrfs_fs_info *fs_info, { struct btrfs_trans_handle *trans; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_root *chunk_root = fs_info->chunk_root; struct btrfs_dev_item *di; u64 old_bytes = device->total_bytes; @@ -2737,7 +2736,6 @@ static int reset_device_item_total_bytes(struct btrfs_fs_info *fs_info, return ret; } - btrfs_init_path(&path); ret = btrfs_search_slot(trans, chunk_root, &key, &path, 0, 1); if (ret > 0) { error("failed to find DEV_ITEM for devid %llu", device->devid); diff --git a/mkfs/main.c b/mkfs/main.c index 418c721c..e0b589cd 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -235,11 +235,10 @@ err: static int __recow_root(struct btrfs_trans_handle *trans, struct btrfs_root *root) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int ret; - btrfs_init_path(&path); key.objectid = 0; key.type = 0; key.offset = 0; @@ -590,10 +589,9 @@ static int cleanup_temp_chunks(struct btrfs_fs_info *fs_info, struct btrfs_root *root = btrfs_block_group_root(fs_info); struct btrfs_key key; struct btrfs_key found_key; - struct btrfs_path path; + struct btrfs_path path = {}; int ret = 0; - btrfs_init_path(&path); trans = btrfs_start_transaction(root, 1); if (IS_ERR(trans)) { ret = PTR_ERR(trans); @@ -707,7 +705,7 @@ static int create_data_reloc_tree(struct btrfs_trans_handle *trans) struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_inode_item *inode; struct btrfs_root *root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key = { .objectid = BTRFS_DATA_RELOC_TREE_OBJECTID, .type = BTRFS_ROOT_ITEM_KEY, @@ -749,7 +747,6 @@ static int create_data_reloc_tree(struct btrfs_trans_handle *trans) key.objectid = ino; key.type = BTRFS_INODE_ITEM_KEY; key.offset = 0; - btrfs_init_path(&path); ret = btrfs_search_slot(trans, root, &key, &path, 0, 1); if (ret > 0) { @@ -851,7 +848,7 @@ static int insert_qgroup_items(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info, u64 qgroupid) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_root *quota_root = fs_info->quota_root; struct btrfs_key key; int ret; @@ -865,7 +862,6 @@ static int insert_qgroup_items(struct btrfs_trans_handle *trans, key.type = BTRFS_QGROUP_INFO_KEY; key.offset = qgroupid; - btrfs_init_path(&path); ret = btrfs_insert_empty_item(trans, quota_root, &path, &key, sizeof(struct btrfs_qgroup_info_item)); btrfs_release_path(&path); @@ -886,7 +882,7 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info) struct btrfs_trans_handle *trans; struct btrfs_qgroup_status_item *qsi; struct btrfs_root *quota_root; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int qgroup_repaired = 0; int ret; @@ -910,7 +906,6 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info) key.type = BTRFS_QGROUP_STATUS_KEY; key.offset = 0; - btrfs_init_path(&path); ret = btrfs_insert_empty_item(trans, quota_root, &path, &key, sizeof(*qsi)); if (ret < 0) { diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c index aa2577ad..d6de3eba 100644 --- a/mkfs/rootdir.c +++ b/mkfs/rootdir.c @@ -455,7 +455,7 @@ static int traverse_directory(struct btrfs_trans_handle *trans, ino_t parent_inum, cur_inum; ino_t highest_inum = 0; const char *parent_dir_name; - struct btrfs_path path; + struct btrfs_path path = {}; struct extent_buffer *leaf; struct btrfs_key root_dir_key; u64 root_dir_inode_size = 0; @@ -476,8 +476,6 @@ static int traverse_directory(struct btrfs_trans_handle *trans, dir_entry->inum = parent_inum; list_add_tail(&dir_entry->list, &dir_head->list); - btrfs_init_path(&path); - root_dir_key.objectid = btrfs_root_dirid(&root->root_item); root_dir_key.offset = 0; root_dir_key.type = BTRFS_INODE_ITEM_KEY; @@ -810,7 +808,7 @@ static int get_device_extent_end(struct btrfs_fs_info *fs_info, { struct btrfs_root *dev_root = fs_info->dev_root; struct btrfs_key key; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_dev_extent *de; int ret; @@ -818,7 +816,6 @@ static int get_device_extent_end(struct btrfs_fs_info *fs_info, key.type = BTRFS_DEV_EXTENT_KEY; key.offset = (u64)-1; - btrfs_init_path(&path); ret = btrfs_search_slot(NULL, dev_root, &key, &path, 0, 0); if (ret == 0) { error("DEV_EXTENT for devid %llu not found", devid); @@ -862,7 +859,7 @@ static int set_device_size(struct btrfs_fs_info *fs_info, struct btrfs_root *chunk_root = fs_info->chunk_root; struct btrfs_trans_handle *trans; struct btrfs_dev_item *di; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; int ret; @@ -871,7 +868,6 @@ static int set_device_size(struct btrfs_fs_info *fs_info, * super->dev_item will also get updated */ device->total_bytes = new_size; - btrfs_init_path(&path); /* Update device item in chunk tree */ trans = btrfs_start_transaction(chunk_root, 1); diff --git a/quick-test.c b/quick-test.c index 480e78bb..3f3c1cb3 100644 --- a/quick-test.c +++ b/quick-test.c @@ -41,7 +41,7 @@ int main(int ac, char **av) { int run_size = 300000; int max_key = 100000000; int tree_size = 2; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_root *root; struct btrfs_trans_handle *trans; @@ -86,7 +86,6 @@ int main(int ac, char **av) { for (i = 0; i < run_size; i++) { num = next_key(i, max_key); ins.objectid = num; - btrfs_init_path(&path); if (i % 10000 == 0) fprintf(stderr, "search %d:%d\n", num, i); ret = btrfs_search_slot(NULL, root, &ins, &path, 0, 0); @@ -117,7 +116,6 @@ int main(int ac, char **av) { for (i = 0 ; i < run_size/4; i++) { num = next_key(i, max_key); ins.objectid = num; - btrfs_init_path(&path); ret = btrfs_search_slot(trans, root, &ins, &path, -1, 1); if (!ret) { if (i % 10000 == 0) @@ -163,7 +161,6 @@ int main(int ac, char **av) { for (i = 0; i < run_size; i++) { num = next_key(i, max_key); ins.objectid = num; - btrfs_init_path(&path); if (i % 10000 == 0) fprintf(stderr, "search %d:%d\n", num, i); ret = btrfs_search_slot(NULL, root, &ins, &path, 0, 0); @@ -181,7 +178,6 @@ int main(int ac, char **av) { struct extent_buffer *leaf; int slot; ins.objectid = (u64)-1; - btrfs_init_path(&path); ret = btrfs_search_slot(trans, root, &ins, &path, -1, 1); if (ret == 0) BUG(); diff --git a/tune/change-csum.c b/tune/change-csum.c index 49624c6f..f7917f0b 100644 --- a/tune/change-csum.c +++ b/tune/change-csum.c @@ -29,12 +29,11 @@ static int change_tree_csum(struct btrfs_trans_handle *trans, struct btrfs_root int csum_type) { struct btrfs_fs_info *fs_info = root->fs_info; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key = {0, 0, 0}; int ret = 0; int level; - btrfs_init_path(&path); /* No transaction, all in-place */ ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) @@ -298,7 +297,7 @@ static int fill_csum_tree_from_extent(struct btrfs_fs_info *fs_info) { struct btrfs_root *extent_root = btrfs_extent_root(fs_info, 0); struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_extent_item *ei; struct extent_buffer *leaf; char *buf; @@ -313,7 +312,6 @@ static int fill_csum_tree_from_extent(struct btrfs_fs_info *fs_info) return -EINVAL; } - btrfs_init_path(&path); key.objectid = 0; key.type = BTRFS_EXTENT_ITEM_KEY; key.offset = 0; @@ -373,7 +371,7 @@ int rewrite_checksums(struct btrfs_fs_info *fs_info, int csum_type) struct btrfs_root *root; struct btrfs_super_block *disk_super; struct btrfs_trans_handle *trans; - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key; u64 super_flags; int ret; @@ -404,7 +402,6 @@ int rewrite_checksums(struct btrfs_fs_info *fs_info, int csum_type) return ret; } - btrfs_init_path(&path); key.objectid = BTRFS_CSUM_TREE_TMP_OBJECTID; key.type = BTRFS_TEMPORARY_ITEM_KEY; key.offset = 0; diff --git a/tune/change-uuid.c b/tune/change-uuid.c index dae41056..41118416 100644 --- a/tune/change-uuid.c +++ b/tune/change-uuid.c @@ -81,11 +81,10 @@ static int change_buffer_header_uuid(struct extent_buffer *eb, uuid_t new_fsid) static int change_extent_tree_uuid(struct btrfs_fs_info *fs_info, uuid_t new_fsid) { struct btrfs_root *root = btrfs_extent_root(fs_info, 0); - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key = {0, 0, 0}; int ret = 0; - btrfs_init_path(&path); /* * Here we don't use transaction as it will takes a lot of reserve * space, and that will make a near-full btrfs unable to change uuid @@ -161,11 +160,10 @@ static int change_device_uuid(struct extent_buffer *eb, int slot, static int change_chunk_tree_uuid(struct btrfs_root *root, uuid_t new_fsid) { - struct btrfs_path path; + struct btrfs_path path = {}; struct btrfs_key key = {0, 0, 0}; int ret = 0; - btrfs_init_path(&path); /* No transaction again */ ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0); if (ret < 0) From patchwork Sat Apr 29 20:19:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227092 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64277C7EE24 for ; Sat, 29 Apr 2023 20:20:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230305AbjD2UU2 (ORCPT ); Sat, 29 Apr 2023 16:20:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45474 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230244AbjD2UUY (ORCPT ); Sat, 29 Apr 2023 16:20:24 -0400 Received: from mail-yb1-xb35.google.com (mail-yb1-xb35.google.com [IPv6:2607:f8b0:4864:20::b35]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E32B21FCA for ; Sat, 29 Apr 2023 13:20:22 -0700 (PDT) Received: by mail-yb1-xb35.google.com with SMTP id 3f1490d57ef6-b9965b0b5e9so800693276.1 for ; Sat, 29 Apr 2023 13:20:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799622; x=1685391622; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=dBY++4kd5hHCLhE0awQpLGoynre+5dBjKiGxb7dAMTE=; b=qrZ37TvQ36841NcOYjX1CMYR7Ek83xKtDtJYEEC0gc0x0fwIj4n8Tieli7ze8+mYPQ eSIj20KDpr5lJXiRYyndcfJPlH23ZkFmsEdLDp8xI0Nd9Rhgx7RCyATQZUTYCIynz0ul L/jmKp1xzd4kSseu00Im5KaMzsxHJSwsmb5pxt5FEMXxqN5fI2jgefLTsXfpnJIJXlmM HsiehRQ37mwOq6fUuC77hww3hvwoFAkAYUfIZDocRIAYG1v6gg4TMZ5r5F6Qh8MnxVkJ bMdGVLLIyIRi+TrYTgVi2e2DZWsXpcbaBOiCNPLHRiBDH/XrfT/Zkf0oFaqZkcoo7z19 XV+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799622; x=1685391622; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=dBY++4kd5hHCLhE0awQpLGoynre+5dBjKiGxb7dAMTE=; b=g5Cu0aT3eCHQyIr3F2kcoMpyb2n625gFErpupxcRVTjcaTcvpTj5POE7ZsTYeurz80 Mm9q/xbFjivu6GOkoNJ31UzqtCDlocqz9SYfwIn/2NBQB50HgOyz+9s4exMWoaKR/Oj8 t3A1g6oVotUWQ6xyhRsEsOOLLNJYZGRnGAS4VBMWNXQPkmLZYqlPIKvFj2V7ikkkgRHT EIZ0FtNSOHgHY+tlPwwmlsktKMAuU+kbrUnLEGUUHe5WQGK/BIgbLm7iICWTa7cKUepu 0q/y6P99b8y1DBt9OMO4BUEcOU9tO8vV7unC82PYmLBtPdv0WZfyZJgn+AhR8rNy36Ws 2DiA== X-Gm-Message-State: AC+VfDyMnTFsOJcJhJy2+aPygg0FMNCdJ0egiiPFuuzya7wYmjT3JBCz sIC2una5JUCVTx49J9CdTID+oAsY+faOM7rMNb7czA== X-Google-Smtp-Source: ACHHUZ63qQFMj9DhsH1DHELDWJnm07oJUA1bzl8QG6yVxy//HH7htWSwuFIQH2lH9Nx5ZYTpSKIGFg== X-Received: by 2002:a81:4890:0:b0:54f:881e:75bb with SMTP id v138-20020a814890000000b0054f881e75bbmr7526670ywa.45.1682799621691; Sat, 29 Apr 2023 13:20:21 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id p71-20020a0de64a000000b00552e1d1ac1esm6295640ywe.13.2023.04.29.13.20.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:21 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 15/26] btrfs-progs: move btrfs_set_item_key_unsafe to check/ Date: Sat, 29 Apr 2023 16:19:46 -0400 Message-Id: <21fa88f1877d3c8c10434068c369f508acfcbe00.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This helper exists for check and for btrfs-corrupt-block. Move the helper and the btrfs_fixup_low_keys helper into check/repair.[ch] so we can keep the kernel-shared sources close to the upstream kernel. Signed-off-by: Josef Bacik --- btrfs-corrupt-block.c | 1 + check/repair.c | 47 +++++++++++++++++++++++++++++++++++++++++++ check/repair.h | 5 +++++ kernel-shared/ctree.c | 40 +++++++++--------------------------- kernel-shared/ctree.h | 5 ----- 5 files changed, 62 insertions(+), 36 deletions(-) diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c index 98cfe598..a97c3b90 100644 --- a/btrfs-corrupt-block.c +++ b/btrfs-corrupt-block.c @@ -35,6 +35,7 @@ #include "common/messages.h" #include "common/string-utils.h" #include "cmds/commands.h" +#include "check/repair.h" #define FIELD_BUF_LEN 80 diff --git a/check/repair.c b/check/repair.c index c5afbaa1..d1407947 100644 --- a/check/repair.c +++ b/check/repair.c @@ -33,6 +33,53 @@ int opt_check_repair = 0; +/* + * adjust the pointers going up the tree, starting at level + * making sure the right key of each node is points to 'key'. + * This is used after shifting pointers to the left, so it stops + * fixing up pointers when a given leaf/node is not in slot 0 of the + * higher levels + */ +void btrfs_fixup_low_keys(struct btrfs_path *path, struct btrfs_disk_key *key, + int level) +{ + int i; + struct extent_buffer *t; + + for (i = level; i < BTRFS_MAX_LEVEL; i++) { + int tslot = path->slots[i]; + if (!path->nodes[i]) + break; + t = path->nodes[i]; + btrfs_set_node_key(t, key, tslot); + btrfs_mark_buffer_dirty(path->nodes[i]); + if (tslot != 0) + break; + } +} + +/* + * update an item key without the safety checks. This is meant to be called by + * fsck only. + */ +void btrfs_set_item_key_unsafe(struct btrfs_root *root, + struct btrfs_path *path, + struct btrfs_key *new_key) +{ + struct btrfs_disk_key disk_key; + struct extent_buffer *eb; + int slot; + + eb = path->nodes[0]; + slot = path->slots[0]; + + btrfs_cpu_key_to_disk(&disk_key, new_key); + btrfs_set_item_key(eb, &disk_key, slot); + btrfs_mark_buffer_dirty(eb); + if (slot == 0) + btrfs_fixup_low_keys(path, &disk_key, 1); +} + int btrfs_add_corrupt_extent_record(struct btrfs_fs_info *info, struct btrfs_key *first_key, u64 start, u64 len, int level) diff --git a/check/repair.h b/check/repair.h index d4222600..010cd391 100644 --- a/check/repair.h +++ b/check/repair.h @@ -45,4 +45,9 @@ int btrfs_mark_used_blocks(struct btrfs_fs_info *fs_info, struct extent_io_tree *tree); enum btrfs_tree_block_status btrfs_check_block_for_repair(struct extent_buffer *eb, struct btrfs_key *first_key); +void btrfs_set_item_key_unsafe(struct btrfs_root *root, + struct btrfs_path *path, + struct btrfs_key *new_key); +void btrfs_fixup_low_keys(struct btrfs_path *path, struct btrfs_disk_key *key, + int level); #endif diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 9ade5fca..68c270ee 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -1321,8 +1321,8 @@ again: * fixing up pointers when a given leaf/node is not in slot 0 of the * higher levels */ -void btrfs_fixup_low_keys( struct btrfs_path *path, struct btrfs_disk_key *key, - int level) +static void fixup_low_keys(struct btrfs_path *path, struct btrfs_disk_key *key, + int level) { int i; struct extent_buffer *t; @@ -1368,29 +1368,7 @@ void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, btrfs_set_item_key(eb, &disk_key, slot); btrfs_mark_buffer_dirty(eb); if (slot == 0) - btrfs_fixup_low_keys(path, &disk_key, 1); -} - -/* - * update an item key without the safety checks. This is meant to be called by - * fsck only. - */ -void btrfs_set_item_key_unsafe(struct btrfs_root *root, - struct btrfs_path *path, - struct btrfs_key *new_key) -{ - struct btrfs_disk_key disk_key; - struct extent_buffer *eb; - int slot; - - eb = path->nodes[0]; - slot = path->slots[0]; - - btrfs_cpu_key_to_disk(&disk_key, new_key); - btrfs_set_item_key(eb, &disk_key, slot); - btrfs_mark_buffer_dirty(eb); - if (slot == 0) - btrfs_fixup_low_keys(path, &disk_key, 1); + fixup_low_keys(path, &disk_key, 1); } /* @@ -2056,7 +2034,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root btrfs_mark_buffer_dirty(right); btrfs_item_key(right, &disk_key, 0); - btrfs_fixup_low_keys(path, &disk_key, 1); + fixup_low_keys(path, &disk_key, 1); /* then fixup the leaf pointer in the path */ if (path->slots[0] < push_items) { @@ -2286,7 +2264,7 @@ again: path->nodes[0] = right; path->slots[0] = 0; if (path->slots[1] == 0) - btrfs_fixup_low_keys(path, &disk_key, 1); + fixup_low_keys(path, &disk_key, 1); } btrfs_mark_buffer_dirty(right); return ret; @@ -2491,7 +2469,7 @@ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) btrfs_set_disk_key_offset(&disk_key, offset + size_diff); btrfs_set_item_key(leaf, &disk_key, slot); if (slot == 0) - btrfs_fixup_low_keys(path, &disk_key, 1); + fixup_low_keys(path, &disk_key, 1); } btrfs_set_item_size(leaf, slot, new_size); @@ -2655,7 +2633,7 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, ret = 0; if (slot == 0) { btrfs_cpu_key_to_disk(&disk_key, cpu_key); - btrfs_fixup_low_keys(path, &disk_key, 1); + fixup_low_keys(path, &disk_key, 1); } if (btrfs_leaf_free_space(leaf) < 0) { @@ -2728,7 +2706,7 @@ int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, struct btrfs_disk_key disk_key; btrfs_node_key(parent, &disk_key, 0); - btrfs_fixup_low_keys(path, &disk_key, level + 1); + fixup_low_keys(path, &disk_key, level + 1); } btrfs_mark_buffer_dirty(parent); return ret; @@ -2826,7 +2804,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_disk_key disk_key; btrfs_item_key(leaf, &disk_key, 0); - btrfs_fixup_low_keys(path, &disk_key, 1); + fixup_low_keys(path, &disk_key, 1); } /* delete the leaf if it is mostly empty */ diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 3ff11dd0..d7b386db 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -1051,14 +1051,9 @@ static inline int btrfs_next_item(struct btrfs_root *root, int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); int btrfs_leaf_free_space(struct extent_buffer *leaf); -void btrfs_fixup_low_keys(struct btrfs_path *path, struct btrfs_disk_key *key, - int level); void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, struct btrfs_path *path, const struct btrfs_key *new_key); -void btrfs_set_item_key_unsafe(struct btrfs_root *root, - struct btrfs_path *path, - struct btrfs_key *new_key); u16 btrfs_super_csum_size(const struct btrfs_super_block *s); const char *btrfs_super_csum_name(u16 csum_type); From patchwork Sat Apr 29 20:19:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227096 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C09BDC77B7F for ; Sat, 29 Apr 2023 20:20:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230346AbjD2UUd (ORCPT ); Sat, 29 Apr 2023 16:20:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45570 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230291AbjD2UU1 (ORCPT ); Sat, 29 Apr 2023 16:20:27 -0400 Received: from mail-yb1-xb34.google.com (mail-yb1-xb34.google.com [IPv6:2607:f8b0:4864:20::b34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 487F9198A for ; Sat, 29 Apr 2023 13:20:24 -0700 (PDT) Received: by mail-yb1-xb34.google.com with SMTP id 3f1490d57ef6-b9daef8681fso380613276.1 for ; Sat, 29 Apr 2023 13:20:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799623; x=1685391623; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=CFiLDffUY2P8Hj97VdNTG5/ErorwuoC6NIuWFWZyjMM=; b=xYXIFk2Vk953fRzzb5ae5VFb8se1dGYkS6f01MWUCo4vCXI+YVpWBDHs0U6YYJ4qFm Df3FG4XekP+2nXMwZjP6jP/j+1o8KrYyZYAEpWdjUiwJV+AAa6lCMfU4apD2wYuPZrY5 EcOmOvuHuxhOVnp9mPO0PlO8xfwI44Cg6X2WsbkkgszO6JWS5UFoXCTyhJBxMAzPRgg5 y35XScoP+4kmS4/e/DItJL9w/CbLJsWmjT8om270U++Xg6UZ44+7ebPN6dudjYuNq66/ B8xb6Gc899AJenpx3Sqb8inG+2B6W52G3A5V4GwniugU96zAw7EAus5orb0+uEtRTorh 5acA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799623; x=1685391623; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CFiLDffUY2P8Hj97VdNTG5/ErorwuoC6NIuWFWZyjMM=; b=K/oMtcGNZqSQaJ916S540K8ZWdOnTEi/QDLMARFLiH1s1kJ45O9imREwkHH7D+JMhI elqZOGh0cCV3ujpOY8KTuQ6eSt/PIuPryqkHM/jOXMPISA7rtV1pnVYE6uQH6Z0UC3Pu JITq4jfs2t5DU2dDxBPcXYkeRT/ZNEVkH8e4sPlVg3k1rg1Q6+LRXURwVXSAPsTN0O13 VGMAKZpR37Z5dQ5qk7eOhPThL10H4YzE0fsfRPBcZHtM3c83B3y60q9bKXWUY9hmYPl4 NCh1RjGx5E7I8Ft6PW/UACdABKr/Spam6RPeWF2b4Sh6gxsXojCW8R+NuzWuraPxWmzI T41g== X-Gm-Message-State: AC+VfDxyIA3t2/fWz3xvT1g91XFMYHwsrIVqgyCJmdzA8QdXFOpCgZ+G byg6o0yPjPhhU+M7b3F8DbAhlDUY/FH3MEvpHoQ5UA== X-Google-Smtp-Source: ACHHUZ4xjk21j7B+DC5SVpfXf3GmdmdFNtDcZCaHRdEa6AG2ed++xVeLnWd6mWne7Er65sgdQKnmpg== X-Received: by 2002:a81:7345:0:b0:545:637c:3ed7 with SMTP id o66-20020a817345000000b00545637c3ed7mr6427606ywc.1.1682799622898; Sat, 29 Apr 2023 13:20:22 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id m11-20020a81710b000000b00555e1886350sm6281002ywc.78.2023.04.29.13.20.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:22 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 16/26] btrfs-progs: move btrfs_record_file_extent and code into a new file Date: Sat, 29 Apr 2023 16:19:47 -0400 Message-Id: <51bd817f87867d61a5b209ea6a8634e04cf1d20d.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This function and it's related functions only exist for the utilities that populate existing file systems, and do not exist in the upstream kernel. Move this function and the related function into it's own common source file and out of the kernel-shared sources, and then update all of the users to include the new location of this code. Signed-off-by: Josef Bacik --- Makefile | 1 + btrfs-map-logical.c | 1 + common/extent-tree-utils.c | 282 ++++++++++++++++++++++++++++++++++++ common/extent-tree-utils.h | 28 ++++ convert/main.c | 1 + convert/source-fs.c | 1 + kernel-shared/ctree.c | 24 --- kernel-shared/ctree.h | 7 - kernel-shared/extent-tree.c | 234 ------------------------------ mkfs/rootdir.c | 1 + 10 files changed, 315 insertions(+), 265 deletions(-) create mode 100644 common/extent-tree-utils.c create mode 100644 common/extent-tree-utils.h diff --git a/Makefile b/Makefile index 6806d347..09e12d06 100644 --- a/Makefile +++ b/Makefile @@ -196,6 +196,7 @@ objects = \ common/device-scan.o \ common/device-utils.o \ common/extent-cache.o \ + common/extent-tree-utils.o \ common/filesystem-utils.o \ common/format-output.o \ common/fsfeatures.o \ diff --git a/btrfs-map-logical.c b/btrfs-map-logical.c index 19514e40..8631774c 100644 --- a/btrfs-map-logical.c +++ b/btrfs-map-logical.c @@ -33,6 +33,7 @@ #include "common/utils.h" #include "common/help.h" #include "common/extent-cache.h" +#include "common/extent-tree-utils.h" #include "common/string-utils.h" #include "cmds/commands.h" diff --git a/common/extent-tree-utils.c b/common/extent-tree-utils.c new file mode 100644 index 00000000..06d5436f --- /dev/null +++ b/common/extent-tree-utils.c @@ -0,0 +1,282 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#include "kerncompat.h" +#include "kernel-shared/ctree.h" +#include "kernel-shared/disk-io.h" +#include "kernel-shared/file-item.h" +#include "kernel-shared/transaction.h" +#include "kernel-shared/free-space-tree.h" +#include "common/internal.h" +#include "common/extent-tree-utils.h" +#include "common/messages.h" + +/* + * Search in extent tree to found next meta/data extent + * Caller needs to check for no-hole or skinny metadata features. + */ +int btrfs_next_extent_item(struct btrfs_root *root, struct btrfs_path *path, + u64 max_objectid) +{ + struct btrfs_key found_key; + int ret; + + while (1) { + ret = btrfs_next_item(root, path); + if (ret) + return ret; + btrfs_item_key_to_cpu(path->nodes[0], &found_key, + path->slots[0]); + if (found_key.objectid > max_objectid) + return 1; + if (found_key.type == BTRFS_EXTENT_ITEM_KEY || + found_key.type == BTRFS_METADATA_ITEM_KEY) + return 0; + } +} + +static void __get_extent_size(struct btrfs_root *root, struct btrfs_path *path, + u64 *start, u64 *len) +{ + struct btrfs_key key; + + btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); + BUG_ON(!(key.type == BTRFS_EXTENT_ITEM_KEY || + key.type == BTRFS_METADATA_ITEM_KEY)); + *start = key.objectid; + if (key.type == BTRFS_EXTENT_ITEM_KEY) + *len = key.offset; + else + *len = root->fs_info->nodesize; +} + +/* + * Find first overlap extent for range [bytenr, bytenr + len) + * Return 0 for found and point path to it. + * Return >0 for not found. + * Return <0 for err + */ +static int btrfs_search_overlap_extent(struct btrfs_root *root, + struct btrfs_path *path, u64 bytenr, u64 len) +{ + struct btrfs_key key; + u64 cur_start; + u64 cur_len; + int ret; + + key.objectid = bytenr; + key.type = BTRFS_EXTENT_DATA_KEY; + key.offset = (u64)-1; + + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) + return ret; + BUG_ON(ret == 0); + + ret = btrfs_previous_extent_item(root, path, 0); + if (ret < 0) + return ret; + /* no previous, check next extent */ + if (ret > 0) + goto next; + __get_extent_size(root, path, &cur_start, &cur_len); + /* Tail overlap */ + if (cur_start + cur_len > bytenr) + return 1; + +next: + ret = btrfs_next_extent_item(root, path, bytenr + len); + if (ret < 0) + return ret; + /* No next, prev already checked, no overlap */ + if (ret > 0) + return 0; + __get_extent_size(root, path, &cur_start, &cur_len); + /* head overlap*/ + if (cur_start < bytenr + len) + return 1; + return 0; +} + +static int __btrfs_record_file_extent(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 objectid, + struct btrfs_inode_item *inode, + u64 file_pos, u64 disk_bytenr, + u64 *ret_num_bytes) +{ + int ret; + struct btrfs_fs_info *info = root->fs_info; + struct btrfs_root *extent_root = btrfs_extent_root(info, disk_bytenr); + struct extent_buffer *leaf; + struct btrfs_file_extent_item *fi; + struct btrfs_key ins_key; + struct btrfs_path *path; + struct btrfs_extent_item *ei; + u64 nbytes; + u64 extent_num_bytes; + u64 extent_bytenr; + u64 extent_offset; + u64 num_bytes = *ret_num_bytes; + + /* + * @objectid should be an inode number, thus it must not be smaller + * than BTRFS_FIRST_FREE_OBJECTID. + */ + UASSERT(objectid >= BTRFS_FIRST_FREE_OBJECTID); + + /* + * All supported file system should not use its 0 extent. + * As it's for hole + * + * And hole extent has no size limit, no need to loop. + */ + if (disk_bytenr == 0) { + ret = btrfs_insert_file_extent(trans, root, objectid, + file_pos, disk_bytenr, + num_bytes, num_bytes); + return ret; + } + num_bytes = min_t(u64, num_bytes, BTRFS_MAX_EXTENT_SIZE); + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + /* First to check extent overlap */ + ret = btrfs_search_overlap_extent(extent_root, path, disk_bytenr, + num_bytes); + if (ret < 0) + goto fail; + if (ret > 0) { + /* Found overlap */ + u64 cur_start; + u64 cur_len; + + __get_extent_size(extent_root, path, &cur_start, &cur_len); + /* + * For convert case, this extent should be a subset of + * existing one. + */ + BUG_ON(disk_bytenr < cur_start); + + extent_bytenr = cur_start; + extent_num_bytes = cur_len; + extent_offset = disk_bytenr - extent_bytenr; + } else { + /* No overlap, create new extent */ + btrfs_release_path(path); + ins_key.objectid = disk_bytenr; + ins_key.offset = num_bytes; + ins_key.type = BTRFS_EXTENT_ITEM_KEY; + + ret = btrfs_insert_empty_item(trans, extent_root, path, + &ins_key, sizeof(*ei)); + if (ret == 0) { + leaf = path->nodes[0]; + ei = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_extent_item); + + btrfs_set_extent_refs(leaf, ei, 0); + btrfs_set_extent_generation(leaf, ei, trans->transid); + btrfs_set_extent_flags(leaf, ei, + BTRFS_EXTENT_FLAG_DATA); + btrfs_mark_buffer_dirty(leaf); + + ret = btrfs_update_block_group(trans, disk_bytenr, + num_bytes, 1, 0); + if (ret) + goto fail; + } else if (ret != -EEXIST) { + goto fail; + } + + ret = remove_from_free_space_tree(trans, disk_bytenr, num_bytes); + if (ret) + goto fail; + + btrfs_run_delayed_refs(trans, -1); + extent_bytenr = disk_bytenr; + extent_num_bytes = num_bytes; + extent_offset = 0; + } + btrfs_release_path(path); + ins_key.objectid = objectid; + ins_key.offset = file_pos; + ins_key.type = BTRFS_EXTENT_DATA_KEY; + ret = btrfs_insert_empty_item(trans, root, path, &ins_key, + sizeof(*fi)); + if (ret) + goto fail; + leaf = path->nodes[0]; + fi = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_file_extent_item); + btrfs_set_file_extent_generation(leaf, fi, trans->transid); + btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG); + btrfs_set_file_extent_disk_bytenr(leaf, fi, extent_bytenr); + btrfs_set_file_extent_disk_num_bytes(leaf, fi, extent_num_bytes); + btrfs_set_file_extent_offset(leaf, fi, extent_offset); + btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes); + btrfs_set_file_extent_ram_bytes(leaf, fi, extent_num_bytes); + btrfs_set_file_extent_compression(leaf, fi, 0); + btrfs_set_file_extent_encryption(leaf, fi, 0); + btrfs_set_file_extent_other_encoding(leaf, fi, 0); + btrfs_mark_buffer_dirty(leaf); + + nbytes = btrfs_stack_inode_nbytes(inode) + num_bytes; + btrfs_set_stack_inode_nbytes(inode, nbytes); + btrfs_release_path(path); + + ret = btrfs_inc_extent_ref(trans, extent_bytenr, extent_num_bytes, + 0, root->root_key.objectid, objectid, + file_pos - extent_offset); + if (ret) + goto fail; + ret = 0; + *ret_num_bytes = min(extent_num_bytes - extent_offset, num_bytes); +fail: + btrfs_free_path(path); + return ret; +} + +/* + * Record a file extent. Do all the required works, such as inserting + * file extent item, inserting extent item and backref item into extent + * tree and updating block accounting. + */ +int btrfs_record_file_extent(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 objectid, + struct btrfs_inode_item *inode, + u64 file_pos, u64 disk_bytenr, + u64 num_bytes) +{ + u64 cur_disk_bytenr = disk_bytenr; + u64 cur_file_pos = file_pos; + u64 cur_num_bytes = num_bytes; + int ret = 0; + + while (num_bytes > 0) { + ret = __btrfs_record_file_extent(trans, root, objectid, + inode, cur_file_pos, + cur_disk_bytenr, + &cur_num_bytes); + if (ret < 0) + break; + cur_disk_bytenr += cur_num_bytes; + cur_file_pos += cur_num_bytes; + num_bytes -= cur_num_bytes; + } + return ret; +} diff --git a/common/extent-tree-utils.h b/common/extent-tree-utils.h new file mode 100644 index 00000000..4a774dc2 --- /dev/null +++ b/common/extent-tree-utils.h @@ -0,0 +1,28 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef _EXTENT_TREE_UTILS_H_ +#define _EXTENT_TREE_UTILS_H_ + +int btrfs_next_extent_item(struct btrfs_root *root, struct btrfs_path *path, + u64 max_objectid); +int btrfs_record_file_extent(struct btrfs_trans_handle *trans, + struct btrfs_root *root, u64 objectid, + struct btrfs_inode_item *inode, + u64 file_pos, u64 disk_bytenr, + u64 num_bytes); + +#endif /* _EXTENT_TREE_UTILS_H_ */ diff --git a/convert/main.c b/convert/main.c index 78c8d76e..a8b74dfa 100644 --- a/convert/main.c +++ b/convert/main.c @@ -114,6 +114,7 @@ #include "common/device-scan.h" #include "common/box.h" #include "common/open-utils.h" +#include "common/extent-tree-utils.h" #include "cmds/commands.h" #include "check/repair.h" #include "mkfs/common.h" diff --git a/convert/source-fs.c b/convert/source-fs.c index d206fab6..cc82fdb6 100644 --- a/convert/source-fs.c +++ b/convert/source-fs.c @@ -24,6 +24,7 @@ #include "common/internal.h" #include "common/messages.h" #include "common/extent-cache.h" +#include "common/extent-tree-utils.h" #include "convert/common.h" #include "convert/source-fs.h" diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 68c270ee..96d25953 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -3042,30 +3042,6 @@ int btrfs_previous_extent_item(struct btrfs_root *root, return 1; } -/* - * Search in extent tree to found next meta/data extent - * Caller needs to check for no-hole or skinny metadata features. - */ -int btrfs_next_extent_item(struct btrfs_root *root, - struct btrfs_path *path, u64 max_objectid) -{ - struct btrfs_key found_key; - int ret; - - while (1) { - ret = btrfs_next_item(root, path); - if (ret) - return ret; - btrfs_item_key_to_cpu(path->nodes[0], &found_key, - path->slots[0]); - if (found_key.objectid > max_objectid) - return 1; - if (found_key.type == BTRFS_EXTENT_ITEM_KEY || - found_key.type == BTRFS_METADATA_ITEM_KEY) - return 0; - } -} - /* * Search uuid tree - unmounted * diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index d7b386db..cc71e2a5 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -928,11 +928,6 @@ int btrfs_make_block_groups(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info); int btrfs_update_block_group(struct btrfs_trans_handle *trans, u64 bytenr, u64 num, int alloc, int mark_free); -int btrfs_record_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 objectid, - struct btrfs_inode_item *inode, - u64 file_pos, u64 disk_bytenr, - u64 num_bytes); int btrfs_remove_block_group(struct btrfs_trans_handle *trans, u64 bytenr, u64 len); void free_excluded_extents(struct btrfs_fs_info *fs_info, @@ -955,8 +950,6 @@ int btrfs_previous_item(struct btrfs_root *root, int type); int btrfs_previous_extent_item(struct btrfs_root *root, struct btrfs_path *path, u64 min_objectid); -int btrfs_next_extent_item(struct btrfs_root *root, - struct btrfs_path *path, u64 max_objectid); int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, struct extent_buffer *parent, int parent_slot, diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index c2ff94f5..98c0b297 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -3520,240 +3520,6 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans, return ret; } -static void __get_extent_size(struct btrfs_root *root, struct btrfs_path *path, - u64 *start, u64 *len) -{ - struct btrfs_key key; - - btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]); - BUG_ON(!(key.type == BTRFS_EXTENT_ITEM_KEY || - key.type == BTRFS_METADATA_ITEM_KEY)); - *start = key.objectid; - if (key.type == BTRFS_EXTENT_ITEM_KEY) - *len = key.offset; - else - *len = root->fs_info->nodesize; -} - -/* - * Find first overlap extent for range [bytenr, bytenr + len) - * Return 0 for found and point path to it. - * Return >0 for not found. - * Return <0 for err - */ -static int btrfs_search_overlap_extent(struct btrfs_root *root, - struct btrfs_path *path, u64 bytenr, u64 len) -{ - struct btrfs_key key; - u64 cur_start; - u64 cur_len; - int ret; - - key.objectid = bytenr; - key.type = BTRFS_EXTENT_DATA_KEY; - key.offset = (u64)-1; - - ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); - if (ret < 0) - return ret; - BUG_ON(ret == 0); - - ret = btrfs_previous_extent_item(root, path, 0); - if (ret < 0) - return ret; - /* no previous, check next extent */ - if (ret > 0) - goto next; - __get_extent_size(root, path, &cur_start, &cur_len); - /* Tail overlap */ - if (cur_start + cur_len > bytenr) - return 1; - -next: - ret = btrfs_next_extent_item(root, path, bytenr + len); - if (ret < 0) - return ret; - /* No next, prev already checked, no overlap */ - if (ret > 0) - return 0; - __get_extent_size(root, path, &cur_start, &cur_len); - /* head overlap*/ - if (cur_start < bytenr + len) - return 1; - return 0; -} - -static int __btrfs_record_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 objectid, - struct btrfs_inode_item *inode, - u64 file_pos, u64 disk_bytenr, - u64 *ret_num_bytes) -{ - int ret; - struct btrfs_fs_info *info = root->fs_info; - struct btrfs_root *extent_root = btrfs_extent_root(info, disk_bytenr); - struct extent_buffer *leaf; - struct btrfs_file_extent_item *fi; - struct btrfs_key ins_key; - struct btrfs_path *path; - struct btrfs_extent_item *ei; - u64 nbytes; - u64 extent_num_bytes; - u64 extent_bytenr; - u64 extent_offset; - u64 num_bytes = *ret_num_bytes; - - /* - * @objectid should be an inode number, thus it must not be smaller - * than BTRFS_FIRST_FREE_OBJECTID. - */ - ASSERT(objectid >= BTRFS_FIRST_FREE_OBJECTID); - - /* - * All supported file system should not use its 0 extent. - * As it's for hole - * - * And hole extent has no size limit, no need to loop. - */ - if (disk_bytenr == 0) { - ret = btrfs_insert_file_extent(trans, root, objectid, - file_pos, disk_bytenr, - num_bytes, num_bytes); - return ret; - } - num_bytes = min_t(u64, num_bytes, BTRFS_MAX_EXTENT_SIZE); - - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - - /* First to check extent overlap */ - ret = btrfs_search_overlap_extent(extent_root, path, disk_bytenr, - num_bytes); - if (ret < 0) - goto fail; - if (ret > 0) { - /* Found overlap */ - u64 cur_start; - u64 cur_len; - - __get_extent_size(extent_root, path, &cur_start, &cur_len); - /* - * For convert case, this extent should be a subset of - * existing one. - */ - BUG_ON(disk_bytenr < cur_start); - - extent_bytenr = cur_start; - extent_num_bytes = cur_len; - extent_offset = disk_bytenr - extent_bytenr; - } else { - /* No overlap, create new extent */ - btrfs_release_path(path); - ins_key.objectid = disk_bytenr; - ins_key.offset = num_bytes; - ins_key.type = BTRFS_EXTENT_ITEM_KEY; - - ret = btrfs_insert_empty_item(trans, extent_root, path, - &ins_key, sizeof(*ei)); - if (ret == 0) { - leaf = path->nodes[0]; - ei = btrfs_item_ptr(leaf, path->slots[0], - struct btrfs_extent_item); - - btrfs_set_extent_refs(leaf, ei, 0); - btrfs_set_extent_generation(leaf, ei, trans->transid); - btrfs_set_extent_flags(leaf, ei, - BTRFS_EXTENT_FLAG_DATA); - btrfs_mark_buffer_dirty(leaf); - - ret = btrfs_update_block_group(trans, disk_bytenr, - num_bytes, 1, 0); - if (ret) - goto fail; - } else if (ret != -EEXIST) { - goto fail; - } - - ret = remove_from_free_space_tree(trans, disk_bytenr, num_bytes); - if (ret) - goto fail; - - btrfs_run_delayed_refs(trans, -1); - extent_bytenr = disk_bytenr; - extent_num_bytes = num_bytes; - extent_offset = 0; - } - btrfs_release_path(path); - ins_key.objectid = objectid; - ins_key.offset = file_pos; - ins_key.type = BTRFS_EXTENT_DATA_KEY; - ret = btrfs_insert_empty_item(trans, root, path, &ins_key, - sizeof(*fi)); - if (ret) - goto fail; - leaf = path->nodes[0]; - fi = btrfs_item_ptr(leaf, path->slots[0], - struct btrfs_file_extent_item); - btrfs_set_file_extent_generation(leaf, fi, trans->transid); - btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG); - btrfs_set_file_extent_disk_bytenr(leaf, fi, extent_bytenr); - btrfs_set_file_extent_disk_num_bytes(leaf, fi, extent_num_bytes); - btrfs_set_file_extent_offset(leaf, fi, extent_offset); - btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes); - btrfs_set_file_extent_ram_bytes(leaf, fi, extent_num_bytes); - btrfs_set_file_extent_compression(leaf, fi, 0); - btrfs_set_file_extent_encryption(leaf, fi, 0); - btrfs_set_file_extent_other_encoding(leaf, fi, 0); - btrfs_mark_buffer_dirty(leaf); - - nbytes = btrfs_stack_inode_nbytes(inode) + num_bytes; - btrfs_set_stack_inode_nbytes(inode, nbytes); - btrfs_release_path(path); - - ret = btrfs_inc_extent_ref(trans, extent_bytenr, extent_num_bytes, - 0, root->root_key.objectid, objectid, - file_pos - extent_offset); - if (ret) - goto fail; - ret = 0; - *ret_num_bytes = min(extent_num_bytes - extent_offset, num_bytes); -fail: - btrfs_free_path(path); - return ret; -} - -/* - * Record a file extent. Do all the required works, such as inserting - * file extent item, inserting extent item and backref item into extent - * tree and updating block accounting. - */ -int btrfs_record_file_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 objectid, - struct btrfs_inode_item *inode, - u64 file_pos, u64 disk_bytenr, - u64 num_bytes) -{ - u64 cur_disk_bytenr = disk_bytenr; - u64 cur_file_pos = file_pos; - u64 cur_num_bytes = num_bytes; - int ret = 0; - - while (num_bytes > 0) { - ret = __btrfs_record_file_extent(trans, root, objectid, - inode, cur_file_pos, - cur_disk_bytenr, - &cur_num_bytes); - if (ret < 0) - break; - cur_disk_bytenr += cur_num_bytes; - cur_file_pos += cur_num_bytes; - num_bytes -= cur_num_bytes; - } - return ret; -} - - static int add_excluded_extent(struct btrfs_fs_info *fs_info, u64 start, u64 num_bytes) { diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c index d6de3eba..91f97ed6 100644 --- a/mkfs/rootdir.c +++ b/mkfs/rootdir.c @@ -39,6 +39,7 @@ #include "common/internal.h" #include "common/messages.h" #include "common/path-utils.h" +#include "common/extent-tree-utils.h" #include "mkfs/rootdir.h" static u32 fs_block_size; From patchwork Sat Apr 29 20:19:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227093 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 111CFC77B7C for ; Sat, 29 Apr 2023 20:20:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230323AbjD2UU3 (ORCPT ); Sat, 29 Apr 2023 16:20:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230284AbjD2UUZ (ORCPT ); Sat, 29 Apr 2023 16:20:25 -0400 Received: from mail-yw1-x112f.google.com (mail-yw1-x112f.google.com [IPv6:2607:f8b0:4864:20::112f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC0F31FF5 for ; Sat, 29 Apr 2023 13:20:24 -0700 (PDT) Received: by mail-yw1-x112f.google.com with SMTP id 00721157ae682-54f8e823e47so16268987b3.2 for ; Sat, 29 Apr 2023 13:20:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799624; x=1685391624; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Y/QpagkIvkCEHFlz06VLWpboPR5ZjwVdSRT9NuDo2r8=; b=CEDb+cGt/q5gdIEALvyUAC9Bg4tnt10J+kLrgNtxZjFZ0oYP0fyr/sNJBP4SoQ0jFD YxTd66Lf+8p5XGZi6VxKkDRjf7NozD/BBJPDyGvz3K/mHR+pKJLr5rBrth+wAglzvEzE P8BZv8sB1WFYbHSsgNVTnyXXCigFRW0WcL+C7KTtEKytZbDDGRHZTa3RxwtuCYf19M2U R3IauSSe4TpeE/pvvyFTda6CGYv+9uLIkK0ldDJc6h4W2U5fjYeuZshFqLJ7U86IsYej hnHeGWgMWowmWkGmQczD3+5eariUpxX1x48O+Vjt9XrW1maaqMXcJ1UmepT+I5Ah1WGx H/jA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799624; x=1685391624; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y/QpagkIvkCEHFlz06VLWpboPR5ZjwVdSRT9NuDo2r8=; b=OlYqC7ec0lNd1ep6gm0hPyLmwHrkORzqeuEBYh0Dz7Yl3chmr2dK7CH/8EFJ6JxHGl b9NP63ZW2e3n5SCdd0O9opvdj0lrLfiK5xr3YA0OZYYwZZNwB6UW4+bDaGzXH05W1Aqe UL/OPbYXmqCqI/ZjNUnmoNSljjXTYH6ZZByToXU54L60bQiaYA+dFrK5YKOsYfdxBymQ xGNlsXcaA+krYhEmXhKIMJaJq98Edy4RZ2UivGd2c7SmPLduIB0p0cLTQGCuHWdrZPFm EHFGwYr6PL7kKxAzfAgaHOdK2TUgWrOVhGKjiwZNeBOMVoOO0q6nc6AyZ/J3i4WoXV9y 2Kfg== X-Gm-Message-State: AC+VfDyury8tNxoDAcsJ/RV5r4P4C6vJNn/vrBNwLoSpy7CZmkUEcWgH UK71wDIX3RkmlbjwWp3nKKRI0fm8CzHM01nOeQT5oA== X-Google-Smtp-Source: ACHHUZ40M3zYrEka2aaDWmZbOVRecCJZi5e/oJZDjmo52PpYVcR4AcUe/KImCWxpV/Fm+T9qWWXsPA== X-Received: by 2002:a81:ab4b:0:b0:559:e235:5f65 with SMTP id d11-20020a81ab4b000000b00559e2355f65mr2534090ywk.37.1682799624085; Sat, 29 Apr 2023 13:20:24 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id t192-20020a8183c9000000b00552f3887d16sm6232314ywf.22.2023.04.29.13.20.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:23 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 17/26] btrfs-progs: make a local copy of btrfs_next_sibling_block in print-tree.c Date: Sat, 29 Apr 2023 16:19:48 -0400 Message-Id: <152afd02fc3c024248a6e4f31b63e5dab1129231.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org We use this in print-tree to do BFS tree printing, but there are no other users and it doesn't exist upstream. Copy the current code and clean it up so it can exist in print-tree.c and use the local copy there. This will allow us to remove the function call when ctree.c is synced. Signed-off-by: Josef Bacik --- kernel-shared/print-tree.c | 53 +++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c index 9e9eb43a..5147f652 100644 --- a/kernel-shared/print-tree.c +++ b/kernel-shared/print-tree.c @@ -1498,6 +1498,57 @@ out: return ret; } +/* + * Walk up the tree as far as necessary to find the next sibling tree block. + * More generic version of btrfs_next_leaf(), as it could find sibling nodes + * if @path->lowest_level is not 0. + * + * returns 0 if it found something or 1 if there are no greater leaves. + * returns < 0 on io errors. + */ +int next_sibling_tree_block(struct btrfs_fs_info *fs_info, + struct btrfs_path *path) +{ + int slot; + int level = path->lowest_level + 1; + struct extent_buffer *c; + struct extent_buffer *next = NULL; + + BUG_ON(path->lowest_level + 1 >= BTRFS_MAX_LEVEL); + do { + if (!path->nodes[level]) + return 1; + + slot = path->slots[level] + 1; + c = path->nodes[level]; + if (slot >= btrfs_header_nritems(c)) { + level++; + if (level == BTRFS_MAX_LEVEL) + return 1; + continue; + } + + next = btrfs_read_node_slot(c, slot); + if (!extent_buffer_uptodate(next)) + return -EIO; + break; + } while (level < BTRFS_MAX_LEVEL); + path->slots[level] = slot; + while(1) { + level--; + c = path->nodes[level]; + free_extent_buffer(c); + path->nodes[level] = next; + path->slots[level] = 0; + if (level == path->lowest_level) + break; + next = btrfs_read_node_slot(next, 0); + if (!extent_buffer_uptodate(next)) + return -EIO; + } + return 0; +} + static void bfs_print_children(struct extent_buffer *root_eb, unsigned int mode) { struct btrfs_fs_info *fs_info = root_eb->fs_info; @@ -1528,7 +1579,7 @@ static void bfs_print_children(struct extent_buffer *root_eb, unsigned int mode) /* Print all sibling tree blocks */ while (1) { btrfs_print_tree(path.nodes[cur_level], mode); - ret = btrfs_next_sibling_tree_block(fs_info, &path); + ret = next_sibling_tree_block(fs_info, &path); if (ret < 0) goto out; if (ret > 0) { From patchwork Sat Apr 29 20:19:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227094 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 34E91C77B7F for ; Sat, 29 Apr 2023 20:20:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230326AbjD2UUa (ORCPT ); Sat, 29 Apr 2023 16:20:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45576 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230248AbjD2UU1 (ORCPT ); Sat, 29 Apr 2023 16:20:27 -0400 Received: from mail-yb1-xb35.google.com (mail-yb1-xb35.google.com [IPv6:2607:f8b0:4864:20::b35]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 266FC213B for ; Sat, 29 Apr 2023 13:20:26 -0700 (PDT) Received: by mail-yb1-xb35.google.com with SMTP id 3f1490d57ef6-b983027d0faso1694232276.0 for ; Sat, 29 Apr 2023 13:20:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799625; x=1685391625; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=BcC2hnCsatnYMvrBn30F5bFpiqpYNore5TaVS9jo++M=; b=lKPTp6lyWQVJq+R0BG0MLA2P0rGb8z1o8hwkFCKkZulHIso2GXR/gMbqAu1pcyzmxr H+0qikrAWVQd4WA3morD9iTA8harSv2mgg9YASV7wThSn0pMYbiPCurN7DoP4QiPxHfP TyITNXIE2OwstnlTwQYhade9PkaFjthkDYwkb+e9IW1nRBYTHDYofe3oF7PgUgAtk7RZ YxZuwwmgmDr+2oWfGTvx+eTJJpXZ/NhSXoJKtUijrc4zDtMzJr/8NTkeiR5urehjg1pi WOnTp9neTwzy3lizDEN726l4RHS4c6RdW9lWhPfXJUAww//U8s9DKKN7Fs33dzyPZxib a8ag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799625; x=1685391625; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BcC2hnCsatnYMvrBn30F5bFpiqpYNore5TaVS9jo++M=; b=PcT+1GkmAW5PJQXqwq8hTiLc8YPpNpzPwxRsqfOvftHQciU0p52TBBoEGpZtlvXjj/ ttoOBsx2loJSaH/SzlA4h/ClzZYPosq03Nq/poLoZNw7phhHLeElIg38FxQGWGp5qNtU kXKVjEK3QvtpOxUytS7yfyqXYlahbuuBlc/hmUebgLM+YeeLxQgUkqxDzMyeT/zKPUKZ K2eCNM6Ffuko8nNS/Jgx2VC7Th5kdds6hOqLwTXH7NUvu4l83Ppdc9nGkO0Y67rqXCb9 b0UtSE4LBgt5BXwSEIF5g9AOwTlaS//u2tps7pI806pfbEZ1V5NOzwgoJ8sA7T9qK09R QD3w== X-Gm-Message-State: AC+VfDxpMEmANaQwX6v6XRrnL4LnEXJH3JRr9pqNYEYF5EUMLdjb+6Yh FIgpSv+DJefHJR9JfQooJ4v9VKQcSuQy7p+jkBNfAA== X-Google-Smtp-Source: ACHHUZ693cRZ45CqjAone0rvryV3yz3RrBFkFkuWXi2YguYOe+DZjiZC2LZSpQlkX2/gYKpcr8IyUA== X-Received: by 2002:a25:d04c:0:b0:b95:5682:7db0 with SMTP id h73-20020a25d04c000000b00b9556827db0mr9227870ybg.13.1682799625075; Sat, 29 Apr 2023 13:20:25 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id 130-20020a250f88000000b00b92426aba45sm5878572ybp.57.2023.04.29.13.20.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:24 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 18/26] btrfs-progs: don't set the ->commit_root in btrfs_create_tree Date: Sat, 29 Apr 2023 16:19:49 -0400 Message-Id: <4a64fa21d07392cb7f109b0c9a362a57e926ebcc.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In btrfs_create_tree we set ->commit_root to the current node, however we don't add the root to the dirty list, so this is never cleaned up. This is a problem in btrfs-progs because the transaction commit stuff clears the commit_root when we write the dirty root out, so if we try to re-modify this root later we'll fail to start the transaction. Fix this by noting that we do this differently in the kernel, and drop the assignment as we're inserting the root into the tree_root in this function and thus don't need to update it again at transaction commit time. Signed-off-by: Josef Bacik --- kernel-shared/disk-io.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index b7a98c4c..ec97ff08 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -2384,7 +2384,14 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(leaf); extent_buffer_get(root->node); - root->commit_root = root->node; + + /* + * MODIFIED: + * - In the kernel we set ->commit_root here, however in btrfs-progs + * confuses the transaction code. For now don't set the commit_root + * here, if we update transaction.c to match the kernel version we + * need to revisit this. + */ set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state); root->root_item.flags = 0; From patchwork Sat Apr 29 20:19:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227095 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7E526C77B7C for ; Sat, 29 Apr 2023 20:20:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230352AbjD2UUe (ORCPT ); Sat, 29 Apr 2023 16:20:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45634 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230312AbjD2UU2 (ORCPT ); Sat, 29 Apr 2023 16:20:28 -0400 Received: from mail-yb1-xb2e.google.com (mail-yb1-xb2e.google.com [IPv6:2607:f8b0:4864:20::b2e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 62D342710 for ; Sat, 29 Apr 2023 13:20:27 -0700 (PDT) Received: by mail-yb1-xb2e.google.com with SMTP id 3f1490d57ef6-b9a6eec8611so14247644276.0 for ; Sat, 29 Apr 2023 13:20:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799626; x=1685391626; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=pEoZc+nEXW3E34N4qvHm3Kt4zypq/oZE+Vhd2LMh5uY=; b=gsYURdd7Yq/1tcJjX8XiYv2qeEwCFSJ6gmaNXZYDF47bZu9aJLvv3rzV4YbF+dste9 jogr35WGjn3OMZU6Pt0IueVJj40Zz1VfVxajSB4dDTrvOeNPCh53u/sKKcUMzrGvK3J8 OPRByELxVES5pQjJhymjhHnlIDuCfsgChq9aqPCqKtc3IxKX3IkS2aRuDqP2KcDQnzaN 3OTWGHEy8fbKOCf1nT1QwzlI9cjnWotLbFzoC6TvPx2Vw/qSOirwdMQoeJbPJb7wE7mW 4DdMG3N7Ds12TunaGNhFLh00ESHJ9dmY0Whh9MqkFgu/7kK3cPKLPYz7uOCETwVFUczh /YfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799626; x=1685391626; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pEoZc+nEXW3E34N4qvHm3Kt4zypq/oZE+Vhd2LMh5uY=; b=F8VcsmLZKADgdR4K/RJenPNrPXYC3TCvHl90S4yvUwISOEHkw6zQXfYPz0DHt35ZCG SXERxYgCWWYj7efJnovPsPbJVKl65T9zRQn/aEdzH75K4ImpjnTAJUCfapPklJZNvkiv thEvnHmnDG5f9fX05bV7nDNfnGks0Pozvf2udiai4DeXf1/DLYF2hUkGPyetaLhqs3PP cE06zTPSHwcrxVooYX4sRqA8/0cBB9QrnFHOsrgeDN4dzqAapTe0ua8er54yZrgNbTPO qpZzXykbkwLimEKfd6gz60dBWVzxG2ytRUWMvzJj0xCps/yIey7xWwRgqX3DSs108A1v xBtg== X-Gm-Message-State: AC+VfDwqvtRhUeOaSJtTeu4MUW1gCWoPZh7aDMoHjxYV5wYQ5rZ6cevX n8FuRUixYfP9EXHZLVLCRQkYIXtHpvJHfQZ5Le8OiQ== X-Google-Smtp-Source: ACHHUZ6H4+ogIkWkVCmDcle9bECW/VSE9a6rdOp+Yd79T2x5H0TuqkrxxDUDXHPedHDuKdcT+PYshQ== X-Received: by 2002:a81:6d14:0:b0:54f:a8cf:6b48 with SMTP id i20-20020a816d14000000b0054fa8cf6b48mr8538385ywc.10.1682799626244; Sat, 29 Apr 2023 13:20:26 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id i198-20020a816dcf000000b005463239c01esm6361622ywc.51.2023.04.29.13.20.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:25 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 19/26] btrfs-progs: remove btrfs_create_root Date: Sat, 29 Apr 2023 16:19:50 -0400 Message-Id: <69cbc6a5d3d222301046cbf91cf27ed26c61aef3.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org We have btrfs_create_root and btrfs_create_tree that do essentially the same thing. However btrfs_create_root isn't in the kernel, and btrfs_create_tree is. Update all of the callers of btrfs_create_root to use btrfs_create_tree instead and then remove btrfs_create_root. Signed-off-by: Josef Bacik --- kernel-shared/ctree.c | 123 ------------------------------------------ kernel-shared/ctree.h | 2 - mkfs/main.c | 14 +++-- tune/change-csum.c | 11 +++- tune/convert-bgt.c | 13 +++-- 5 files changed, 29 insertions(+), 134 deletions(-) diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 96d25953..327ff40c 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -193,129 +193,6 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, return 0; } -/* - * Create a new tree root, with root objectid set to @objectid. - * - * NOTE: Doesn't support tree with non-zero offset, like data reloc tree. - */ -int btrfs_create_root(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info, u64 objectid) -{ - struct extent_buffer *node; - struct btrfs_root *new_root; - struct btrfs_disk_key disk_key; - struct btrfs_key location; - struct btrfs_root_item root_item = { 0 }; - int ret; - - new_root = malloc(sizeof(*new_root)); - if (!new_root) - return -ENOMEM; - - btrfs_setup_root(new_root, fs_info, objectid); - if (!is_fstree(objectid)) - set_bit(BTRFS_ROOT_TRACK_DIRTY, &new_root->state); - add_root_to_dirty_list(new_root); - - new_root->objectid = objectid; - new_root->root_key.objectid = objectid; - new_root->root_key.type = BTRFS_ROOT_ITEM_KEY; - new_root->root_key.offset = 0; - - node = btrfs_alloc_tree_block(trans, new_root, fs_info->nodesize, - objectid, &disk_key, 0, 0, 0, - BTRFS_NESTING_NORMAL); - if (IS_ERR(node)) { - ret = PTR_ERR(node); - error("failed to create root node for tree %llu: %d (%m)", - objectid, ret); - return ret; - } - new_root->node = node; - - memset_extent_buffer(node, 0, 0, sizeof(struct btrfs_header)); - btrfs_set_header_bytenr(node, node->start); - btrfs_set_header_generation(node, trans->transid); - btrfs_set_header_backref_rev(node, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(node, objectid); - write_extent_buffer(node, fs_info->fs_devices->metadata_uuid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); - write_extent_buffer(node, fs_info->chunk_tree_uuid, - btrfs_header_chunk_tree_uuid(node), - BTRFS_UUID_SIZE); - btrfs_set_header_nritems(node, 0); - btrfs_set_header_level(node, 0); - ret = btrfs_inc_ref(trans, new_root, node, 0); - if (ret < 0) - goto free; - - /* - * Special tree roots may need to modify pointers in @fs_info - * Only quota is supported yet. - */ - switch (objectid) { - case BTRFS_QUOTA_TREE_OBJECTID: - if (fs_info->quota_root) { - error("quota root already exists"); - ret = -EEXIST; - goto free; - } - fs_info->quota_root = new_root; - fs_info->quota_enabled = 1; - break; - case BTRFS_BLOCK_GROUP_TREE_OBJECTID: - if (fs_info->block_group_root) { - error("bg root already exists"); - ret = -EEXIST; - goto free; - } - fs_info->block_group_root = new_root; - break; - - case BTRFS_CSUM_TREE_TMP_OBJECTID: - fs_info->csum_tree_tmp = new_root; - break; - /* - * Essential trees can't be created by this function, yet. - * As we expect such skeleton exists, or a lot of functions like - * btrfs_alloc_tree_block() doesn't work at all - */ - case BTRFS_ROOT_TREE_OBJECTID: - case BTRFS_EXTENT_TREE_OBJECTID: - case BTRFS_CHUNK_TREE_OBJECTID: - case BTRFS_FS_TREE_OBJECTID: - ret = -EEXIST; - goto free; - default: - /* Subvolume trees don't need special handling */ - if (is_fstree(objectid)) - break; - /* Other special trees are not supported yet */ - ret = -ENOTTY; - goto free; - } - btrfs_mark_buffer_dirty(node); - btrfs_set_root_bytenr(&root_item, btrfs_header_bytenr(node)); - btrfs_set_root_level(&root_item, 0); - btrfs_set_root_generation(&root_item, trans->transid); - btrfs_set_root_dirid(&root_item, 0); - btrfs_set_root_refs(&root_item, 1); - btrfs_set_root_used(&root_item, fs_info->nodesize); - location.objectid = objectid; - location.type = BTRFS_ROOT_ITEM_KEY; - location.offset = 0; - - ret = btrfs_insert_root(trans, fs_info->tree_root, &location, &root_item); - if (ret < 0) - goto free; - return ret; - -free: - free_extent_buffer(node); - free(new_root); - return ret; -} - /* * check if the tree block can be shared by multiple trees */ diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index cc71e2a5..ce1c3d25 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -958,8 +958,6 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, struct extent_buffer **cow_ret, u64 new_root_objectid); -int btrfs_create_root(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info, u64 objectid); void btrfs_extend_item(struct btrfs_path *path, u32 data_size); void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end); int btrfs_split_item(struct btrfs_trans_handle *trans, diff --git a/mkfs/main.c b/mkfs/main.c index e0b589cd..88fea33b 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -883,7 +883,10 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info) struct btrfs_qgroup_status_item *qsi; struct btrfs_root *quota_root; struct btrfs_path path = {}; - struct btrfs_key key; + struct btrfs_key key = { + .objectid = BTRFS_QUOTA_TREE_OBJECTID, + .type = BTRFS_ROOT_ITEM_KEY, + }; int qgroup_repaired = 0; int ret; @@ -895,12 +898,15 @@ static int setup_quota_root(struct btrfs_fs_info *fs_info) error_msg(ERROR_MSG_START_TRANS, "%m"); return ret; } - ret = btrfs_create_root(trans, fs_info, BTRFS_QUOTA_TREE_OBJECTID); - if (ret < 0) { + + quota_root = btrfs_create_tree(trans, fs_info, &key); + if (IS_ERR(quota_root)) { + ret = PTR_ERR(quota_root); error("failed to create quota root: %d (%m)", ret); goto fail; } - quota_root = fs_info->quota_root; + fs_info->quota_root = quota_root; + fs_info->quota_enabled = 1; key.objectid = 0; key.type = BTRFS_QGROUP_STATUS_KEY; diff --git a/tune/change-csum.c b/tune/change-csum.c index f7917f0b..e75d0d9f 100644 --- a/tune/change-csum.c +++ b/tune/change-csum.c @@ -410,6 +410,11 @@ int rewrite_checksums(struct btrfs_fs_info *fs_info, int csum_type) return ret; if (ret == 1) { + struct btrfs_root *tmp; + struct btrfs_key key = { + .objectid = BTRFS_CSUM_TREE_TMP_OBJECTID, + .type = BTRFS_ROOT_ITEM_KEY, + }; struct item { u64 offset; u64 generation; @@ -421,10 +426,12 @@ int rewrite_checksums(struct btrfs_fs_info *fs_info, int csum_type) */ } item[1]; - ret = btrfs_create_root(trans, fs_info, BTRFS_CSUM_TREE_TMP_OBJECTID); - if (ret < 0) { + tmp = btrfs_create_tree(trans, fs_info, &key); + if (IS_ERR(tmp)) { + ret = PTR_ERR(tmp); return ret; } else { + fs_info->csum_tree_tmp = tmp; item->offset = btrfs_header_bytenr(fs_info->csum_tree_tmp->node); item->generation = btrfs_super_generation(fs_info->super_copy); item->csum_type = csum_type; diff --git a/tune/convert-bgt.c b/tune/convert-bgt.c index 79d9169e..cdd0a007 100644 --- a/tune/convert-bgt.c +++ b/tune/convert-bgt.c @@ -30,7 +30,12 @@ int convert_to_bg_tree(struct btrfs_fs_info *fs_info) { struct btrfs_super_block *sb = fs_info->super_copy; struct btrfs_trans_handle *trans; + struct btrfs_root *root; struct cache_extent *ce; + struct btrfs_key key = { + .objectid = BTRFS_BLOCK_GROUP_TREE_OBJECTID, + .type = BTRFS_ROOT_ITEM_KEY, + }; int converted_bgs = 0; int ret; @@ -50,12 +55,14 @@ int convert_to_bg_tree(struct btrfs_fs_info *fs_info) if (btrfs_super_flags(sb) & BTRFS_SUPER_FLAG_CHANGING_BG_TREE) goto iterate_bgs; - ret = btrfs_create_root(trans, fs_info, - BTRFS_BLOCK_GROUP_TREE_OBJECTID); - if (ret < 0) { + root = btrfs_create_tree(trans, fs_info, &key); + if (IS_ERR(root)) { + ret = PTR_ERR(root); error("failed to create block group root: %d", ret); goto error; } + fs_info->block_group_root = root; + btrfs_set_super_flags(sb, btrfs_super_flags(sb) | BTRFS_SUPER_FLAG_CHANGING_BG_TREE); From patchwork Sat Apr 29 20:19:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227098 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B910C7EE23 for ; Sat, 29 Apr 2023 20:20:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230359AbjD2UUf (ORCPT ); Sat, 29 Apr 2023 16:20:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45666 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230324AbjD2UU3 (ORCPT ); Sat, 29 Apr 2023 16:20:29 -0400 Received: from mail-yw1-x112a.google.com (mail-yw1-x112a.google.com [IPv6:2607:f8b0:4864:20::112a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5F11B2701 for ; Sat, 29 Apr 2023 13:20:28 -0700 (PDT) Received: by mail-yw1-x112a.google.com with SMTP id 00721157ae682-54fc1824f0bso16725877b3.0 for ; Sat, 29 Apr 2023 13:20:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799627; x=1685391627; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=j6tSDbopNqV00viv7j7TC+sCDwehceS4885UdmKt8xY=; b=3Zw4tn+VfShSf7l/1aG/Yh60aEEGJNMaBBXe+9/45IwJKPVzA7YBktJapjTwogi5Lr 3I6Mwa12CQWVwE9pOq41QuLN8TcOiHbnOqqBT5J+caxowom636thjEjDjmSP3WGx93Yw TD+sEtIHa7qNACfUS56zffFXMqBQITaK5epfJoV0LqpoAAUd/iUv+v3JJCwveuhnSmEO PIGTRF2OHyM2C4XRPVYzPZve5At013718+1xwr7OUJThobB0W0FN9E6hsECdVKKqTo+r f8VfR0ZxpiV0wBJNqR5iv/kqsjJTnsOVdNvmWAZZVmJ77TfPwqK+yO0UTcsC2oskZgyJ 2Beg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799627; x=1685391627; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=j6tSDbopNqV00viv7j7TC+sCDwehceS4885UdmKt8xY=; b=CTxQlPOfZqfc3jfW1yj4j974buryvK1GA5fs3odCY/NjTMVLCi/LRNMNRslSbQMrff sBKd5WqVSpHPR3cxQoGfmf4P8H8CJRMjWouIpHCgnY3bq8cCrm1zBn6EyGeu6E4iB0fh 2bibgo7Hxcs5pfft73gmzkoOrsP5anRBTxMZ/SqgwQnAZaQFiAR4AKA3gO2rw07A+spV EZ5qypLc1JNNRA1eyU94Ur1D8I3yJ17tqWMgXf5Pr8D7p076s2nfHg3D43SzEutLF7i6 KarSCIfH9EhxZA7MHsN6mKUSvsMNuYi0R274FDMHs6o7oiJV0O8ICi/sRs1hhG+SeFWp y/fA== X-Gm-Message-State: AC+VfDzihi7nhemklmKNJbdvuiAKk6yHsw7YSIrZbyBaPdXpYUguXaD8 BxROySJXLCMSQT4fFDeVbJuM4AbsH46tB4H/s9NwPA== X-Google-Smtp-Source: ACHHUZ6VRDDOEOyYVFrgX30V7+kLDuDtG3qCJEXgVRmbexk7AN2uGEZEC1lJMSbIMYK2hpPTC1DliA== X-Received: by 2002:a0d:e84f:0:b0:54f:b9bc:bd31 with SMTP id r76-20020a0de84f000000b0054fb9bcbd31mr8337867ywe.29.1682799627247; Sat, 29 Apr 2023 13:20:27 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id u205-20020a8147d6000000b00557027bf788sm1681868ywa.74.2023.04.29.13.20.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:26 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 20/26] btrfs-progs: move btrfs_uuid_tree_add into mkfs/main.c Date: Sat, 29 Apr 2023 16:19:51 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This function is only used in mkfs, and doesn't exist in the kernel in ctree.c. Additionally we have a uuid lookup function to see if the uuid exists in the tree, which for mkfs it won't because we just created the tree. Move btrfs_uuid_tree_add into mkfs, and remove the lookup function as it's not needed. Signed-off-by: Josef Bacik --- kernel-shared/ctree.c | 133 ------------------------------------------ kernel-shared/ctree.h | 2 - mkfs/main.c | 59 +++++++++++++++++++ 3 files changed, 59 insertions(+), 135 deletions(-) diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 327ff40c..9cb58908 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -2918,136 +2918,3 @@ int btrfs_previous_extent_item(struct btrfs_root *root, } return 1; } - -/* - * Search uuid tree - unmounted - * - * return -ENOENT for !found, < 0 for errors, or 0 if an item was found - */ -static int btrfs_uuid_tree_lookup(struct btrfs_root *uuid_root, u8 *uuid, - u8 type, u64 subid) -{ - int ret; - struct btrfs_path *path = NULL; - struct extent_buffer *eb; - int slot; - u32 item_size; - unsigned long offset; - struct btrfs_key key; - - if (!uuid_root) { - ret = -ENOENT; - goto out; - } - - path = btrfs_alloc_path(); - if (!path) { - ret = -ENOMEM; - goto out; - } - - btrfs_uuid_to_key(uuid, &key); - key.type = type; - ret = btrfs_search_slot(NULL, uuid_root, &key, path, 0, 0); - if (ret < 0) { - goto out; - } else if (ret > 0) { - ret = -ENOENT; - goto out; - } - - eb = path->nodes[0]; - slot = path->slots[0]; - item_size = btrfs_item_size(eb, slot); - offset = btrfs_item_ptr_offset(eb, slot); - ret = -ENOENT; - - if (!IS_ALIGNED(item_size, sizeof(u64))) { - warning("uuid item with invalid size %lu!", - (unsigned long)item_size); - goto out; - } - while (item_size) { - __le64 data; - - read_extent_buffer(eb, &data, offset, sizeof(data)); - if (le64_to_cpu(data) == subid) { - ret = 0; - break; - } - offset += sizeof(data); - item_size -= sizeof(data); - } - -out: - btrfs_free_path(path); - return ret; -} - -int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type, - u64 subvol_id_cpu) -{ - struct btrfs_fs_info *fs_info = trans->fs_info; - struct btrfs_root *uuid_root = fs_info->uuid_root; - int ret; - struct btrfs_path *path = NULL; - struct btrfs_key key; - struct extent_buffer *eb; - int slot; - unsigned long offset; - __le64 subvol_id_le; - - if (!uuid_root) { - warning("%s: uuid root is not initialized", __func__); - return -EINVAL; - } - - ret = btrfs_uuid_tree_lookup(uuid_root, uuid, type, subvol_id_cpu); - if (ret != -ENOENT) - return ret; - - key.type = type; - btrfs_uuid_to_key(uuid, &key); - - path = btrfs_alloc_path(); - if (!path) { - ret = -ENOMEM; - goto out; - } - - ret = btrfs_insert_empty_item(trans, uuid_root, path, &key, - sizeof(subvol_id_le)); - if (ret < 0 && ret != -EEXIST) { - warning( - "inserting uuid item failed (0x%016llx, 0x%016llx) type %u: %d", - (unsigned long long)key.objectid, - (unsigned long long)key.offset, type, ret); - goto out; - } - - if (ret >= 0) { - /* Add an item for the type for the first time */ - eb = path->nodes[0]; - slot = path->slots[0]; - offset = btrfs_item_ptr_offset(eb, slot); - } else { - /* - * ret == -EEXIST case, An item with that type already exists. - * Extend the item and store the new subvol_id at the end. - */ - btrfs_extend_item(path, sizeof(subvol_id_le)); - eb = path->nodes[0]; - slot = path->slots[0]; - offset = btrfs_item_ptr_offset(eb, slot); - offset += btrfs_item_size(eb, slot) - sizeof(subvol_id_le); - } - - ret = 0; - subvol_id_le = cpu_to_le64(subvol_id_cpu); - write_extent_buffer(eb, &subvol_id_le, offset, sizeof(subvol_id_le)); - btrfs_mark_buffer_dirty(eb); - -out: - btrfs_free_path(path); - return ret; -} diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index ce1c3d25..40b8854c 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -1130,8 +1130,6 @@ int btrfs_lookup_uuid_received_subvol_item(int fd, const u8 *uuid, u64 *subvol_id); /* uuid-tree.c, interface for unmounte filesystem */ -int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type, - u64 subvol_id_cpu); int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type, u64 subid); diff --git a/mkfs/main.c b/mkfs/main.c index 88fea33b..a008f139 100644 --- a/mkfs/main.c +++ b/mkfs/main.c @@ -769,6 +769,65 @@ out: return ret; } +static int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, + u8 type, u64 subvol_id_cpu) +{ + struct btrfs_fs_info *fs_info = trans->fs_info; + struct btrfs_root *uuid_root = fs_info->uuid_root; + int ret; + struct btrfs_path *path = NULL; + struct btrfs_key key; + struct extent_buffer *eb; + int slot; + unsigned long offset; + __le64 subvol_id_le; + + key.type = type; + btrfs_uuid_to_key(uuid, &key); + + path = btrfs_alloc_path(); + if (!path) { + ret = -ENOMEM; + goto out; + } + + ret = btrfs_insert_empty_item(trans, uuid_root, path, &key, + sizeof(subvol_id_le)); + if (ret < 0 && ret != -EEXIST) { + warning( + "inserting uuid item failed (0x%016llx, 0x%016llx) type %u: %d", + (unsigned long long)key.objectid, + (unsigned long long)key.offset, type, ret); + goto out; + } + + if (ret >= 0) { + /* Add an item for the type for the first time */ + eb = path->nodes[0]; + slot = path->slots[0]; + offset = btrfs_item_ptr_offset(eb, slot); + } else { + /* + * ret == -EEXIST case, An item with that type already exists. + * Extend the item and store the new subvol_id at the end. + */ + btrfs_extend_item(path, sizeof(subvol_id_le)); + eb = path->nodes[0]; + slot = path->slots[0]; + offset = btrfs_item_ptr_offset(eb, slot); + offset += btrfs_item_size(eb, slot) - sizeof(subvol_id_le); + } + + ret = 0; + subvol_id_le = cpu_to_le64(subvol_id_cpu); + write_extent_buffer(eb, &subvol_id_le, offset, sizeof(subvol_id_le)); + btrfs_mark_buffer_dirty(eb); + +out: + btrfs_free_path(path); + return ret; +} + static int create_uuid_tree(struct btrfs_trans_handle *trans) { struct btrfs_fs_info *fs_info = trans->fs_info; From patchwork Sat Apr 29 20:19:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227099 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2D927C7EE24 for ; Sat, 29 Apr 2023 20:20:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230360AbjD2UUg (ORCPT ); Sat, 29 Apr 2023 16:20:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45678 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230334AbjD2UUa (ORCPT ); Sat, 29 Apr 2023 16:20:30 -0400 Received: from mail-yb1-xb32.google.com (mail-yb1-xb32.google.com [IPv6:2607:f8b0:4864:20::b32]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 804FA211C for ; Sat, 29 Apr 2023 13:20:29 -0700 (PDT) Received: by mail-yb1-xb32.google.com with SMTP id 3f1490d57ef6-b9a805fd0dcso1562652276.1 for ; Sat, 29 Apr 2023 13:20:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799628; x=1685391628; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=bYR7l0Iu2faBmf0CDEI84J75njZbfj+Kjz8af9wFOME=; b=ZhGyEKBgO77vdnSUHD6Qk2uezA38xK4F7JdD8Z5dR1IYtRMOoEER/Gof0vEE70zK1N +pru50CIHsBOPrxyphy+9PMYIj+qdV6R6ftXMpyQkxt7Gvbop5QmLOU509hPW/GKcucr RokO3YKzh9Jo77G6lFPBHpKJAOgOPiqavisTCanphUZOexBofEJsZjMGW3+Bu4xU9vFU fwCpQAgZxOLuAWHR8rVR8zcV2i8jHkcc1VqhTHLKjRuLk9l1xwyHmd1uaYRFKVt+VIoW 9XETutNoAnRfkKGzRn14BCMOYewumUnkqir/TzIYmP6KbPIz7qup5zsQ6GwoVy6Lz36l KJgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799628; x=1685391628; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bYR7l0Iu2faBmf0CDEI84J75njZbfj+Kjz8af9wFOME=; b=V7afPTpsrWRc0l790ta+LoGFVQoeiSUnCxvwdkV/5dGlnPEsRB0oYeI6Zs/VGojitK Zw9K+u0wJXzsGRiQ41UU3UlXQRG1h3ZXqPApxQvvYYvpnSTBOt1nituNxUsDyb0zi3zt 9J8iorP1C6OhcgeNBuHWn/1qyVs/3k/s5MhnMeHJHVbDm1f8MqNpPixZJFP84mwIf1az nyDZTSrhR2HrPx/LUTKTqALWnXVDkROaErVEX71b6/IOKz2LMzyL01LFDarEl6bRSvKJ +oFB20zzDbQkkiQfh1ZWM4wwRn6HmrQvGE33tGw5HWV75phrW/QJBl/x/w66PSYmnqsh 6MOQ== X-Gm-Message-State: AC+VfDyS2VJsRp3GS2aIG8/hdQckytPB3NP2wKuPI3zwuESFdLgg6OsS +D4wen5kX6JUE5zszrf+z8FBB/VgNY1NqvG/L4Ud6A== X-Google-Smtp-Source: ACHHUZ4iSRM4yfvKdE3i/OhoG5AYOHAAHAgJ3dcu4nylwk0Mffg7IbKrs3Eoatf516sM+eWtGiwSVw== X-Received: by 2002:a25:b120:0:b0:b8f:517c:1c15 with SMTP id g32-20020a25b120000000b00b8f517c1c15mr8632916ybj.11.1682799628395; Sat, 29 Apr 2023 13:20:28 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id p138-20020a257490000000b00b8be4767167sm5873659ybc.26.2023.04.29.13.20.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:27 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 21/26] btrfs-progs: make btrfs_del_ptr a void Date: Sat, 29 Apr 2023 16:19:52 -0400 Message-Id: <846c93398a45417a0f9cd0fb8e7bd8aeec2bfa93.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This always returns 0, and in the kernel is a void. Update the definition to match the kernel and then update all of the callers. Signed-off-by: Josef Bacik --- check/main.c | 7 +++---- kernel-shared/ctree.c | 16 ++++------------ kernel-shared/ctree.h | 2 +- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/check/main.c b/check/main.c index 5e4f5827..2643244f 100644 --- a/check/main.c +++ b/check/main.c @@ -3569,9 +3569,8 @@ static int repair_btree(struct btrfs_root *root, path.slots[level]); /* Remove the ptr */ - ret = btrfs_del_ptr(root, &path, level, path.slots[level]); - if (ret < 0) - goto out; + btrfs_del_ptr(root, &path, level, path.slots[level]); + /* * Remove the corresponding extent * return value is not concerned. @@ -7829,7 +7828,7 @@ again: del_ptr: printk("deleting pointer to block %llu\n", corrupt->cache.start); - ret = btrfs_del_ptr(extent_root, &path, level, slot); + btrfs_del_ptr(extent_root, &path, level, slot); out: btrfs_release_path(&path); diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 9cb58908..f9cf78da 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -685,9 +685,7 @@ static int balance_level(struct btrfs_trans_handle *trans, btrfs_clear_buffer_dirty(trans, right); free_extent_buffer(right); right = NULL; - wret = btrfs_del_ptr(root, path, level + 1, pslot + 1); - if (wret) - ret = wret; + btrfs_del_ptr(root, path, level + 1, pslot + 1); root_sub_used(root, blocksize); wret = btrfs_free_extent(trans, bytenr, blocksize, 0, @@ -732,9 +730,7 @@ static int balance_level(struct btrfs_trans_handle *trans, btrfs_clear_buffer_dirty(trans, mid); free_extent_buffer(mid); mid = NULL; - wret = btrfs_del_ptr(root, path, level + 1, pslot); - if (wret) - ret = wret; + btrfs_del_ptr(root, path, level + 1, pslot); root_sub_used(root, blocksize); wret = btrfs_free_extent(trans, bytenr, blocksize, 0, @@ -2557,12 +2553,11 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root * continuing all the way the root if required. The root is converted into * a leaf if all the nodes are emptied. */ -int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, +void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot) { struct extent_buffer *parent = path->nodes[level]; u32 nritems; - int ret = 0; nritems = btrfs_header_nritems(parent); if (slot < nritems - 1) { @@ -2586,7 +2581,6 @@ int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, fixup_low_keys(path, &disk_key, level + 1); } btrfs_mark_buffer_dirty(parent); - return ret; } /* @@ -2607,9 +2601,7 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, int ret; WARN_ON(btrfs_header_generation(leaf) != trans->transid); - ret = btrfs_del_ptr(root, path, 1, path->slots[1]); - if (ret) - return ret; + btrfs_del_ptr(root, path, 1, path->slots[1]); root_sub_used(root, leaf->len); diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 40b8854c..88a105ab 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -941,7 +941,7 @@ int btrfs_convert_one_bg(struct btrfs_trans_handle *trans, u64 bytenr); /* ctree.c */ int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2); -int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, +void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot); struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent, int slot); From patchwork Sat Apr 29 20:19:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227100 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1EF72C77B60 for ; Sat, 29 Apr 2023 20:20:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230361AbjD2UUi (ORCPT ); Sat, 29 Apr 2023 16:20:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45712 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230339AbjD2UUc (ORCPT ); Sat, 29 Apr 2023 16:20:32 -0400 Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF5651FD5 for ; Sat, 29 Apr 2023 13:20:30 -0700 (PDT) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-55a00da4e53so5437227b3.0 for ; Sat, 29 Apr 2023 13:20:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799630; x=1685391630; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=9tVmDDHyTh9kII60ufgF1qZDrFipk8YiatOI1xQ1kqM=; b=aSyJ2HNos2yMf4QXgyycb9xK+nFLHR+TaiXOgMI0Fdad5s1hhq2QlEBG78JUr0o2b6 lhxpxmo3xB7OEsgo194WaKpBi0zr4/I3Lrhnb+zeWklQR4qzPOkhwQGlTQZuPwssOzNi tK5Oq0yuiXajB7zTweC+vObTz9DDJoFRkcQ53rJ7LMTi8S06Cqxn4g3Q0df159a8bYi1 w9zwDXCv8SMAuTJ5azW/I26UOai6+LebE9owEnbEG8MmNFQCSP4aZZ/U8p5BxkGYFc3T +HtdAvjWBPs0pcrQ08BDDslQmLMI4ex+vngoZJ2R0/qUGoKaxMbnanc1/0nGrKSUAflv +Qnw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799630; x=1685391630; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9tVmDDHyTh9kII60ufgF1qZDrFipk8YiatOI1xQ1kqM=; b=ECi+EZD5zl8gPLoaVKiZVk5A26QpOO7XCDe+4UToFJgW/hycy/+cJ7/iGI3zC5iLyF YLFHAIDoY0wXDSxjxzmeZ2QjHjsI0QaYVt+7DaB2IGcmvZHX44WTD7wvUWeA9jP1VOaJ cFa/QU1CbRrysxp9rUdTIC4xlkd+Ju9VMmzOb901HWfP76/UOzdcS0BCtcq7K1hdpmMA DreXfLhijKaqz/gLRhwIDV/CcyM23Xz6+r/wQ+IQjcQHC515TEUzajUtfEX3owOb6R3h BhD35dwBACjg+gWoeZ4K1on1NqNXn0HnNNX49SiUScbI+4xd6hAPiqSdOLPTbKusYp8t vDPw== X-Gm-Message-State: AC+VfDypMK5GcjN4VHhcsvHVJ+wrHo7L+eEzupTYJLLre7V0Tv2fD5KQ PmPoUFG2y5TadAkKFnlDbPFIs6vJgLp5AEOHjtogaA== X-Google-Smtp-Source: ACHHUZ4jWDE9xvJDi8uhQh7c0P56h0nx22xhJIJPMbsfLR0iw3AyvTVT9i4d6AcH1F4/VoUD1sxt3w== X-Received: by 2002:a0d:d74c:0:b0:54f:b26f:bc8 with SMTP id z73-20020a0dd74c000000b0054fb26f0bc8mr7062730ywd.26.1682799629657; Sat, 29 Apr 2023 13:20:29 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id n187-20020a0de4c4000000b005463e45458bsm6288976ywe.123.2023.04.29.13.20.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:29 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 22/26] btrfs-progs: replace blocksize with parent argument for btrfs_alloc_tree_block Date: Sat, 29 Apr 2023 16:19:53 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In the kernel we pass in the parent to btrfs_alloc_tree_block instead of the blocksize and simply derive the blocksize from the fs_info. Update the function to match the kernel's convention and update all of the callers so we can sync ctree.c easily. Signed-off-by: Josef Bacik --- check/main.c | 3 +-- cmds/rescue-chunk-recover.c | 3 +-- kernel-shared/ctree.c | 29 ++++++++++++----------------- kernel-shared/ctree.h | 2 +- kernel-shared/disk-io.c | 5 ++--- kernel-shared/extent-tree.c | 9 +++++---- 6 files changed, 22 insertions(+), 29 deletions(-) diff --git a/check/main.c b/check/main.c index 2643244f..ca49863b 100644 --- a/check/main.c +++ b/check/main.c @@ -9067,8 +9067,7 @@ static struct extent_buffer *btrfs_fsck_clear_root( if (!path) return ERR_PTR(-ENOMEM); - c = btrfs_alloc_tree_block(trans, gfs_info->tree_root, - gfs_info->nodesize, key->objectid, + c = btrfs_alloc_tree_block(trans, gfs_info->tree_root, 0, key->objectid, &disk_key, 0, 0, 0, BTRFS_NESTING_NORMAL); if (IS_ERR(c)) { btrfs_free_path(path); diff --git a/cmds/rescue-chunk-recover.c b/cmds/rescue-chunk-recover.c index f30612d1..660d17f7 100644 --- a/cmds/rescue-chunk-recover.c +++ b/cmds/rescue-chunk-recover.c @@ -1143,8 +1143,7 @@ static int __rebuild_chunk_root(struct btrfs_trans_handle *trans, btrfs_set_disk_key_type(&disk_key, BTRFS_DEV_ITEM_KEY); btrfs_set_disk_key_offset(&disk_key, min_devid); - cow = btrfs_alloc_tree_block(trans, root, root->fs_info->nodesize, - BTRFS_CHUNK_TREE_OBJECTID, + cow = btrfs_alloc_tree_block(trans, root, 0, BTRFS_CHUNK_TREE_OBJECTID, &disk_key, 0, 0, 0, BTRFS_NESTING_NORMAL); btrfs_set_header_bytenr(cow, cow->start); btrfs_set_header_generation(cow, trans->transid); diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index f9cf78da..2728452f 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -158,9 +158,8 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, btrfs_item_key(buf, &disk_key, 0); else btrfs_node_key(buf, &disk_key, 0); - cow = btrfs_alloc_tree_block(trans, new_root, buf->len, - new_root_objectid, &disk_key, - level, buf->start, 0, + cow = btrfs_alloc_tree_block(trans, new_root, 0, new_root_objectid, + &disk_key, level, buf->start, 0, BTRFS_NESTING_NORMAL); if (IS_ERR(cow)) { kfree(new_root); @@ -329,9 +328,8 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, else btrfs_node_key(buf, &disk_key, 0); - cow = btrfs_alloc_tree_block(trans, root, buf->len, - root->root_key.objectid, &disk_key, - level, search_start, empty_size, + cow = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, + &disk_key, level, search_start, empty_size, BTRFS_NESTING_NORMAL); if (IS_ERR(cow)) return PTR_ERR(cow); @@ -1395,9 +1393,8 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, else btrfs_node_key(lower, &lower_key, 0); - c = btrfs_alloc_tree_block(trans, root, root->fs_info->nodesize, - root->root_key.objectid, &lower_key, - level, root->node->start, 0, + c = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, + &lower_key, level, root->node->start, 0, BTRFS_NESTING_NORMAL); if (IS_ERR(c)) @@ -1522,10 +1519,9 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root mid = (c_nritems + 1) / 2; btrfs_node_key(c, &disk_key, mid); - split = btrfs_alloc_tree_block(trans, root, root->fs_info->nodesize, - root->root_key.objectid, - &disk_key, level, c->start, 0, - BTRFS_NESTING_NORMAL); + split = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, + &disk_key, level, c->start, 0, + BTRFS_NESTING_NORMAL); if (IS_ERR(split)) return PTR_ERR(split); @@ -2088,10 +2084,9 @@ again: else btrfs_item_key(l, &disk_key, mid); - right = btrfs_alloc_tree_block(trans, root, root->fs_info->nodesize, - root->root_key.objectid, - &disk_key, 0, l->start, 0, - BTRFS_NESTING_NORMAL); + right = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, + &disk_key, 0, l->start, 0, + BTRFS_NESTING_NORMAL); if (IS_ERR(right)) { BUG_ON(1); return PTR_ERR(right); diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 88a105ab..b68a8080 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -885,7 +885,7 @@ struct btrfs_block_group *btrfs_lookup_first_block_group(struct u64 bytenr); struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, - u32 blocksize, u64 root_objectid, + u64 parent, u64 root_objectid, struct btrfs_disk_key *key, int level, u64 hint, u64 empty_size, enum btrfs_lock_nesting nest); diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index ec97ff08..bdf77d50 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -2361,9 +2361,8 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans, btrfs_setup_root(root, fs_info, key->objectid); memcpy(&root->root_key, key, sizeof(struct btrfs_key)); - leaf = btrfs_alloc_tree_block(trans, root, fs_info->nodesize, - root->root_key.objectid, NULL, 0, 0, 0, - BTRFS_NESTING_NORMAL); + leaf = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, + NULL, 0, 0, 0, BTRFS_NESTING_NORMAL); if (IS_ERR(leaf)) { ret = PTR_ERR(leaf); leaf = NULL; diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index 98c0b297..a9f3eba6 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -2480,7 +2480,7 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, } static int alloc_tree_block(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 num_bytes, + struct btrfs_root *root, u64 parent, u64 root_objectid, u64 generation, u64 flags, struct btrfs_disk_key *key, int level, u64 empty_size, u64 hint_byte, @@ -2491,6 +2491,7 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans, struct btrfs_delayed_extent_op *extent_op; struct btrfs_space_info *sinfo; struct btrfs_fs_info *fs_info = root->fs_info; + u64 num_bytes = fs_info->nodesize; bool skinny_metadata = btrfs_fs_incompat(root->fs_info, SKINNY_METADATA); @@ -2537,7 +2538,7 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans, sinfo->bytes_reserved += extent_size; ret = btrfs_add_delayed_tree_ref(root->fs_info, trans, ins->objectid, - extent_size, 0, root_objectid, + extent_size, parent, root_objectid, level, BTRFS_ADD_DELAYED_EXTENT, extent_op, NULL, NULL); return ret; @@ -2549,7 +2550,7 @@ static int alloc_tree_block(struct btrfs_trans_handle *trans, */ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, - u32 blocksize, u64 root_objectid, + u64 parent, u64 root_objectid, struct btrfs_disk_key *key, int level, u64 hint, u64 empty_size, enum btrfs_lock_nesting nest) @@ -2558,7 +2559,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, int ret; struct extent_buffer *buf; - ret = alloc_tree_block(trans, root, blocksize, root_objectid, + ret = alloc_tree_block(trans, root, parent, root_objectid, trans->transid, 0, key, level, empty_size, hint, (u64)-1, &ins); if (ret) { From patchwork Sat Apr 29 20:19:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227101 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5219AC77B7C for ; Sat, 29 Apr 2023 20:20:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230363AbjD2UUj (ORCPT ); Sat, 29 Apr 2023 16:20:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45716 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230343AbjD2UUc (ORCPT ); Sat, 29 Apr 2023 16:20:32 -0400 Received: from mail-yw1-x112f.google.com (mail-yw1-x112f.google.com [IPv6:2607:f8b0:4864:20::112f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B7E7FE79 for ; Sat, 29 Apr 2023 13:20:31 -0700 (PDT) Received: by mail-yw1-x112f.google.com with SMTP id 00721157ae682-559debdedb5so14158937b3.0 for ; Sat, 29 Apr 2023 13:20:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799631; x=1685391631; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=nNKI1mkk4Olz7aQqBRv928o21xDlQhzLeZwjDxJD1Vo=; b=gLQrIyf+GI3Ij1ziUTvWZF2pzY+KFMppnwezAw/FgdGhivrhzP6JU2Oc//3Ofywk6w ls6VBTiLI1gJ/0mX4QwAvaBbQLyGqJtX7PhwNSs5pzyVVUb5i5F/+8LWPEeMCzmtvZgU v9e8OhkrEswH7JiU7BA3hsOFHeLh7g6SPVEl/gfsMjPrDv43Ic+c9VCG5bfSf/40epFQ qQ+syOHU5ih2fIMO2DGtd3GgdSYy7uzmUdjsbBcrIWP4HGvcoMO70eAM43MFWY1VdF1G xeI+sBpgzTiC5m/cCFZZ04ou9tz+3KeazbHJJLMVHZIddRv0HoQegOE6KYinUmuEYmo0 RExA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799631; x=1685391631; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=nNKI1mkk4Olz7aQqBRv928o21xDlQhzLeZwjDxJD1Vo=; b=LGbFU/agWFpyAkEbKP+XBHj0256YfqCh8yWHXQ+Tbj3TcbWsHS11X5nLwYOGxr2PmN wqsxV1cAuAp5IybhaZwkPrlU9dRnmGw/ZbQ537Vph1KCLXn/ufLttSWvacKOqhsZ/qJB ZZ5GXIy22/zAfzVhtF1OnDHivBWaJ9gjWpwtsjhZl+vKe8P/tsiE5KZiC+Pg43moaAvl LoBbIKc++hpMKrABGiICEwwf47crT5C0DFxFX/Hpw8FhLgKYuQ0q91qQtPE3xHXy67YJ PrCeRAx81+SoYgiiunyG2dvThr5goLCxN+LKL4SFxuMjRU+xD0S4MrixP0+dLs2TcjTV jS1w== X-Gm-Message-State: AC+VfDzurKdISB5DanM7Qbrc7c8imp2yHxd/w+e6kFJ4UCFma5V9dUgZ 97RhDqSjtSsQGWd7O399Brno8ndQbeQzo50jPRqHlQ== X-Google-Smtp-Source: ACHHUZ6aanWFGrx0mDuGkKblELhM6ULYCqPTG4p0Ui7VjK6p7gWii5JyTOyPQc0Gpifg+CDEiuPqhQ== X-Received: by 2002:a0d:d54f:0:b0:54f:c68f:dc40 with SMTP id x76-20020a0dd54f000000b0054fc68fdc40mr8217696ywd.39.1682799630713; Sat, 29 Apr 2023 13:20:30 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id z66-20020a0df045000000b0054f56baf3f2sm6249686ywe.122.2023.04.29.13.20.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:30 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 23/26] btrfs-progs: use path->search_for_extension Date: Sat, 29 Apr 2023 16:19:54 -0400 Message-Id: <373d0890a6c4f320006c3600d223ad64a3597f69.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This flag is used by the kernel btrfs_search_slot to make sure that leaf splitting decision doesn't subtract the size of an item. This is for inline extent items and csum items where we know we're going to find the item we want, and we're only going to want to extend it. Currently this flag doesn't do anything, but when we sync ctree.c we'll stop making the right decision WRT the leaf space, so add the flag usage in the places we need it so we can sync ctree.c easily. Signed-off-by: Josef Bacik --- kernel-shared/extent-tree.c | 8 ++++++-- kernel-shared/file-item.c | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index a9f3eba6..e29a1cb4 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -882,10 +882,12 @@ static int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, key.offset = num_bytes; want = extent_ref_type(parent, owner); - if (insert) + if (insert) { extra_size = btrfs_extent_inline_ref_size(want); - else + path->search_for_extension = 1; + } else { extra_size = -1; + } if (owner < BTRFS_FIRST_FREE_OBJECTID && skinny_metadata) { key.type = BTRFS_METADATA_ITEM_KEY; @@ -1023,6 +1025,8 @@ again: } *ref_ret = (struct btrfs_extent_inline_ref *)ptr; out: + if (insert) + path->search_for_extension = 0; return err; } diff --git a/kernel-shared/file-item.c b/kernel-shared/file-item.c index fd6756e9..d6d01198 100644 --- a/kernel-shared/file-item.c +++ b/kernel-shared/file-item.c @@ -268,8 +268,10 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, * enough yet to put our csum in. Grow it */ btrfs_release_path(path); + path->search_for_extension = 1; ret = btrfs_search_slot(trans, root, &file_key, path, csum_size, 1); + path->search_for_extension = 0; if (ret < 0) goto fail; if (ret == 0) { From patchwork Sat Apr 29 20:19:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227102 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0B6C9C7EE23 for ; Sat, 29 Apr 2023 20:20:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230373AbjD2UUj (ORCPT ); Sat, 29 Apr 2023 16:20:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45752 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230349AbjD2UUd (ORCPT ); Sat, 29 Apr 2023 16:20:33 -0400 Received: from mail-yw1-x1129.google.com (mail-yw1-x1129.google.com [IPv6:2607:f8b0:4864:20::1129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E130A210A for ; Sat, 29 Apr 2023 13:20:32 -0700 (PDT) Received: by mail-yw1-x1129.google.com with SMTP id 00721157ae682-54fe25c2765so20193527b3.3 for ; Sat, 29 Apr 2023 13:20:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799632; x=1685391632; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=N1KxpMDL2OEA6fseh0uFJ5Ba9UtMnXLtg1UDeo+UDpA=; b=yPxpRp+WmFFelZK3+Y3iadUBJ3InceOEepBfJxGxHkfGUteGaa40HNu5VRBFkC6C7N qQGOkZdrXv+nn/RnTSjbAoXIZPf8/jwFoBI113yfrNbi/WnHdOEQ4/cyQkO3J9ZhYEyD bbzy/QCEAuphh1yrG6JAOPyZxoEU0gvOQJxznDs6Pa9v56MQETN78PzoXJNdtTvyauTs QJ98e2ndi9mztm6arV+x8JLpGFjLXKldAGDmXlJQmNLhEh4VRFWW1wvNJXe1u4TVcziF w0fv7bl0RTCgo4jCw1rxLA4JZ2kFyZxUMCudL6ikFvmQa4k87ynLLasw/oWYYBchmnVY Z1ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799632; x=1685391632; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=N1KxpMDL2OEA6fseh0uFJ5Ba9UtMnXLtg1UDeo+UDpA=; b=WNlcVwrYU6ovgX20xXd4zYpjOreZNIfB19OD06Fp54AJIlD/U8PNADQ1/E0DtkFPYJ 7qBoV94/ICTSrUNOnhz1Uyij0WPVx+/+VcDsbW3SZyqyweqohhh2+DnAvjg8Mulc8jUw sEfuDQEiSNDs6cPhR9JPLR0NSK9tl71HNwLmLmxVzzZ9cK2uyThD0grApg73DF+rV10C gvtIo1nKX+c5pG1sLhLm9BVDROCmtNNKOkHFDnYc6PVRijfufaoy87nVfiuQFxGpyGB/ DC8VvIuGECTKzgGjWtBfsEFhW2Edw1v39cnjeu0AtE9O7IWioNJYUyIv/WUiC+m0ISod uB3w== X-Gm-Message-State: AC+VfDwT0VkpIrVUQxobN/Wte8TGgdHjTELSuGtwlsbEzZ6duSGN6+60 OAWdbc4hDiCDFfEkWfB4WhTQCR6PYgM87EAJoncVoQ== X-Google-Smtp-Source: ACHHUZ5HdiN9N04HkXO7omGiT4iePbJrUHj630KUMIrCit1jhgQcm55iR69Y6w/ooNxP1muOn5nvnA== X-Received: by 2002:a0d:d606:0:b0:559:e5d1:a4c2 with SMTP id y6-20020a0dd606000000b00559e5d1a4c2mr2730712ywd.49.1682799631818; Sat, 29 Apr 2023 13:20:31 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id c134-20020a814e8c000000b00555abba6ff7sm6310829ywb.113.2023.04.29.13.20.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:31 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 24/26] btrfs-progs: add write_extent_buffer_chunk_tree_uuid helper Date: Sat, 29 Apr 2023 16:19:55 -0400 Message-Id: <046464e2ca6e3ba086cbf82bdc7c8c143a17251c.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This exists in the kernel to update the chunk tree uuid on the btrfs_header. Add the helper to btrfs-progs to make future kernel sync changes easier. Signed-off-by: Josef Bacik --- kernel-shared/ctree.h | 2 +- kernel-shared/extent_io.c | 7 +++++++ kernel-shared/extent_io.h | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index b68a8080..376b8eca 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -731,7 +731,7 @@ static inline unsigned long btrfs_header_fsid(void) return offsetof(struct btrfs_header, fsid); } -static inline unsigned long btrfs_header_chunk_tree_uuid(struct extent_buffer *eb) +static inline unsigned long btrfs_header_chunk_tree_uuid(const struct extent_buffer *eb) { return offsetof(struct btrfs_header, chunk_tree_uuid); } diff --git a/kernel-shared/extent_io.c b/kernel-shared/extent_io.c index fbf45e9d..e942a7b4 100644 --- a/kernel-shared/extent_io.c +++ b/kernel-shared/extent_io.c @@ -659,6 +659,13 @@ void write_extent_buffer_fsid(const struct extent_buffer *eb, const void *srcv) write_extent_buffer(eb, srcv, btrfs_header_fsid(), BTRFS_FSID_SIZE); } +void write_extent_buffer_chunk_tree_uuid(const struct extent_buffer *eb, + const void *srcv) +{ + write_extent_buffer(eb, srcv, btrfs_header_chunk_tree_uuid(eb), + BTRFS_FSID_SIZE); +} + /* * btrfs_readahead_node_child - readahead a node's child block * @node: parent node we're reading from diff --git a/kernel-shared/extent_io.h b/kernel-shared/extent_io.h index 544d5710..aa56c115 100644 --- a/kernel-shared/extent_io.h +++ b/kernel-shared/extent_io.h @@ -143,5 +143,7 @@ void extent_buffer_init_cache(struct btrfs_fs_info *fs_info); void extent_buffer_free_cache(struct btrfs_fs_info *fs_info); void write_extent_buffer_fsid(const struct extent_buffer *eb, const void *srcv); void btrfs_readahead_node_child(struct extent_buffer *node, int slot); +void write_extent_buffer_chunk_tree_uuid(const struct extent_buffer *eb, + const void *src); #endif From patchwork Sat Apr 29 20:19:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227103 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9EBF8C77B7F for ; Sat, 29 Apr 2023 20:20:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230381AbjD2UUk (ORCPT ); Sat, 29 Apr 2023 16:20:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45766 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230356AbjD2UUe (ORCPT ); Sat, 29 Apr 2023 16:20:34 -0400 Received: from mail-yw1-x1134.google.com (mail-yw1-x1134.google.com [IPv6:2607:f8b0:4864:20::1134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E5448E77 for ; Sat, 29 Apr 2023 13:20:33 -0700 (PDT) Received: by mail-yw1-x1134.google.com with SMTP id 00721157ae682-54f8af6dfa9so20301177b3.2 for ; Sat, 29 Apr 2023 13:20:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799633; x=1685391633; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=R3o8quIZ2qw7VXGH9TgH15X7BhGRwXuhJtg12h5dinI=; b=HTYWW8dsAIoWDQZ+zu4PCVDtvJdjpMB7MxnNtDKH3nRhhsJ0QwEUEej3H6XSuCvyTO IoPeltdIGcUiD3U34Ag8w1obxxNt2h4zOak6nuzCS9/TPf9B/Q17Uogx3cv+uNUnupS9 S3VsuzsQ7WNy7FpmvWOIfxI7uy0LvAXTJVw3CrbtIIetVSkwCkCG6oEI061GhAZGX0R9 YFC25CjBQbDub35nWVdbsTL5cmaEpOEH7hIUrAvDApuJC1O/b/Hg/c+3fSC5sD9H/5KO 5nu3o/eoMC4u7ii6lnQXOgp9wGNynEnroOB0YU8ETu7qO3L/hY2Anci5LorY76giHaZL Afrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799633; x=1685391633; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=R3o8quIZ2qw7VXGH9TgH15X7BhGRwXuhJtg12h5dinI=; b=OxI6LuEaz3QgtFGAf99aUl1o4QOlaNeS2LRJkYssZLeWhQ8ZH6JkQhaCUeiyZZdcjt XwIrSFATZ03jaeqKyW8RfZr8pvj1mP+puIf3vv2ydlkQfItiXaSxu1vQgWujCzavmofT zdmrTyutU5AluNNjm8JppazKAL7aK70M9xiYqXdRYEFtrpc5TpKh4YIDE+Mzbua50fHG FT8ecciyBmTg5drSLRo+bNdd7Ojlsy1ehBdH/OsJvmAHR3So1pcuOAsuPRAFIhF/cQlb BH2NnBfplh+yOipYqr+E9pgBzfuDahBiB9koRlGfLEkndIYiGlwKc1vyGsBgb2/qrddh GnyQ== X-Gm-Message-State: AC+VfDw3upeYI4IgJS6dB+Rc3NI93wilIZQ5O3osoILgfEtW3UNWwNgr 2fTnvIn74xiYfVD9QjcJXrMBgkndTFP/qekJZwmACg== X-Google-Smtp-Source: ACHHUZ56IdXN+qyv1/F55xTVO9gHDvhG8701WujxRz4aMh3wUAGOcYd/jODCnCTkIztbfGd0rfvgLg== X-Received: by 2002:a81:498d:0:b0:54f:b4eb:bc14 with SMTP id w135-20020a81498d000000b0054fb4ebbc14mr7591986ywa.3.1682799632918; Sat, 29 Apr 2023 13:20:32 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id d201-20020a814fd2000000b0054f8b7b8514sm6250773ywb.128.2023.04.29.13.20.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:32 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 25/26] btrfs-progs: init new tree blocks in btrfs_alloc_tree_block Date: Sat, 29 Apr 2023 16:19:56 -0400 Message-Id: <816212e82d57a67fdf9b741ab0621ab7f12b57ab.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This is how the kernel initializes blocks, so anybody who uses btrfs_alloc_tree_block in the kernel expects the blocks to be already initialized. Put this init code into btrfs-progs so as we sync code from the kernel we get the correct behavior. Signed-off-by: Josef Bacik --- kernel-shared/extent-tree.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index e29a1cb4..6da30011 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -2559,6 +2559,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, u64 hint, u64 empty_size, enum btrfs_lock_nesting nest) { + struct btrfs_fs_info *fs_info = trans->fs_info; struct btrfs_key ins; int ret; struct extent_buffer *buf; @@ -2579,6 +2580,14 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, return ERR_PTR(-ENOMEM); } btrfs_set_buffer_uptodate(buf); + memset_extent_buffer(buf, 0, 0, sizeof(struct btrfs_header)); + btrfs_set_header_level(buf, level); + btrfs_set_header_bytenr(buf, buf->start); + btrfs_set_header_generation(buf, trans->transid); + btrfs_set_header_backref_rev(buf, BTRFS_MIXED_BACKREF_REV); + btrfs_set_header_owner(buf, root_objectid); + write_extent_buffer_fsid(buf, fs_info->fs_devices->metadata_uuid); + write_extent_buffer_chunk_tree_uuid(buf, fs_info->chunk_tree_uuid); trans->blocks_used++; return buf; From patchwork Sat Apr 29 20:19:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13227104 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 99ECAC77B60 for ; Sat, 29 Apr 2023 20:20:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230397AbjD2UUn (ORCPT ); Sat, 29 Apr 2023 16:20:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230356AbjD2UUl (ORCPT ); Sat, 29 Apr 2023 16:20:41 -0400 Received: from mail-yw1-x1136.google.com (mail-yw1-x1136.google.com [IPv6:2607:f8b0:4864:20::1136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DC5E326B7 for ; Sat, 29 Apr 2023 13:20:36 -0700 (PDT) Received: by mail-yw1-x1136.google.com with SMTP id 00721157ae682-54fe08015c1so18011797b3.3 for ; Sat, 29 Apr 2023 13:20:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1682799636; x=1685391636; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=g5C8eZ4Y2tnfOHfv2C+e9wVMSW3DBoscgbBu5hQ2jCk=; b=FaodiPwN8abmhTB1GfXs/iBwIj+hJ4jHc69QyTIsB2/3VF76K4z3FC0lGL/nb/GdIU IhDRFL620u+TC/+cghXgblfOWq1LT2ST9bT/0LF7AtptfWFY0rbkPkoYSDUWQHEPGZHy W6vG8RaI23EZfqsHZ/C8MFqG2dBFqYevo8TWwNS5pqDwj8sROnUCptFw0n33sPr871VA 307fNX93UjZmavfYYEgJTYlqfjUK5pKeZt32fQwlUsvuv0958LKPKhR3/mX+2XHb/8oo hSsOZ3ZTnKRj2zbjLeImZDQEvM1Ag6VT40Ww44IabD5gSJc8zguS3DNLPX/nZSpH5mUS Q8NQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1682799636; x=1685391636; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=g5C8eZ4Y2tnfOHfv2C+e9wVMSW3DBoscgbBu5hQ2jCk=; b=j/sOSwQI86PXVa+VzyT/ixp7GH0lh9zu6ZYQRuUDkuB5E5nxjliVp2V6MqWq9mM07q B4VM3pOk4yr+G3qZXs6J+2qQB+gKrTF06h46t3YwOE5b/NpW92xc7pi+9cskubCpqsT0 oukppw6uftkPnC5VV5+hpQvIW0BLlIXfF2ZMELmO5rNp+mnMiwvmqhOuzqPWYMvw0NQh o7FHgHyEsY94G1fpQRhcwRr2RVelHyXXlaf0tBq5z+bKS9sAOLd/58p6ZhoEKKEJr4wm v1/rNbolE2rPEJcyLHwiQqK7Xdpd5L6bduwviPvE/3JQSzzswKY3l4QhwPfhpJGVdLpB 3sVA== X-Gm-Message-State: AC+VfDz5ax3N/WzLV9NDirzhTvCF6SR37QF35RgP3YVivlwQOnKyW7HC 8UDXLnzy/R0x3GFscPOAH031fIIupVnNuGY+idsW9g== X-Google-Smtp-Source: ACHHUZ40y03zAuttvLt0EZeh/kC2vYzLnvDl1ZZUjWhoQ+fJ4AnkuiTRkzze7w0syezcWURRt3Ck1g== X-Received: by 2002:a0d:c582:0:b0:552:a63e:18d1 with SMTP id h124-20020a0dc582000000b00552a63e18d1mr6174316ywd.52.1682799634314; Sat, 29 Apr 2023 13:20:34 -0700 (PDT) Received: from localhost (cpe-76-182-20-124.nc.res.rr.com. [76.182.20.124]) by smtp.gmail.com with ESMTPSA id e124-20020a0df582000000b0054f0349073esm2817213ywf.62.2023.04.29.13.20.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 29 Apr 2023 13:20:33 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 26/26] btrfs-progs: sync ctree.c from the kernel Date: Sat, 29 Apr 2023 16:19:57 -0400 Message-Id: <9e7695d842e81db247941026b16f37ce447e7e1c.1682799405.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This patch sync's ctree.c from the kernel. This is mostly painless, there were a few modifications that were necessary - There is no btrfs_transaction in btrfs-progs currently, those references had to be commented out. - The path kmem cache has to be init'ed on open ctree, so there was some weirdness to get that to work properly. - Some references to page_address that had to be removed in the btrfs_bin_search function that are optimizations for the kernel. - We have a struct that we pass around for block validation in the kernel that we don't have here, so removed that stuff. These sites are all marked, otherwise it's a straight copy. There were some changes outside of ctree.c that couldn't be done as a preparation as it came with the behavior changes in the newer ctree.c. This are easy to spot as they're outside of ctree.c and straightforward. Signed-off-by: Josef Bacik --- include/kerncompat.h | 80 + kernel-lib/trace.h | 8 + kernel-shared/ctree.c | 4474 ++++++++++++++++++++++++++--------- kernel-shared/ctree.h | 95 +- kernel-shared/disk-io.c | 5 + kernel-shared/locking.c | 6 +- kernel-shared/transaction.c | 5 +- 7 files changed, 3477 insertions(+), 1196 deletions(-) diff --git a/include/kerncompat.h b/include/kerncompat.h index 7472ff75..3bda16d2 100644 --- a/include/kerncompat.h +++ b/include/kerncompat.h @@ -202,6 +202,10 @@ typedef struct spinlock_struct { unsigned long lock; } spinlock_t; +struct rw_semaphore { + long lock; +}; + #define mutex_init(m) \ do { \ (m)->lock = 1; \ @@ -244,6 +248,27 @@ static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags) spin_unlock(lock); } +static inline void init_rwsem(struct rw_semaphore *sem) +{ + sem->lock = 0; +} + +static inline bool down_read_trylock(struct rw_semaphore *sem) +{ + sem->lock++; + return true; +} + +static inline void down_read(struct rw_semaphore *sem) +{ + sem->lock++; +} + +static inline void up_read(struct rw_semaphore *sem) +{ + sem->lock--; +} + #define cond_resched() do { } while (0) #define preempt_enable() do { } while (0) #define preempt_disable() do { } while (0) @@ -400,6 +425,11 @@ static inline void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t mask) return malloc(cache->size); } +static inline void *kmem_cache_zalloc(struct kmem_cache *cache, gfp_t mask) +{ + return calloc(1, cache->size); +} + static inline void kmem_cache_free(struct kmem_cache *cache, void *ptr) { free(ptr); @@ -704,6 +734,10 @@ static inline bool sb_rdonly(struct super_block *sb) #define unlikely(cond) (cond) +#define rcu_dereference(c) (c) + +#define rcu_assign_pointer(p, v) do { (p) = (v); } while (0) + static inline void atomic_set(atomic_t *a, int val) { *a = val; @@ -724,6 +758,15 @@ static inline void atomic_dec(atomic_t *a) (*a)--; } +static inline bool atomic_inc_not_zero(atomic_t *a) +{ + if (*a) { + atomic_inc(a); + return true; + } + return false; +} + static inline struct workqueue_struct *alloc_workqueue(const char *name, unsigned long flags, int max_active, ...) @@ -766,6 +809,10 @@ static inline void lockdep_set_class(spinlock_t *lock, struct lock_class_key *lc { } +static inline void lockdep_assert_held_read(struct rw_semaphore *sem) +{ +} + static inline bool cond_resched_lock(spinlock_t *lock) { return false; @@ -800,11 +847,30 @@ static inline void schedule(void) { } +static inline void might_sleep(void) +{ +} + +static inline void rcu_read_lock(void) +{ +} + +static inline void rcu_read_unlock(void) +{ +} + +static inline void synchronize_rcu(void) +{ +} + /* * Temporary definitions while syncing. */ struct btrfs_inode; struct extent_state; +struct extent_buffer; +struct btrfs_root; +struct btrfs_trans_handle; static inline void btrfs_merge_delalloc_extent(struct btrfs_inode *inode, struct extent_state *state, @@ -830,4 +896,18 @@ static inline void btrfs_clear_delalloc_extent(struct btrfs_inode *inode, { } +static inline int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *buf, + struct extent_buffer *cow) +{ + return 0; +} + +static inline void btrfs_qgroup_trace_subtree_after_cow(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *buf) +{ +} + #endif diff --git a/kernel-lib/trace.h b/kernel-lib/trace.h index 99bee344..10fc589d 100644 --- a/kernel-lib/trace.h +++ b/kernel-lib/trace.h @@ -1,6 +1,8 @@ #ifndef __PROGS_TRACE_H__ #define __PROGS_TRACE_H__ +struct btrfs_work; + static inline void trace_btrfs_workqueue_alloc(void *ret, const char *name) { } @@ -52,4 +54,10 @@ static inline void trace_btrfs_convert_extent_bit(struct extent_io_tree *tree, { } +static inline void trace_btrfs_cow_block(struct btrfs_root *root, + struct extent_buffer *buf, + struct extent_buffer *cow) +{ +} + #endif /* __PROGS_TRACE_H__ */ diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 2728452f..1405dde6 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -1,155 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2007 Oracle. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License v2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 021110-1307, USA. + * Copyright (C) 2007,2008 Oracle. All rights reserved. */ -#include "kernel-shared/ctree.h" -#include "kernel-shared/disk-io.h" -#include "kernel-shared/transaction.h" -#include "kernel-shared/print-tree.h" +#include "include/kerncompat.h" #include "kernel-lib/bitops.h" -#include "crypto/crc32c.h" -#include "common/internal.h" -#include "common/messages.h" -#include "common/utils.h" -#include "kernel-lib/sizes.h" -#include "kernel-shared/volumes.h" -#include "check/repair.h" +#include "messages.h" +#include "ctree.h" +#include "disk-io.h" +#include "transaction.h" +#include "print-tree.h" +#include "locking.h" +#include "volumes.h" +#include "tree-mod-log.h" #include "tree-checker.h" +#include "accessors.h" +#include "file-item.h" +#include "kernel-lib/trace.h" + +/* + * MODIFIED: + * - This has to be init'ed to NULL so we know to create it on usage. + */ +static struct kmem_cache *btrfs_path_cachep = NULL; static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level); -static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root - *root, const struct btrfs_key *ins_key, - struct btrfs_path *path, int data_size, int extend); +static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root *root, + const struct btrfs_key *ins_key, struct btrfs_path *path, + int data_size, int extend); static int push_node_left(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct extent_buffer *dst, + struct extent_buffer *dst, struct extent_buffer *src, int empty); static int balance_node_right(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct extent_buffer *dst_buf, struct extent_buffer *src_buf); -static const struct btrfs_csum { - u16 size; - const char name[14]; +static const struct btrfs_csums { + u16 size; + const char name[10]; + const char driver[12]; } btrfs_csums[] = { - [BTRFS_CSUM_TYPE_CRC32] = { 4, "crc32c" }, - [BTRFS_CSUM_TYPE_XXHASH] = { 8, "xxhash64" }, - [BTRFS_CSUM_TYPE_SHA256] = { 32, "sha256" }, - [BTRFS_CSUM_TYPE_BLAKE2] = { 32, "blake2" }, + [BTRFS_CSUM_TYPE_CRC32] = { .size = 4, .name = "crc32c" }, + [BTRFS_CSUM_TYPE_XXHASH] = { .size = 8, .name = "xxhash64" }, + [BTRFS_CSUM_TYPE_SHA256] = { .size = 32, .name = "sha256" }, + [BTRFS_CSUM_TYPE_BLAKE2] = { .size = 32, .name = "blake2b", + .driver = "blake2b-256" }, }; -u16 btrfs_super_csum_size(const struct btrfs_super_block *sb) +/* + * The leaf data grows from end-to-front in the node. this returns the address + * of the start of the last item, which is the stop of the leaf data stack. + */ +static unsigned int leaf_data_end(const struct extent_buffer *leaf) { - const u16 csum_type = btrfs_super_csum_type(sb); + u32 nr = btrfs_header_nritems(leaf); - return btrfs_csums[csum_type].size; + if (nr == 0) + return BTRFS_LEAF_DATA_SIZE(leaf->fs_info); + return btrfs_item_offset(leaf, nr - 1); +} + +/* + * Move data in a @leaf (using memmove, safe for overlapping ranges). + * + * @leaf: leaf that we're doing a memmove on + * @dst_offset: item data offset we're moving to + * @src_offset: item data offset were' moving from + * @len: length of the data we're moving + * + * Wrapper around memmove_extent_buffer() that takes into account the header on + * the leaf. The btrfs_item offset's start directly after the header, so we + * have to adjust any offsets to account for the header in the leaf. This + * handles that math to simplify the callers. + */ +static inline void memmove_leaf_data(const struct extent_buffer *leaf, + unsigned long dst_offset, + unsigned long src_offset, + unsigned long len) +{ + memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, 0) + dst_offset, + btrfs_item_nr_offset(leaf, 0) + src_offset, len); +} + +/* + * Copy item data from @src into @dst at the given @offset. + * + * @dst: destination leaf that we're copying into + * @src: source leaf that we're copying from + * @dst_offset: item data offset we're copying to + * @src_offset: item data offset were' copying from + * @len: length of the data we're copying + * + * Wrapper around copy_extent_buffer() that takes into account the header on + * the leaf. The btrfs_item offset's start directly after the header, so we + * have to adjust any offsets to account for the header in the leaf. This + * handles that math to simplify the callers. + */ +static inline void copy_leaf_data(const struct extent_buffer *dst, + const struct extent_buffer *src, + unsigned long dst_offset, + unsigned long src_offset, unsigned long len) +{ + copy_extent_buffer(dst, src, btrfs_item_nr_offset(dst, 0) + dst_offset, + btrfs_item_nr_offset(src, 0) + src_offset, len); +} + +/* + * Move items in a @leaf (using memmove). + * + * @dst: destination leaf for the items + * @dst_item: the item nr we're copying into + * @src_item: the item nr we're copying from + * @nr_items: the number of items to copy + * + * Wrapper around memmove_extent_buffer() that does the math to get the + * appropriate offsets into the leaf from the item numbers. + */ +static inline void memmove_leaf_items(const struct extent_buffer *leaf, + int dst_item, int src_item, int nr_items) +{ + memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, dst_item), + btrfs_item_nr_offset(leaf, src_item), + nr_items * sizeof(struct btrfs_item)); +} + +/* + * Copy items from @src into @dst at the given @offset. + * + * @dst: destination leaf for the items + * @src: source leaf for the items + * @dst_item: the item nr we're copying into + * @src_item: the item nr we're copying from + * @nr_items: the number of items to copy + * + * Wrapper around copy_extent_buffer() that does the math to get the + * appropriate offsets into the leaf from the item numbers. + */ +static inline void copy_leaf_items(const struct extent_buffer *dst, + const struct extent_buffer *src, + int dst_item, int src_item, int nr_items) +{ + copy_extent_buffer(dst, src, btrfs_item_nr_offset(dst, dst_item), + btrfs_item_nr_offset(src, src_item), + nr_items * sizeof(struct btrfs_item)); +} + +/* This exists for btrfs-progs usages. */ +u16 btrfs_csum_type_size(u16 type) +{ + return btrfs_csums[type].size; +} + +int btrfs_super_csum_size(const struct btrfs_super_block *s) +{ + u16 t = btrfs_super_csum_type(s); + /* + * csum type is validated at mount time + */ + return btrfs_csum_type_size(t); } const char *btrfs_super_csum_name(u16 csum_type) { + /* csum type is validated at mount time */ return btrfs_csums[csum_type].name; } -u16 btrfs_csum_type_size(u16 csum_type) -{ - return btrfs_csums[csum_type].size; -} - -u64 btrfs_name_hash(const char *name, int len) -{ - return crc32c((u32)~1, name, len); -} - /* - * Figure the key offset of an extended inode ref + * Return driver name if defined, otherwise the name that's also a valid driver + * name */ -u64 btrfs_extref_hash(u64 parent_objectid, const char *name, int len) +const char *btrfs_super_csum_driver(u16 csum_type) { - return (u64)crc32c(parent_objectid, name, len); + /* csum type is validated at mount time */ + return btrfs_csums[csum_type].driver[0] ? + btrfs_csums[csum_type].driver : + btrfs_csums[csum_type].name; +} + +size_t __attribute_const__ btrfs_get_num_csums(void) +{ + return ARRAY_SIZE(btrfs_csums); } struct btrfs_path *btrfs_alloc_path(void) { - struct btrfs_path *path; - path = kzalloc(sizeof(struct btrfs_path), GFP_NOFS); - return path; + might_sleep(); + + return kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS); } +/* this also releases the path */ void btrfs_free_path(struct btrfs_path *p) { if (!p) return; btrfs_release_path(p); - kfree(p); + kmem_cache_free(btrfs_path_cachep, p); } -void btrfs_release_path(struct btrfs_path *p) +/* + * path release drops references on the extent buffers in the path + * and it drops any locks held by this path + * + * It is safe to call this on paths that no locks or extent buffers held. + */ +noinline void btrfs_release_path(struct btrfs_path *p) { int i; + for (i = 0; i < BTRFS_MAX_LEVEL; i++) { + p->slots[i] = 0; if (!p->nodes[i]) continue; + if (p->locks[i]) { + btrfs_tree_unlock_rw(p->nodes[i], p->locks[i]); + p->locks[i] = 0; + } free_extent_buffer(p->nodes[i]); + p->nodes[i] = NULL; } - memset(p, 0, sizeof(*p)); } +/* + * We want the transaction abort to print stack trace only for errors where the + * cause could be a bug, eg. due to ENOSPC, and not for common errors that are + * caused by external factors. + */ +bool __cold abort_should_print_stack(int errno) +{ + switch (errno) { + case -EIO: + case -EROFS: + case -ENOMEM: + return false; + } + return true; +} + +/* + * safely gets a reference on the root node of a tree. A lock + * is not taken, so a concurrent writer may put a different node + * at the root of the tree. See btrfs_lock_root_node for the + * looping required. + * + * The extent buffer returned by this has a reference taken, so + * it won't disappear. It may stop being the root of the tree + * at any time because there are no locks held. + */ +struct extent_buffer *btrfs_root_node(struct btrfs_root *root) +{ + struct extent_buffer *eb; + + while (1) { + rcu_read_lock(); + eb = rcu_dereference(root->node); + + /* + * RCU really hurts here, we could free up the root node because + * it was COWed but we may not get the new root node yet so do + * the inc_not_zero dance and if it doesn't work then + * synchronize_rcu and try again. + */ + if (atomic_inc_not_zero(&eb->refs)) { + rcu_read_unlock(); + break; + } + rcu_read_unlock(); + synchronize_rcu(); + } + return eb; +} + +/* + * Cowonly root (not-shareable trees, everything not subvolume or reloc roots), + * just get put onto a simple dirty list. Transaction walks this list to make + * sure they get properly updated on disk. + */ static void add_root_to_dirty_list(struct btrfs_root *root) { - if (test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state) && - list_empty(&root->dirty_list)) { - list_add(&root->dirty_list, - &root->fs_info->dirty_cowonly_roots); + struct btrfs_fs_info *fs_info = root->fs_info; + + if (test_bit(BTRFS_ROOT_DIRTY, &root->state) || + !test_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state)) + return; + + spin_lock(&fs_info->trans_lock); + if (!test_and_set_bit(BTRFS_ROOT_DIRTY, &root->state)) { + /* Want the extent tree to be the last on the list */ + if (root->root_key.objectid == BTRFS_EXTENT_TREE_OBJECTID) + list_move_tail(&root->dirty_list, + &fs_info->dirty_cowonly_roots); + else + list_move(&root->dirty_list, + &fs_info->dirty_cowonly_roots); } + spin_unlock(&fs_info->trans_lock); } -static void root_add_used(struct btrfs_root *root, u32 size) -{ - btrfs_set_root_used(&root->root_item, - btrfs_root_used(&root->root_item) + size); -} - -static void root_sub_used(struct btrfs_root *root, u32 size) -{ - btrfs_set_root_used(&root->root_item, - btrfs_root_used(&root->root_item) - size); -} - +/* + * used by snapshot creation to make a copy of a root for a tree with + * a given objectid. The buffer with the new root node is returned in + * cow_ret, and this func returns zero on success or a negative error code. + */ int btrfs_copy_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, struct extent_buffer **cow_ret, u64 new_root_objectid) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *cow; int ret = 0; int level; - struct btrfs_root *new_root; struct btrfs_disk_key disk_key; - new_root = kmalloc(sizeof(*new_root), GFP_NOFS); - if (!new_root) - return -ENOMEM; - - memcpy(new_root, root, sizeof(*new_root)); - new_root->root_key.objectid = new_root_objectid; - WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && - trans->transid != root->fs_info->running_transaction->transid); + trans->transid != fs_info->running_transaction->transid); WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && trans->transid != root->last_trans); @@ -158,15 +325,14 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, btrfs_item_key(buf, &disk_key, 0); else btrfs_node_key(buf, &disk_key, 0); - cow = btrfs_alloc_tree_block(trans, new_root, 0, new_root_objectid, - &disk_key, level, buf->start, 0, - BTRFS_NESTING_NORMAL); - if (IS_ERR(cow)) { - kfree(new_root); - return PTR_ERR(cow); - } - copy_extent_buffer(cow, buf, 0, 0, cow->len); + cow = btrfs_alloc_tree_block(trans, root, 0, new_root_objectid, + &disk_key, level, buf->start, 0, + BTRFS_NESTING_NEW_ROOT); + if (IS_ERR(cow)) + return PTR_ERR(cow); + + copy_extent_buffer_full(cow, buf); btrfs_set_header_bytenr(cow, cow->start); btrfs_set_header_generation(cow, trans->transid); btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV); @@ -177,15 +343,19 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, else btrfs_set_header_owner(cow, new_root_objectid); - write_extent_buffer(cow, root->fs_info->fs_devices->metadata_uuid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); + write_extent_buffer_fsid(cow, fs_info->fs_devices->metadata_uuid); WARN_ON(btrfs_header_generation(buf) > trans->transid); - ret = btrfs_inc_ref(trans, new_root, cow, 0); - kfree(new_root); - - if (ret) + if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID) + ret = btrfs_inc_ref(trans, root, cow, 1); + else + ret = btrfs_inc_ref(trans, root, cow, 0); + if (ret) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); return ret; + } btrfs_mark_buffer_dirty(cow); *cow_ret = cow; @@ -195,14 +365,13 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans, /* * check if the tree block can be shared by multiple trees */ -static int btrfs_block_can_be_shared(struct btrfs_root *root, - struct extent_buffer *buf) +int btrfs_block_can_be_shared(struct btrfs_root *root, + struct extent_buffer *buf) { /* - * Tree blocks not in reference counted trees and tree roots - * are never shared. If a block was allocated after the last - * snapshot and the block was not allocated by tree relocation, - * we know the block is not shared. + * Tree blocks not in shareable trees and tree roots are never shared. + * If a block was allocated after the last snapshot and the block was + * not allocated by tree relocation, we know the block is not shared. */ if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && buf != root->node && buf != root->commit_root && @@ -210,14 +379,17 @@ static int btrfs_block_can_be_shared(struct btrfs_root *root, btrfs_root_last_snapshot(&root->root_item) || btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC))) return 1; + return 0; } static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, - struct extent_buffer *cow) + struct extent_buffer *cow, + int *last_ref) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 refs; u64 owner; u64 flags; @@ -242,12 +414,16 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, */ if (btrfs_block_can_be_shared(root, buf)) { - ret = btrfs_lookup_extent_info(trans, trans->fs_info, - buf->start, + ret = btrfs_lookup_extent_info(trans, fs_info, buf->start, btrfs_header_level(buf), 1, &refs, &flags); - BUG_ON(ret); - BUG_ON(refs == 0); + if (ret) + return ret; + if (refs == 0) { + ret = -EROFS; + btrfs_handle_fs_error(fs_info, ret, NULL); + return ret; + } } else { refs = 1; if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID || @@ -258,22 +434,25 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, } owner = btrfs_header_owner(buf); - BUG_ON(!(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) && - owner == BTRFS_TREE_RELOC_OBJECTID); + BUG_ON(owner == BTRFS_TREE_RELOC_OBJECTID && + !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)); if (refs > 1) { if ((owner == root->root_key.objectid || root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) { ret = btrfs_inc_ref(trans, root, buf, 1); - BUG_ON(ret); + if (ret) + return ret; if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) { ret = btrfs_dec_ref(trans, root, buf, 0); - BUG_ON(ret); + if (ret) + return ret; ret = btrfs_inc_ref(trans, root, cow, 1); - BUG_ON(ret); + if (ret) + return ret; } new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF; } else { @@ -283,11 +462,13 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, ret = btrfs_inc_ref(trans, root, cow, 1); else ret = btrfs_inc_ref(trans, root, cow, 0); - BUG_ON(ret); + if (ret) + return ret; } if (new_flags != 0) { ret = btrfs_set_disk_extent_flags(trans, buf, new_flags); - BUG_ON(ret); + if (ret) + return ret; } } else { if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) { @@ -296,28 +477,53 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, ret = btrfs_inc_ref(trans, root, cow, 1); else ret = btrfs_inc_ref(trans, root, cow, 0); - BUG_ON(ret); + if (ret) + return ret; ret = btrfs_dec_ref(trans, root, buf, 1); - BUG_ON(ret); + if (ret) + return ret; } btrfs_clear_buffer_dirty(trans, buf); + *last_ref = 1; } return 0; } -static int __btrfs_cow_block(struct btrfs_trans_handle *trans, +/* + * does the dirty work in cow of a single block. The parent block (if + * supplied) is updated to point to the new cow copy. The new buffer is marked + * dirty and returned locked. If you modify the block it needs to be marked + * dirty again. + * + * search_start -- an allocation hint for the new block + * + * empty_size -- a hint that you plan on doing more cow. This is the size in + * bytes the allocator should try to find free next to the block it returns. + * This is just a hint and may be ignored by the allocator. + */ +static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, struct extent_buffer *parent, int parent_slot, struct extent_buffer **cow_ret, - u64 search_start, u64 empty_size) + u64 search_start, u64 empty_size, + enum btrfs_lock_nesting nest) { - struct extent_buffer *cow; + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_disk_key disk_key; - int level; + struct extent_buffer *cow; + int level, ret; + int last_ref = 0; + int unlock_orig = 0; + u64 parent_start = 0; + + if (*cow_ret == buf) + unlock_orig = 1; + + btrfs_assert_tree_write_locked(buf); WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && - trans->transid != root->fs_info->running_transaction->transid); + trans->transid != fs_info->running_transaction->transid); WARN_ON(test_bit(BTRFS_ROOT_SHAREABLE, &root->state) && trans->transid != root->last_trans); @@ -328,13 +534,18 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, else btrfs_node_key(buf, &disk_key, 0); - cow = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, - &disk_key, level, search_start, empty_size, - BTRFS_NESTING_NORMAL); + if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent) + parent_start = parent->start; + + cow = btrfs_alloc_tree_block(trans, root, parent_start, + root->root_key.objectid, &disk_key, level, + search_start, empty_size, nest); if (IS_ERR(cow)) return PTR_ERR(cow); - copy_extent_buffer(cow, buf, 0, 0, cow->len); + /* cow is set to blocking by btrfs_init_new_buffer */ + + copy_extent_buffer_full(cow, buf); btrfs_set_header_bytenr(cow, cow->start); btrfs_set_header_generation(cow, trans->transid); btrfs_set_header_backref_rev(cow, BTRFS_MIXED_BACKREF_REV); @@ -345,39 +556,65 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, else btrfs_set_header_owner(cow, root->root_key.objectid); - write_extent_buffer(cow, root->fs_info->fs_devices->metadata_uuid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); + write_extent_buffer_fsid(cow, fs_info->fs_devices->metadata_uuid); - WARN_ON(!(buf->flags & EXTENT_BUFFER_BAD_TRANSID) && - btrfs_header_generation(buf) > trans->transid); + ret = update_ref_for_cow(trans, root, buf, cow, &last_ref); + if (ret) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); + return ret; + } - update_ref_for_cow(trans, root, buf, cow); + if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) { + ret = btrfs_reloc_cow_block(trans, root, buf, cow); + if (ret) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); + return ret; + } + } if (buf == root->node) { - root->node = cow; - extent_buffer_get(cow); + WARN_ON(parent && parent != buf); + if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID || + btrfs_header_backref_rev(buf) < BTRFS_MIXED_BACKREF_REV) + parent_start = buf->start; - btrfs_free_extent(trans, buf->start, buf->len, 0, - root->root_key.objectid, level, 0); + atomic_inc(&cow->refs); + ret = btrfs_tree_mod_log_insert_root(root->node, cow, true); + BUG_ON(ret < 0); + rcu_assign_pointer(root->node, cow); + + btrfs_free_tree_block(trans, btrfs_root_id(root), buf, + parent_start, last_ref); free_extent_buffer(buf); add_root_to_dirty_list(root); } else { + WARN_ON(trans->transid != btrfs_header_generation(parent)); + btrfs_tree_mod_log_insert_key(parent, parent_slot, + BTRFS_MOD_LOG_KEY_REPLACE); btrfs_set_node_blockptr(parent, parent_slot, cow->start); - WARN_ON(trans->transid == 0); btrfs_set_node_ptr_generation(parent, parent_slot, trans->transid); btrfs_mark_buffer_dirty(parent); - WARN_ON(btrfs_header_generation(parent) != trans->transid); - - btrfs_free_extent(trans, buf->start, buf->len, 0, - root->root_key.objectid, level, 0); + if (last_ref) { + ret = btrfs_tree_mod_log_free_eb(buf); + if (ret) { + btrfs_tree_unlock(cow); + free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); + return ret; + } + } + btrfs_free_tree_block(trans, btrfs_root_id(root), buf, + parent_start, last_ref); } - if (!list_empty(&buf->recow)) { - list_del_init(&buf->recow); - free_extent_buffer(buf); - } - free_extent_buffer(buf); + if (unlock_orig) + btrfs_tree_unlock(buf); + free_extent_buffer_stale(buf); btrfs_mark_buffer_dirty(cow); *cow_ret = cow; return 0; @@ -387,46 +624,137 @@ static inline int should_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf) { + if (btrfs_is_testing(root->fs_info)) + return 0; + + /* Ensure we can see the FORCE_COW bit */ + smp_mb__before_atomic(); + + /* + * We do not need to cow a block if + * 1) this block is not created or changed in this transaction; + * 2) this block does not belong to TREE_RELOC tree; + * 3) the root is not forced COW. + * + * What is forced COW: + * when we create snapshot during committing the transaction, + * after we've finished copying src root, we must COW the shared + * block to ensure the metadata consistency. + */ if (btrfs_header_generation(buf) == trans->transid && !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN) && !(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID && - btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC))) + btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)) && + !test_bit(BTRFS_ROOT_FORCE_COW, &root->state)) return 0; return 1; } -int btrfs_cow_block(struct btrfs_trans_handle *trans, +/* + * cows a single block, see __btrfs_cow_block for the real work. + * This version of it has extra checks so that a block isn't COWed more than + * once per transaction, as long as it hasn't been written yet + */ +noinline int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, struct extent_buffer *parent, int parent_slot, - struct extent_buffer **cow_ret) + struct extent_buffer **cow_ret, + enum btrfs_lock_nesting nest) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 search_start; int ret; + + if (test_bit(BTRFS_ROOT_DELETING, &root->state)) + btrfs_err(fs_info, + "COW'ing blocks on a fs root that's being dropped"); + /* - if (trans->transaction != root->fs_info->running_transaction) { - printk(KERN_CRIT "trans %llu running %llu\n", trans->transid, - root->fs_info->running_transaction->transid); - WARN_ON(1); - } + * MODIFIED: + * - In the kernel we have a transaction and a trans_handle, here we + * only have a trans_handle, so just don't worry about this right + * now. + * + if (trans->transaction != fs_info->running_transaction) + WARN(1, KERN_CRIT "trans %llu running %llu\n", + trans->transid, + fs_info->running_transaction->transid); */ - if (trans->transid != root->fs_info->generation) { - printk(KERN_CRIT "trans %llu running %llu\n", - (unsigned long long)trans->transid, - (unsigned long long)root->fs_info->generation); - WARN_ON(1); - } + + if (trans->transid != fs_info->generation) + WARN(1, KERN_CRIT "trans %llu running %llu\n", + trans->transid, fs_info->generation); + if (!should_cow_block(trans, root, buf)) { *cow_ret = buf; return 0; } search_start = buf->start & ~((u64)SZ_1G - 1); + + /* + * Before CoWing this block for later modification, check if it's + * the subtree root and do the delayed subtree trace if needed. + * + * Also We don't care about the error, as it's handled internally. + */ + btrfs_qgroup_trace_subtree_after_cow(trans, root, buf); ret = __btrfs_cow_block(trans, root, buf, parent, - parent_slot, cow_ret, search_start, 0); + parent_slot, cow_ret, search_start, 0, nest); + + trace_btrfs_cow_block(root, buf, *cow_ret); + return ret; } +ALLOW_ERROR_INJECTION(btrfs_cow_block, ERRNO); -int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2) +/* + * helper function for defrag to decide if two blocks pointed to by a + * node are actually close by + */ +static int close_blocks(u64 blocknr, u64 other, u32 blocksize) +{ + if (blocknr < other && other - (blocknr + blocksize) < 32768) + return 1; + if (blocknr > other && blocknr - (other + blocksize) < 32768) + return 1; + return 0; +} + +#ifdef __LITTLE_ENDIAN + +/* + * Compare two keys, on little-endian the disk order is same as CPU order and + * we can avoid the conversion. + */ +static int comp_keys(const struct btrfs_disk_key *disk_key, + const struct btrfs_key *k2) +{ + const struct btrfs_key *k1 = (const struct btrfs_key *)disk_key; + + return btrfs_comp_cpu_keys(k1, k2); +} + +#else + +/* + * compare two keys in a memcmp fashion + */ +static int comp_keys(const struct btrfs_disk_key *disk, + const struct btrfs_key *k2) +{ + struct btrfs_key k1; + + btrfs_disk_key_to_cpu(&k1, disk); + + return btrfs_comp_cpu_keys(&k1, k2); +} +#endif + +/* + * same as comp_keys only with two btrfs_key's + */ +int __pure btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2) { if (k1->objectid > k2->objectid) return 1; @@ -444,73 +772,157 @@ int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2) } /* - * compare two keys in a memcmp fashion + * this is used by the defrag code to go through all the + * leaves pointed to by a node and reallocate them so that + * disk order is close to key order */ -static int btrfs_comp_keys(struct btrfs_disk_key *disk, - const struct btrfs_key *k2) +int btrfs_realloc_node(struct btrfs_trans_handle *trans, + struct btrfs_root *root, struct extent_buffer *parent, + int start_slot, u64 *last_ret, + struct btrfs_key *progress) { - struct btrfs_key k1; + struct btrfs_fs_info *fs_info = root->fs_info; + struct extent_buffer *cur; + u64 blocknr; + u64 search_start = *last_ret; + u64 last_block = 0; + u64 other; + u32 parent_nritems; + int end_slot; + int i; + int err = 0; + u32 blocksize; + int progress_passed = 0; + struct btrfs_disk_key disk_key; - btrfs_disk_key_to_cpu(&k1, disk); - return btrfs_comp_cpu_keys(&k1, k2); + /* + * MODIFIED: + * - We don't have struct btrfs_transaction in btrfs-progs yet. + * + WARN_ON(trans->transaction != fs_info->running_transaction); + */ + + WARN_ON(trans->transid != fs_info->generation); + + parent_nritems = btrfs_header_nritems(parent); + blocksize = fs_info->nodesize; + end_slot = parent_nritems - 1; + + if (parent_nritems <= 1) + return 0; + + for (i = start_slot; i <= end_slot; i++) { + int close = 1; + + btrfs_node_key(parent, &disk_key, i); + if (!progress_passed && comp_keys(&disk_key, progress) < 0) + continue; + + progress_passed = 1; + blocknr = btrfs_node_blockptr(parent, i); + if (last_block == 0) + last_block = blocknr; + + if (i > 0) { + other = btrfs_node_blockptr(parent, i - 1); + close = close_blocks(blocknr, other, blocksize); + } + if (!close && i < end_slot) { + other = btrfs_node_blockptr(parent, i + 1); + close = close_blocks(blocknr, other, blocksize); + } + if (close) { + last_block = blocknr; + continue; + } + + cur = btrfs_read_node_slot(parent, i); + if (IS_ERR(cur)) + return PTR_ERR(cur); + if (search_start == 0) + search_start = last_block; + + btrfs_tree_lock(cur); + err = __btrfs_cow_block(trans, root, cur, parent, i, + &cur, search_start, + min(16 * blocksize, + (end_slot - i) * blocksize), + BTRFS_NESTING_COW); + if (err) { + btrfs_tree_unlock(cur); + free_extent_buffer(cur); + break; + } + search_start = cur->start; + last_block = cur->start; + *last_ret = search_start; + btrfs_tree_unlock(cur); + free_extent_buffer(cur); + } + return err; } /* - * The leaf data grows from end-to-front in the node. - * this returns the address of the start of the last item, - * which is the stop of the leaf data stack - */ -static inline unsigned int leaf_data_end(const struct extent_buffer *leaf) -{ - u32 nr = btrfs_header_nritems(leaf); - if (nr == 0) - return BTRFS_LEAF_DATA_SIZE(leaf->fs_info); - return btrfs_item_offset(leaf, nr - 1); -} - -static int noinline check_block(struct btrfs_fs_info *fs_info, - struct btrfs_path *path, int level) -{ - enum btrfs_tree_block_status ret; - - if (path->skip_check_block) - return 0; - if (level == 0) - ret = __btrfs_check_leaf(path->nodes[0]); - else - ret = __btrfs_check_node(path->nodes[level]); - if (ret == BTRFS_TREE_BLOCK_CLEAN) - return 0; - return -EIO; -} - -/* - * search for key in the extent_buffer. The items start at offset p, - * and they are item_size apart. There are 'max' items in p. + * Search for a key in the given extent_buffer. * - * the slot in the array is returned via slot, and it points to - * the place where you would insert key if it is not found in - * the array. + * The lower boundary for the search is specified by the slot number @first_slot. + * Use a value of 0 to search over the whole extent buffer. Works for both + * leaves and nodes. * - * slot may point to max if the key is bigger than all of the keys + * The slot in the extent buffer is returned via @slot. If the key exists in the + * extent buffer, then @slot will point to the slot where the key is, otherwise + * it points to the slot where you would insert the key. + * + * Slot may point to the total number of items (i.e. one position beyond the last + * key) if the key is bigger than the last key in the extent buffer. */ -static int generic_bin_search(struct extent_buffer *eb, unsigned long p, - int item_size, const struct btrfs_key *key, - int max, int *slot) +int btrfs_bin_search(struct extent_buffer *eb, int first_slot, + const struct btrfs_key *key, int *slot) { - int low = 0; - int high = max; - int mid; + unsigned long p; + int item_size; + /* + * Use unsigned types for the low and high slots, so that we get a more + * efficient division in the search loop below. + */ + u32 low = first_slot; + u32 high = btrfs_header_nritems(eb); int ret; - unsigned long offset; - struct btrfs_disk_key *tmp; + const int key_size = sizeof(struct btrfs_disk_key); + + if (unlikely(low > high)) { + btrfs_err(eb->fs_info, + "%s: low (%u) > high (%u) eb %llu owner %llu level %d", + __func__, low, high, eb->start, + btrfs_header_owner(eb), btrfs_header_level(eb)); + return -EINVAL; + } + + if (btrfs_header_level(eb) == 0) { + p = offsetof(struct btrfs_leaf, items); + item_size = sizeof(struct btrfs_item); + } else { + p = offsetof(struct btrfs_node, ptrs); + item_size = sizeof(struct btrfs_key_ptr); + } + + /* + * MODIFIED: + * - Removed the oip + key_size <= PAGE_SIZE optimization. + */ + while (low < high) { + unsigned long offset; + struct btrfs_disk_key *tmp; + struct btrfs_disk_key unaligned; + int mid; - while(low < high) { mid = (low + high) / 2; offset = p + mid * item_size; - tmp = (struct btrfs_disk_key *)(eb->data + offset); - ret = btrfs_comp_keys(tmp, key); + read_extent_buffer(eb, &unaligned, offset, key_size); + tmp = &unaligned; + + ret = comp_keys(tmp, key); if (ret < 0) low = mid + 1; @@ -525,79 +937,79 @@ static int generic_bin_search(struct extent_buffer *eb, unsigned long p, return 1; } -/* - * simple bin_search frontend that does the right thing for - * leaves vs nodes - */ -int btrfs_bin_search(struct extent_buffer *eb, int first_slot, - const struct btrfs_key *key, int *slot) +static void root_add_used(struct btrfs_root *root, u32 size) { - if (btrfs_header_level(eb) == 0) - return generic_bin_search(eb, - offsetof(struct btrfs_leaf, items), - sizeof(struct btrfs_item), - key, btrfs_header_nritems(eb), - slot); - else - return generic_bin_search(eb, - offsetof(struct btrfs_node, ptrs), - sizeof(struct btrfs_key_ptr), - key, btrfs_header_nritems(eb), - slot); + spin_lock(&root->accounting_lock); + btrfs_set_root_used(&root->root_item, + btrfs_root_used(&root->root_item) + size); + spin_unlock(&root->accounting_lock); } +static void root_sub_used(struct btrfs_root *root, u32 size) +{ + spin_lock(&root->accounting_lock); + btrfs_set_root_used(&root->root_item, + btrfs_root_used(&root->root_item) - size); + spin_unlock(&root->accounting_lock); +} + +/* given a node and slot number, this reads the blocks it points to. The + * extent buffer is returned with a reference taken (but unlocked). + * + * MODIFIED: + * - Removed the btrfs_tree_parent_check stuff as we don't have that yet. + */ struct extent_buffer *btrfs_read_node_slot(struct extent_buffer *parent, int slot) { - struct btrfs_fs_info *fs_info = parent->fs_info; - struct extent_buffer *ret; int level = btrfs_header_level(parent); + struct extent_buffer *eb; + struct btrfs_key first_key; - if (slot < 0) - return NULL; - if (slot >= btrfs_header_nritems(parent)) - return NULL; + if (slot < 0 || slot >= btrfs_header_nritems(parent)) + return ERR_PTR(-ENOENT); - if (level == 0) - return NULL; + ASSERT(level); - ret = read_tree_block(fs_info, btrfs_node_blockptr(parent, slot), - btrfs_header_owner(parent), - btrfs_node_ptr_generation(parent, slot), - level - 1, NULL); - if (!extent_buffer_uptodate(ret)) - return ERR_PTR(-EIO); - - if (btrfs_header_level(ret) != level - 1) { - error( -"child eb corrupted: parent bytenr=%llu item=%d parent level=%d child bytenr=%llu child level=%d", - btrfs_header_bytenr(parent), slot, btrfs_header_level(parent), - btrfs_header_bytenr(ret), btrfs_header_level(ret)); - free_extent_buffer(ret); + eb = read_tree_block(parent->fs_info, btrfs_node_blockptr(parent, slot), + btrfs_header_owner(parent), + btrfs_node_ptr_generation(parent, slot), + level - 1, &first_key); + if (IS_ERR(eb)) + return eb; + if (!extent_buffer_uptodate(eb)) { + free_extent_buffer(eb); return ERR_PTR(-EIO); } - return ret; + + return eb; } -static int balance_level(struct btrfs_trans_handle *trans, +/* + * node level balancing, used to make sure nodes are in proper order for + * item deletion. We balance from the top down, so we have to make sure + * that a deletion won't leave an node completely empty later on. + */ +static noinline int balance_level(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *right = NULL; struct extent_buffer *mid; struct extent_buffer *left = NULL; struct extent_buffer *parent = NULL; - struct btrfs_fs_info *fs_info = root->fs_info; int ret = 0; int wret; int pslot; int orig_slot = path->slots[level]; u64 orig_ptr; - if (level == 0) - return 0; + ASSERT(level > 0); mid = path->nodes[level]; + + WARN_ON(path->locks[level] != BTRFS_WRITE_LOCK); WARN_ON(btrfs_header_generation(mid) != trans->transid); orig_ptr = btrfs_node_blockptr(mid, orig_slot); @@ -619,42 +1031,75 @@ static int balance_level(struct btrfs_trans_handle *trans, /* promote the child to a root */ child = btrfs_read_node_slot(mid, 0); - BUG_ON(!extent_buffer_uptodate(child)); - ret = btrfs_cow_block(trans, root, child, mid, 0, &child); - BUG_ON(ret); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + btrfs_handle_fs_error(fs_info, ret, NULL); + goto enospc; + } + + btrfs_tree_lock(child); + ret = btrfs_cow_block(trans, root, child, mid, 0, &child, + BTRFS_NESTING_COW); + if (ret) { + btrfs_tree_unlock(child); + free_extent_buffer(child); + goto enospc; + } + + ret = btrfs_tree_mod_log_insert_root(root->node, child, true); + BUG_ON(ret < 0); + rcu_assign_pointer(root->node, child); - root->node = child; add_root_to_dirty_list(root); + btrfs_tree_unlock(child); + + path->locks[level] = 0; path->nodes[level] = NULL; btrfs_clear_buffer_dirty(trans, mid); + btrfs_tree_unlock(mid); /* once for the path */ free_extent_buffer(mid); root_sub_used(root, mid->len); - - ret = btrfs_free_extent(trans, mid->start, mid->len, 0, - root->root_key.objectid, level, 0); + btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1); /* once for the root ptr */ - free_extent_buffer(mid); - return ret; + free_extent_buffer_stale(mid); + return 0; } if (btrfs_header_nritems(mid) > BTRFS_NODEPTRS_PER_BLOCK(fs_info) / 4) return 0; - left = btrfs_read_node_slot(parent, pslot - 1); - if (extent_buffer_uptodate(left)) { + if (pslot) { + left = btrfs_read_node_slot(parent, pslot - 1); + if (IS_ERR(left)) { + ret = PTR_ERR(left); + left = NULL; + goto enospc; + } + + __btrfs_tree_lock(left, BTRFS_NESTING_LEFT); wret = btrfs_cow_block(trans, root, left, - parent, pslot - 1, &left); + parent, pslot - 1, &left, + BTRFS_NESTING_LEFT_COW); if (wret) { ret = wret; goto enospc; } } - right = btrfs_read_node_slot(parent, pslot + 1); - if (extent_buffer_uptodate(right)) { + + if (pslot + 1 < btrfs_header_nritems(parent)) { + right = btrfs_read_node_slot(parent, pslot + 1); + if (IS_ERR(right)) { + ret = PTR_ERR(right); + right = NULL; + goto enospc; + } + + __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT); wret = btrfs_cow_block(trans, root, right, - parent, pslot + 1, &right); + parent, pslot + 1, &right, + BTRFS_NESTING_RIGHT_COW); if (wret) { ret = wret; goto enospc; @@ -664,7 +1109,7 @@ static int balance_level(struct btrfs_trans_handle *trans, /* first, try to make some room in the middle buffer */ if (left) { orig_slot += btrfs_header_nritems(left); - wret = push_node_left(trans, root, left, mid, 1); + wret = push_node_left(trans, left, mid, 1); if (wret < 0) ret = wret; } @@ -673,27 +1118,24 @@ static int balance_level(struct btrfs_trans_handle *trans, * then try to empty the right most buffer into the middle */ if (right) { - wret = push_node_left(trans, root, mid, right, 1); + wret = push_node_left(trans, mid, right, 1); if (wret < 0 && wret != -ENOSPC) ret = wret; if (btrfs_header_nritems(right) == 0) { - u64 bytenr = right->start; - u32 blocksize = right->len; - btrfs_clear_buffer_dirty(trans, right); - free_extent_buffer(right); - right = NULL; + btrfs_tree_unlock(right); btrfs_del_ptr(root, path, level + 1, pslot + 1); - - root_sub_used(root, blocksize); - wret = btrfs_free_extent(trans, bytenr, blocksize, 0, - root->root_key.objectid, level, - 0); - if (wret) - ret = wret; + root_sub_used(root, right->len); + btrfs_free_tree_block(trans, btrfs_root_id(root), right, + 0, 1); + free_extent_buffer_stale(right); + right = NULL; } else { struct btrfs_disk_key right_key; btrfs_node_key(right, &right_key, 0); + ret = btrfs_tree_mod_log_insert_key(parent, pslot + 1, + BTRFS_MOD_LOG_KEY_REPLACE); + BUG_ON(ret < 0); btrfs_set_node_key(parent, &right_key, pslot + 1); btrfs_mark_buffer_dirty(parent); } @@ -708,37 +1150,38 @@ static int balance_level(struct btrfs_trans_handle *trans, * otherwise we would have pulled some pointers from the * right */ - BUG_ON(!left); - wret = balance_node_right(trans, root, mid, left); + if (!left) { + ret = -EROFS; + btrfs_handle_fs_error(fs_info, ret, NULL); + goto enospc; + } + wret = balance_node_right(trans, mid, left); if (wret < 0) { ret = wret; goto enospc; } if (wret == 1) { - wret = push_node_left(trans, root, left, mid, 1); + wret = push_node_left(trans, left, mid, 1); if (wret < 0) ret = wret; } BUG_ON(wret == 1); } if (btrfs_header_nritems(mid) == 0) { - /* we've managed to empty the middle node, drop it */ - u64 bytenr = mid->start; - u32 blocksize = mid->len; btrfs_clear_buffer_dirty(trans, mid); - free_extent_buffer(mid); - mid = NULL; + btrfs_tree_unlock(mid); btrfs_del_ptr(root, path, level + 1, pslot); - - root_sub_used(root, blocksize); - wret = btrfs_free_extent(trans, bytenr, blocksize, 0, - root->root_key.objectid, level, 0); - if (wret) - ret = wret; + root_sub_used(root, mid->len); + btrfs_free_tree_block(trans, btrfs_root_id(root), mid, 0, 1); + free_extent_buffer_stale(mid); + mid = NULL; } else { /* update the parent key to reflect our changes */ struct btrfs_disk_key mid_key; btrfs_node_key(mid, &mid_key, 0); + ret = btrfs_tree_mod_log_insert_key(parent, pslot, + BTRFS_MOD_LOG_KEY_REPLACE); + BUG_ON(ret < 0); btrfs_set_node_key(parent, &mid_key, pslot); btrfs_mark_buffer_dirty(parent); } @@ -746,40 +1189,50 @@ static int balance_level(struct btrfs_trans_handle *trans, /* update the path */ if (left) { if (btrfs_header_nritems(left) > orig_slot) { - extent_buffer_get(left); + atomic_inc(&left->refs); + /* left was locked after cow */ path->nodes[level] = left; path->slots[level + 1] -= 1; path->slots[level] = orig_slot; - if (mid) + if (mid) { + btrfs_tree_unlock(mid); free_extent_buffer(mid); + } } else { orig_slot -= btrfs_header_nritems(left); path->slots[level] = orig_slot; } } /* double check we haven't messed things up */ - check_block(root->fs_info, path, level); if (orig_ptr != btrfs_node_blockptr(path->nodes[level], path->slots[level])) BUG(); enospc: - if (right) + if (right) { + btrfs_tree_unlock(right); free_extent_buffer(right); - if (left) + } + if (left) { + if (path->nodes[level] != left) + btrfs_tree_unlock(left); free_extent_buffer(left); + } return ret; } -/* returns zero if the push worked, non-zero otherwise */ -static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, +/* Node balancing for insertion. Here we only split or push nodes around + * when they are completely full. This is also done top down, so we + * have to be pessimistic. + */ +static noinline int push_nodes_for_insert(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *right = NULL; struct extent_buffer *mid; struct extent_buffer *left = NULL; struct extent_buffer *parent = NULL; - struct btrfs_fs_info *fs_info = root->fs_info; int ret = 0; int wret; int pslot; @@ -799,22 +1252,27 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, if (!parent) return 1; - left = btrfs_read_node_slot(parent, pslot - 1); - /* first, try to make some room in the middle buffer */ - if (extent_buffer_uptodate(left)) { + if (pslot) { u32 left_nr; + + left = btrfs_read_node_slot(parent, pslot - 1); + if (IS_ERR(left)) + return PTR_ERR(left); + + __btrfs_tree_lock(left, BTRFS_NESTING_LEFT); + left_nr = btrfs_header_nritems(left); if (left_nr >= BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 1) { wret = 1; } else { ret = btrfs_cow_block(trans, root, left, parent, - pslot - 1, &left); + pslot - 1, &left, + BTRFS_NESTING_LEFT_COW); if (ret) wret = 1; else { - wret = push_node_left(trans, root, - left, mid, 0); + wret = push_node_left(trans, left, mid, 0); } } if (wret < 0) @@ -823,42 +1281,53 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, struct btrfs_disk_key disk_key; orig_slot += left_nr; btrfs_node_key(mid, &disk_key, 0); + ret = btrfs_tree_mod_log_insert_key(parent, pslot, + BTRFS_MOD_LOG_KEY_REPLACE); + BUG_ON(ret < 0); btrfs_set_node_key(parent, &disk_key, pslot); btrfs_mark_buffer_dirty(parent); if (btrfs_header_nritems(left) > orig_slot) { path->nodes[level] = left; path->slots[level + 1] -= 1; path->slots[level] = orig_slot; + btrfs_tree_unlock(mid); free_extent_buffer(mid); } else { orig_slot -= btrfs_header_nritems(left); path->slots[level] = orig_slot; + btrfs_tree_unlock(left); free_extent_buffer(left); } return 0; } + btrfs_tree_unlock(left); free_extent_buffer(left); } - right= btrfs_read_node_slot(parent, pslot + 1); /* * then try to empty the right most buffer into the middle */ - if (extent_buffer_uptodate(right)) { + if (pslot + 1 < btrfs_header_nritems(parent)) { u32 right_nr; + + right = btrfs_read_node_slot(parent, pslot + 1); + if (IS_ERR(right)) + return PTR_ERR(right); + + __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT); + right_nr = btrfs_header_nritems(right); - if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(root->fs_info) - 1) { + if (right_nr >= BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 1) { wret = 1; } else { ret = btrfs_cow_block(trans, root, right, parent, pslot + 1, - &right); + &right, BTRFS_NESTING_RIGHT_COW); if (ret) wret = 1; else { - wret = balance_node_right(trans, root, - right, mid); + wret = balance_node_right(trans, right, mid); } } if (wret < 0) @@ -867,6 +1336,9 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, struct btrfs_disk_key disk_key; btrfs_node_key(right, &disk_key, 0); + ret = btrfs_tree_mod_log_insert_key(parent, pslot + 1, + BTRFS_MOD_LOG_KEY_REPLACE); + BUG_ON(ret < 0); btrfs_set_node_key(parent, &disk_key, pslot + 1); btrfs_mark_buffer_dirty(parent); @@ -875,244 +1347,1045 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, path->slots[level + 1] += 1; path->slots[level] = orig_slot - btrfs_header_nritems(mid); + btrfs_tree_unlock(mid); free_extent_buffer(mid); } else { + btrfs_tree_unlock(right); free_extent_buffer(right); } return 0; } + btrfs_tree_unlock(right); free_extent_buffer(right); } return 1; } /* - * readahead one full node of leaves + * readahead one full node of leaves, finding things that are close + * to the block in 'slot', and triggering ra on them. */ static void reada_for_search(struct btrfs_fs_info *fs_info, - struct btrfs_path *path, int level, int slot, - u64 objectid) + struct btrfs_path *path, + int level, int slot, u64 objectid) { struct extent_buffer *node; struct btrfs_disk_key disk_key; u32 nritems; u64 search; - u64 lowest_read; - u64 highest_read; + u64 target; u64 nread = 0; - int direction = path->reada; - struct extent_buffer *eb; + u64 nread_max; u32 nr; + u32 blocksize; u32 nscan = 0; - if (level != 1) + if (level != 1 && path->reada != READA_FORWARD_ALWAYS) return; if (!path->nodes[level]) return; node = path->nodes[level]; - search = btrfs_node_blockptr(node, slot); - eb = btrfs_find_tree_block(fs_info, search, fs_info->nodesize); - if (eb) { - free_extent_buffer(eb); - return; + + /* + * Since the time between visiting leaves is much shorter than the time + * between visiting nodes, limit read ahead of nodes to 1, to avoid too + * much IO at once (possibly random). + */ + if (path->reada == READA_FORWARD_ALWAYS) { + if (level > 1) + nread_max = node->fs_info->nodesize; + else + nread_max = SZ_128K; + } else { + nread_max = SZ_64K; } - highest_read = search; - lowest_read = search; + search = btrfs_node_blockptr(node, slot); + blocksize = fs_info->nodesize; + if (path->reada != READA_FORWARD_ALWAYS) { + struct extent_buffer *eb; + + eb = find_extent_buffer(fs_info, search); + if (eb) { + free_extent_buffer(eb); + return; + } + } + + target = search; nritems = btrfs_header_nritems(node); nr = slot; - while(1) { - if (direction < 0) { + + while (1) { + if (path->reada == READA_BACK) { if (nr == 0) break; nr--; - } else if (direction > 0) { + } else if (path->reada == READA_FORWARD || + path->reada == READA_FORWARD_ALWAYS) { nr++; if (nr >= nritems) break; } - if (path->reada < 0 && objectid) { + if (path->reada == READA_BACK && objectid) { btrfs_node_key(node, &disk_key, nr); if (btrfs_disk_key_objectid(&disk_key) != objectid) break; } search = btrfs_node_blockptr(node, nr); - if ((search >= lowest_read && search <= highest_read) || - (search < lowest_read && lowest_read - search <= 32768) || - (search > highest_read && search - highest_read <= 32768)) { - readahead_tree_block(fs_info, search, - btrfs_node_ptr_generation(node, nr)); - nread += fs_info->nodesize; + if (path->reada == READA_FORWARD_ALWAYS || + (search <= target && target - search <= 65536) || + (search > target && search - target <= 65536)) { + btrfs_readahead_node_child(node, nr); + nread += blocksize; } nscan++; - if (path->reada < 2 && (nread > SZ_256K || nscan > 32)) + if (nread > nread_max || nscan > 32) break; - if(nread > SZ_1M || nscan > 128) - break; - - if (search < lowest_read) - lowest_read = search; - if (search > highest_read) - highest_read = search; } } -int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *found_path, +static noinline void reada_for_balance(struct btrfs_path *path, int level) +{ + struct extent_buffer *parent; + int slot; + int nritems; + + parent = path->nodes[level + 1]; + if (!parent) + return; + + nritems = btrfs_header_nritems(parent); + slot = path->slots[level + 1]; + + if (slot > 0) + btrfs_readahead_node_child(parent, slot - 1); + if (slot + 1 < nritems) + btrfs_readahead_node_child(parent, slot + 1); +} + + +/* + * when we walk down the tree, it is usually safe to unlock the higher layers + * in the tree. The exceptions are when our path goes through slot 0, because + * operations on the tree might require changing key pointers higher up in the + * tree. + * + * callers might also have set path->keep_locks, which tells this code to keep + * the lock if the path points to the last slot in the block. This is part of + * walking through the tree, and selecting the next slot in the higher block. + * + * lowest_unlock sets the lowest level in the tree we're allowed to unlock. so + * if lowest_unlock is 1, level 0 won't be unlocked + */ +static noinline void unlock_up(struct btrfs_path *path, int level, + int lowest_unlock, int min_write_lock_level, + int *write_lock_level) +{ + int i; + int skip_level = level; + bool check_skip = true; + + for (i = level; i < BTRFS_MAX_LEVEL; i++) { + if (!path->nodes[i]) + break; + if (!path->locks[i]) + break; + + if (check_skip) { + if (path->slots[i] == 0) { + skip_level = i + 1; + continue; + } + + if (path->keep_locks) { + u32 nritems; + + nritems = btrfs_header_nritems(path->nodes[i]); + if (nritems < 1 || path->slots[i] >= nritems - 1) { + skip_level = i + 1; + continue; + } + } + } + + if (i >= lowest_unlock && i > skip_level) { + check_skip = false; + btrfs_tree_unlock_rw(path->nodes[i], path->locks[i]); + path->locks[i] = 0; + if (write_lock_level && + i > min_write_lock_level && + i <= *write_lock_level) { + *write_lock_level = i - 1; + } + } + } +} + +/* + * Helper function for btrfs_search_slot() and other functions that do a search + * on a btree. The goal is to find a tree block in the cache (the radix tree at + * fs_info->buffer_radix), but if we can't find it, or it's not up to date, read + * its pages from disk. + * + * Returns -EAGAIN, with the path unlocked, if the caller needs to repeat the + * whole btree search, starting again from the current root node. + * + * MODIFIED: + * - Removed the btrfs_tree_parent_check stuff as that doesn't exist yet. + */ +static int +read_block_for_search(struct btrfs_root *root, struct btrfs_path *p, + struct extent_buffer **eb_ret, int level, int slot, + const struct btrfs_key *key) +{ + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_key first_key; + u64 blocknr; + u64 gen; + struct extent_buffer *tmp; + int ret; + int parent_level; + bool unlock_up; + + unlock_up = ((level + 1 < BTRFS_MAX_LEVEL) && p->locks[level + 1]); + blocknr = btrfs_node_blockptr(*eb_ret, slot); + gen = btrfs_node_ptr_generation(*eb_ret, slot); + parent_level = btrfs_header_level(*eb_ret); + btrfs_node_key_to_cpu(*eb_ret, &first_key, slot); + + /* + * If we need to read an extent buffer from disk and we are holding locks + * on upper level nodes, we unlock all the upper nodes before reading the + * extent buffer, and then return -EAGAIN to the caller as it needs to + * restart the search. We don't release the lock on the current level + * because we need to walk this node to figure out which blocks to read. + */ + tmp = find_extent_buffer(fs_info, blocknr); + if (tmp) { + if (p->reada == READA_FORWARD_ALWAYS) + reada_for_search(fs_info, p, level, slot, key->objectid); + + /* first we do an atomic uptodate check */ + if (btrfs_buffer_uptodate(tmp, gen, 1) > 0) { + /* + * Do extra check for first_key, eb can be stale due to + * being cached, read from scrub, or have multiple + * parents (shared tree blocks). + */ + if (btrfs_verify_level_key(tmp, + parent_level - 1, &first_key, gen)) { + free_extent_buffer(tmp); + return -EUCLEAN; + } + *eb_ret = tmp; + return 0; + } + + if (p->nowait) { + free_extent_buffer(tmp); + return -EAGAIN; + } + + if (unlock_up) + btrfs_unlock_up_safe(p, level + 1); + + /* now we're allowed to do a blocking uptodate check */ + ret = btrfs_read_extent_buffer(tmp, gen, parent_level - 1, + &first_key); + if (ret) { + free_extent_buffer(tmp); + btrfs_release_path(p); + return -EIO; + } + if (btrfs_check_eb_owner(tmp, root->root_key.objectid)) { + free_extent_buffer(tmp); + btrfs_release_path(p); + return -EUCLEAN; + } + + if (unlock_up) + ret = -EAGAIN; + + goto out; + } else if (p->nowait) { + return -EAGAIN; + } + + if (unlock_up) { + btrfs_unlock_up_safe(p, level + 1); + ret = -EAGAIN; + } else { + ret = 0; + } + + if (p->reada != READA_NONE) + reada_for_search(fs_info, p, level, slot, key->objectid); + + tmp = read_tree_block(fs_info, blocknr, root->root_key.objectid, + gen, parent_level - 1, &first_key); + if (IS_ERR(tmp)) { + btrfs_release_path(p); + return PTR_ERR(tmp); + } + /* + * If the read above didn't mark this buffer up to date, + * it will never end up being up to date. Set ret to EIO now + * and give up so that our caller doesn't loop forever + * on our EAGAINs. + */ + if (!extent_buffer_uptodate(tmp)) + ret = -EIO; + +out: + if (ret == 0) { + *eb_ret = tmp; + } else { + free_extent_buffer(tmp); + btrfs_release_path(p); + } + + return ret; +} + +/* + * helper function for btrfs_search_slot. This does all of the checks + * for node-level blocks and does any balancing required based on + * the ins_len. + * + * If no extra work was required, zero is returned. If we had to + * drop the path, -EAGAIN is returned and btrfs_search_slot must + * start over + */ +static int +setup_nodes_for_search(struct btrfs_trans_handle *trans, + struct btrfs_root *root, struct btrfs_path *p, + struct extent_buffer *b, int level, int ins_len, + int *write_lock_level) +{ + struct btrfs_fs_info *fs_info = root->fs_info; + int ret = 0; + + if ((p->search_for_split || ins_len > 0) && btrfs_header_nritems(b) >= + BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 3) { + + if (*write_lock_level < level + 1) { + *write_lock_level = level + 1; + btrfs_release_path(p); + return -EAGAIN; + } + + reada_for_balance(p, level); + ret = split_node(trans, root, p, level); + + b = p->nodes[level]; + } else if (ins_len < 0 && btrfs_header_nritems(b) < + BTRFS_NODEPTRS_PER_BLOCK(fs_info) / 2) { + + if (*write_lock_level < level + 1) { + *write_lock_level = level + 1; + btrfs_release_path(p); + return -EAGAIN; + } + + reada_for_balance(p, level); + ret = balance_level(trans, root, p, level); + if (ret) + return ret; + + b = p->nodes[level]; + if (!b) { + btrfs_release_path(p); + return -EAGAIN; + } + BUG_ON(btrfs_header_nritems(b) == 1); + } + return ret; +} + +int btrfs_find_item(struct btrfs_root *fs_root, struct btrfs_path *path, u64 iobjectid, u64 ioff, u8 key_type, struct btrfs_key *found_key) { int ret; struct btrfs_key key; struct extent_buffer *eb; - struct btrfs_path *path; + + ASSERT(path); + ASSERT(found_key); key.type = key_type; key.objectid = iobjectid; key.offset = ioff; - if (found_path == NULL) { - path = btrfs_alloc_path(); - if (!path) - return -ENOMEM; - } else - path = found_path; - ret = btrfs_search_slot(NULL, fs_root, &key, path, 0, 0); - if ((ret < 0) || (found_key == NULL)) - goto out; + if (ret < 0) + return ret; eb = path->nodes[0]; if (ret && path->slots[0] >= btrfs_header_nritems(eb)) { ret = btrfs_next_leaf(fs_root, path); if (ret) - goto out; + return ret; eb = path->nodes[0]; } btrfs_item_key_to_cpu(eb, found_key, path->slots[0]); if (found_key->type != key.type || - found_key->objectid != key.objectid) { - ret = 1; + found_key->objectid != key.objectid) + return 1; + + return 0; +} + +static struct extent_buffer *btrfs_search_slot_get_root(struct btrfs_root *root, + struct btrfs_path *p, + int write_lock_level) +{ + struct extent_buffer *b; + int root_lock = 0; + int level = 0; + + if (p->search_commit_root) { + b = root->commit_root; + atomic_inc(&b->refs); + level = btrfs_header_level(b); + /* + * Ensure that all callers have set skip_locking when + * p->search_commit_root = 1. + */ + ASSERT(p->skip_locking == 1); + goto out; } + if (p->skip_locking) { + b = btrfs_root_node(root); + level = btrfs_header_level(b); + goto out; + } + + /* We try very hard to do read locks on the root */ + root_lock = BTRFS_READ_LOCK; + + /* + * If the level is set to maximum, we can skip trying to get the read + * lock. + */ + if (write_lock_level < BTRFS_MAX_LEVEL) { + /* + * We don't know the level of the root node until we actually + * have it read locked + */ + if (p->nowait) { + b = btrfs_try_read_lock_root_node(root); + if (IS_ERR(b)) + return b; + } else { + b = btrfs_read_lock_root_node(root); + } + level = btrfs_header_level(b); + if (level > write_lock_level) + goto out; + + /* Whoops, must trade for write lock */ + btrfs_tree_read_unlock(b); + free_extent_buffer(b); + } + + b = btrfs_lock_root_node(root); + root_lock = BTRFS_WRITE_LOCK; + + /* The level might have changed, check again */ + level = btrfs_header_level(b); + out: - if (path != found_path) - btrfs_free_path(path); + /* + * The root may have failed to write out at some point, and thus is no + * longer valid, return an error in this case. + */ + if (!extent_buffer_uptodate(b)) { + if (root_lock) + btrfs_tree_unlock_rw(b, root_lock); + free_extent_buffer(b); + return ERR_PTR(-EIO); + } + + p->nodes[level] = b; + if (!p->skip_locking) + p->locks[level] = root_lock; + /* + * Callers are responsible for dropping b's references. + */ + return b; +} + +/* + * Replace the extent buffer at the lowest level of the path with a cloned + * version. The purpose is to be able to use it safely, after releasing the + * commit root semaphore, even if relocation is happening in parallel, the + * transaction used for relocation is committed and the extent buffer is + * reallocated in the next transaction. + * + * This is used in a context where the caller does not prevent transaction + * commits from happening, either by holding a transaction handle or holding + * some lock, while it's doing searches through a commit root. + * At the moment it's only used for send operations. + */ +static int finish_need_commit_sem_search(struct btrfs_path *path) +{ + const int i = path->lowest_level; + const int slot = path->slots[i]; + struct extent_buffer *lowest = path->nodes[i]; + struct extent_buffer *clone; + + ASSERT(path->need_commit_sem); + + if (!lowest) + return 0; + + lockdep_assert_held_read(&lowest->fs_info->commit_root_sem); + + clone = btrfs_clone_extent_buffer(lowest); + if (!clone) + return -ENOMEM; + + btrfs_release_path(path); + path->nodes[i] = clone; + path->slots[i] = slot; + + return 0; +} + +static inline int search_for_key_slot(struct extent_buffer *eb, + int search_low_slot, + const struct btrfs_key *key, + int prev_cmp, + int *slot) +{ + /* + * If a previous call to btrfs_bin_search() on a parent node returned an + * exact match (prev_cmp == 0), we can safely assume the target key will + * always be at slot 0 on lower levels, since each key pointer + * (struct btrfs_key_ptr) refers to the lowest key accessible from the + * subtree it points to. Thus we can skip searching lower levels. + */ + if (prev_cmp == 0) { + *slot = 0; + return 0; + } + + return btrfs_bin_search(eb, search_low_slot, key, slot); +} + +static int search_leaf(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + const struct btrfs_key *key, + struct btrfs_path *path, + int ins_len, + int prev_cmp) +{ + struct extent_buffer *leaf = path->nodes[0]; + int leaf_free_space = -1; + int search_low_slot = 0; + int ret; + bool do_bin_search = true; + + /* + * If we are doing an insertion, the leaf has enough free space and the + * destination slot for the key is not slot 0, then we can unlock our + * write lock on the parent, and any other upper nodes, before doing the + * binary search on the leaf (with search_for_key_slot()), allowing other + * tasks to lock the parent and any other upper nodes. + */ + if (ins_len > 0) { + /* + * Cache the leaf free space, since we will need it later and it + * will not change until then. + */ + leaf_free_space = btrfs_leaf_free_space(leaf); + + /* + * !path->locks[1] means we have a single node tree, the leaf is + * the root of the tree. + */ + if (path->locks[1] && leaf_free_space >= ins_len) { + struct btrfs_disk_key first_key; + + ASSERT(btrfs_header_nritems(leaf) > 0); + btrfs_item_key(leaf, &first_key, 0); + + /* + * Doing the extra comparison with the first key is cheap, + * taking into account that the first key is very likely + * already in a cache line because it immediately follows + * the extent buffer's header and we have recently accessed + * the header's level field. + */ + ret = comp_keys(&first_key, key); + if (ret < 0) { + /* + * The first key is smaller than the key we want + * to insert, so we are safe to unlock all upper + * nodes and we have to do the binary search. + * + * We do use btrfs_unlock_up_safe() and not + * unlock_up() because the later does not unlock + * nodes with a slot of 0 - we can safely unlock + * any node even if its slot is 0 since in this + * case the key does not end up at slot 0 of the + * leaf and there's no need to split the leaf. + */ + btrfs_unlock_up_safe(path, 1); + search_low_slot = 1; + } else { + /* + * The first key is >= then the key we want to + * insert, so we can skip the binary search as + * the target key will be at slot 0. + * + * We can not unlock upper nodes when the key is + * less than the first key, because we will need + * to update the key at slot 0 of the parent node + * and possibly of other upper nodes too. + * If the key matches the first key, then we can + * unlock all the upper nodes, using + * btrfs_unlock_up_safe() instead of unlock_up() + * as stated above. + */ + if (ret == 0) + btrfs_unlock_up_safe(path, 1); + /* + * ret is already 0 or 1, matching the result of + * a btrfs_bin_search() call, so there is no need + * to adjust it. + */ + do_bin_search = false; + path->slots[0] = 0; + } + } + } + + if (do_bin_search) { + ret = search_for_key_slot(leaf, search_low_slot, key, + prev_cmp, &path->slots[0]); + if (ret < 0) + return ret; + } + + if (ins_len > 0) { + /* + * Item key already exists. In this case, if we are allowed to + * insert the item (for example, in dir_item case, item key + * collision is allowed), it will be merged with the original + * item. Only the item size grows, no new btrfs item will be + * added. If search_for_extension is not set, ins_len already + * accounts the size btrfs_item, deduct it here so leaf space + * check will be correct. + */ + if (ret == 0 && !path->search_for_extension) { + ASSERT(ins_len >= sizeof(struct btrfs_item)); + ins_len -= sizeof(struct btrfs_item); + } + + ASSERT(leaf_free_space >= 0); + + if (leaf_free_space < ins_len) { + int err; + + err = split_leaf(trans, root, key, path, ins_len, + (ret == 0)); + ASSERT(err <= 0); + if (WARN_ON(err > 0)) + err = -EUCLEAN; + if (err) + ret = err; + } + } + return ret; } /* - * look for key in the tree. path is filled in with nodes along the way - * if key is found, we return zero and you can find the item in the leaf - * level of the path (level 0) + * btrfs_search_slot - look for a key in a tree and perform necessary + * modifications to preserve tree invariants. * - * If the key isn't found, the path points to the slot where it should - * be inserted, and 1 is returned. If there are other errors during the - * search a negative error number is returned. + * @trans: Handle of transaction, used when modifying the tree + * @p: Holds all btree nodes along the search path + * @root: The root node of the tree + * @key: The key we are looking for + * @ins_len: Indicates purpose of search: + * >0 for inserts it's size of item inserted (*) + * <0 for deletions + * 0 for plain searches, not modifying the tree * - * if ins_len > 0, nodes and leaves will be split as we walk down the - * tree. if ins_len < 0, nodes will be merged as we walk down the tree (if - * possible) + * (*) If size of item inserted doesn't include + * sizeof(struct btrfs_item), then p->search_for_extension must + * be set. + * @cow: boolean should CoW operations be performed. Must always be 1 + * when modifying the tree. + * + * If @ins_len > 0, nodes and leaves will be split as we walk down the tree. + * If @ins_len < 0, nodes will be merged as we walk down the tree (if possible) + * + * If @key is found, 0 is returned and you can find the item in the leaf level + * of the path (level 0) + * + * If @key isn't found, 1 is returned and the leaf level of the path (level 0) + * points to the slot where it should be inserted + * + * If an error is encountered while searching the tree a negative error number + * is returned */ -int btrfs_search_slot(struct btrfs_trans_handle *trans, - struct btrfs_root *root, const struct btrfs_key *key, - struct btrfs_path *p, int ins_len, int cow) +int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, + const struct btrfs_key *key, struct btrfs_path *p, + int ins_len, int cow) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *b; int slot; int ret; + int err; int level; - int should_reada = p->reada; - struct btrfs_fs_info *fs_info = root->fs_info; + int lowest_unlock = 1; + /* everything at write_lock_level or lower must be write locked */ + int write_lock_level = 0; u8 lowest_level = 0; + int min_write_lock_level; + int prev_cmp; + + might_sleep(); lowest_level = p->lowest_level; WARN_ON(lowest_level && ins_len > 0); WARN_ON(p->nodes[0] != NULL); -again: - b = root->node; - extent_buffer_get(b); - while (b) { - level = btrfs_header_level(b); - if (cow) { - int wret; - wret = btrfs_cow_block(trans, root, b, - p->nodes[level + 1], - p->slots[level + 1], - &b); - if (wret) { - free_extent_buffer(b); - return wret; - } - } - BUG_ON(!cow && ins_len); - if (level != btrfs_header_level(b)) - WARN_ON(1); - level = btrfs_header_level(b); - p->nodes[level] = b; - ret = check_block(fs_info, p, level); - if (ret) - return -1; - ret = btrfs_bin_search(b, 0, key, &slot); - if (level != 0) { - if (ret && slot > 0) - slot -= 1; - p->slots[level] = slot; - if ((p->search_for_split || ins_len > 0) && - btrfs_header_nritems(b) >= - BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 3) { - int sret = split_node(trans, root, p, level); - BUG_ON(sret > 0); - if (sret) - return sret; - b = p->nodes[level]; - slot = p->slots[level]; - } else if (ins_len < 0) { - int sret = balance_level(trans, root, p, - level); - if (sret) - return sret; - b = p->nodes[level]; - if (!b) { - btrfs_release_path(p); - goto again; - } - slot = p->slots[level]; - BUG_ON(btrfs_header_nritems(b) == 1); - } - /* this is only true while dropping a snapshot */ - if (level == lowest_level) - break; + BUG_ON(!cow && ins_len); - if (should_reada) - reada_for_search(fs_info, p, level, slot, - key->objectid); + /* + * For now only allow nowait for read only operations. There's no + * strict reason why we can't, we just only need it for reads so it's + * only implemented for reads. + */ + ASSERT(!p->nowait || !cow); - b = btrfs_read_node_slot(b, slot); - if (!extent_buffer_uptodate(b)) - return -EIO; + if (ins_len < 0) { + lowest_unlock = 2; + + /* when we are removing items, we might have to go up to level + * two as we update tree pointers Make sure we keep write + * for those levels as well + */ + write_lock_level = 2; + } else if (ins_len > 0) { + /* + * for inserting items, make sure we have a write lock on + * level 1 so we can update keys + */ + write_lock_level = 1; + } + + if (!cow) + write_lock_level = -1; + + if (cow && (p->keep_locks || p->lowest_level)) + write_lock_level = BTRFS_MAX_LEVEL; + + min_write_lock_level = write_lock_level; + + if (p->need_commit_sem) { + ASSERT(p->search_commit_root); + if (p->nowait) { + if (!down_read_trylock(&fs_info->commit_root_sem)) + return -EAGAIN; } else { - p->slots[level] = slot; - if (ins_len > 0 && - ins_len > btrfs_leaf_free_space(b)) { - int sret = split_leaf(trans, root, key, - p, ins_len, ret == 0); - BUG_ON(sret > 0); - if (sret) - return sret; - } - return ret; + down_read(&fs_info->commit_root_sem); } } - return 1; + +again: + prev_cmp = -1; + b = btrfs_search_slot_get_root(root, p, write_lock_level); + if (IS_ERR(b)) { + ret = PTR_ERR(b); + goto done; + } + + while (b) { + int dec = 0; + + level = btrfs_header_level(b); + + if (cow) { + bool last_level = (level == (BTRFS_MAX_LEVEL - 1)); + + /* + * if we don't really need to cow this block + * then we don't want to set the path blocking, + * so we test it here + */ + if (!should_cow_block(trans, root, b)) + goto cow_done; + + /* + * must have write locks on this node and the + * parent + */ + if (level > write_lock_level || + (level + 1 > write_lock_level && + level + 1 < BTRFS_MAX_LEVEL && + p->nodes[level + 1])) { + write_lock_level = level + 1; + btrfs_release_path(p); + goto again; + } + + if (last_level) + err = btrfs_cow_block(trans, root, b, NULL, 0, + &b, + BTRFS_NESTING_COW); + else + err = btrfs_cow_block(trans, root, b, + p->nodes[level + 1], + p->slots[level + 1], &b, + BTRFS_NESTING_COW); + if (err) { + ret = err; + goto done; + } + } +cow_done: + p->nodes[level] = b; + + /* + * we have a lock on b and as long as we aren't changing + * the tree, there is no way to for the items in b to change. + * It is safe to drop the lock on our parent before we + * go through the expensive btree search on b. + * + * If we're inserting or deleting (ins_len != 0), then we might + * be changing slot zero, which may require changing the parent. + * So, we can't drop the lock until after we know which slot + * we're operating on. + */ + if (!ins_len && !p->keep_locks) { + int u = level + 1; + + if (u < BTRFS_MAX_LEVEL && p->locks[u]) { + btrfs_tree_unlock_rw(p->nodes[u], p->locks[u]); + p->locks[u] = 0; + } + } + + if (level == 0) { + if (ins_len > 0) + ASSERT(write_lock_level >= 1); + + ret = search_leaf(trans, root, key, p, ins_len, prev_cmp); + if (!p->search_for_split) + unlock_up(p, level, lowest_unlock, + min_write_lock_level, NULL); + goto done; + } + + ret = search_for_key_slot(b, 0, key, prev_cmp, &slot); + if (ret < 0) + goto done; + prev_cmp = ret; + + if (ret && slot > 0) { + dec = 1; + slot--; + } + p->slots[level] = slot; + err = setup_nodes_for_search(trans, root, p, b, level, ins_len, + &write_lock_level); + if (err == -EAGAIN) + goto again; + if (err) { + ret = err; + goto done; + } + b = p->nodes[level]; + slot = p->slots[level]; + + /* + * Slot 0 is special, if we change the key we have to update + * the parent pointer which means we must have a write lock on + * the parent + */ + if (slot == 0 && ins_len && write_lock_level < level + 1) { + write_lock_level = level + 1; + btrfs_release_path(p); + goto again; + } + + unlock_up(p, level, lowest_unlock, min_write_lock_level, + &write_lock_level); + + if (level == lowest_level) { + if (dec) + p->slots[level]++; + goto done; + } + + err = read_block_for_search(root, p, &b, level, slot, key); + if (err == -EAGAIN) + goto again; + if (err) { + ret = err; + goto done; + } + + if (!p->skip_locking) { + level = btrfs_header_level(b); + + btrfs_maybe_reset_lockdep_class(root, b); + + if (level <= write_lock_level) { + btrfs_tree_lock(b); + p->locks[level] = BTRFS_WRITE_LOCK; + } else { + if (p->nowait) { + if (!btrfs_try_tree_read_lock(b)) { + free_extent_buffer(b); + ret = -EAGAIN; + goto done; + } + } else { + btrfs_tree_read_lock(b); + } + p->locks[level] = BTRFS_READ_LOCK; + } + p->nodes[level] = b; + } + } + ret = 1; +done: + if (ret < 0 && !p->skip_release_on_error) + btrfs_release_path(p); + + if (p->need_commit_sem) { + int ret2; + + ret2 = finish_need_commit_sem_search(p); + up_read(&fs_info->commit_root_sem); + if (ret2) + ret = ret2; + } + + return ret; +} +ALLOW_ERROR_INJECTION(btrfs_search_slot, ERRNO); + +/* + * Like btrfs_search_slot, this looks for a key in the given tree. It uses the + * current state of the tree together with the operations recorded in the tree + * modification log to search for the key in a previous version of this tree, as + * denoted by the time_seq parameter. + * + * Naturally, there is no support for insert, delete or cow operations. + * + * The resulting path and return value will be set up as if we called + * btrfs_search_slot at that point in time with ins_len and cow both set to 0. + */ +int btrfs_search_old_slot(struct btrfs_root *root, const struct btrfs_key *key, + struct btrfs_path *p, u64 time_seq) +{ + struct btrfs_fs_info *fs_info = root->fs_info; + struct extent_buffer *b; + int slot; + int ret; + int err; + int level; + int lowest_unlock = 1; + u8 lowest_level = 0; + + lowest_level = p->lowest_level; + WARN_ON(p->nodes[0] != NULL); + ASSERT(!p->nowait); + + if (p->search_commit_root) { + BUG_ON(time_seq); + return btrfs_search_slot(NULL, root, key, p, 0, 0); + } + +again: + b = btrfs_get_old_root(root, time_seq); + if (!b) { + ret = -EIO; + goto done; + } + level = btrfs_header_level(b); + p->locks[level] = BTRFS_READ_LOCK; + + while (b) { + int dec = 0; + + level = btrfs_header_level(b); + p->nodes[level] = b; + + /* + * we have a lock on b and as long as we aren't changing + * the tree, there is no way to for the items in b to change. + * It is safe to drop the lock on our parent before we + * go through the expensive btree search on b. + */ + btrfs_unlock_up_safe(p, level + 1); + + ret = btrfs_bin_search(b, 0, key, &slot); + if (ret < 0) + goto done; + + if (level == 0) { + p->slots[level] = slot; + unlock_up(p, level, lowest_unlock, 0, NULL); + goto done; + } + + if (ret && slot > 0) { + dec = 1; + slot--; + } + p->slots[level] = slot; + unlock_up(p, level, lowest_unlock, 0, NULL); + + if (level == lowest_level) { + if (dec) + p->slots[level]++; + goto done; + } + + err = read_block_for_search(root, p, &b, level, slot, key); + if (err == -EAGAIN) + goto again; + if (err) { + ret = err; + goto done; + } + + level = btrfs_header_level(b); + btrfs_tree_read_lock(b); + b = btrfs_tree_mod_log_rewind(fs_info, p, b, time_seq); + if (!b) { + ret = -ENOMEM; + goto done; + } + p->locks[level] = BTRFS_READ_LOCK; + p->nodes[level] = b; + } + ret = 1; +done: + if (ret < 0) + btrfs_release_path(p); + + return ret; } /* - * Helper to use instead of search slot if no exact match is needed but + * helper to use instead of search slot if no exact match is needed but * instead the next or previous item should be returned. * When find_higher is true, the next higher item is returned, the next lower * otherwise. @@ -1124,65 +2397,126 @@ again: * < 0 on error */ int btrfs_search_slot_for_read(struct btrfs_root *root, - const struct btrfs_key *key, - struct btrfs_path *p, int find_higher, - int return_any) + const struct btrfs_key *key, + struct btrfs_path *p, int find_higher, + int return_any) { - int ret; - struct extent_buffer *leaf; + int ret; + struct extent_buffer *leaf; again: - ret = btrfs_search_slot(NULL, root, key, p, 0, 0); - if (ret <= 0) - return ret; - /* - * A return value of 1 means the path is at the position where the item - * should be inserted. Normally this is the next bigger item, but in - * case the previous item is the last in a leaf, path points to the - * first free slot in the previous leaf, i.e. at an invalid item. - */ - leaf = p->nodes[0]; + ret = btrfs_search_slot(NULL, root, key, p, 0, 0); + if (ret <= 0) + return ret; + /* + * a return value of 1 means the path is at the position where the + * item should be inserted. Normally this is the next bigger item, + * but in case the previous item is the last in a leaf, path points + * to the first free slot in the previous leaf, i.e. at an invalid + * item. + */ + leaf = p->nodes[0]; - if (find_higher) { - if (p->slots[0] >= btrfs_header_nritems(leaf)) { - ret = btrfs_next_leaf(root, p); - if (ret <= 0) - return ret; - if (!return_any) - return 1; - /* - * No higher item found, return the next lower instead - */ - return_any = 0; - find_higher = 0; - btrfs_release_path(p); - goto again; - } - } else { - if (p->slots[0] == 0) { - ret = btrfs_prev_leaf(root, p); - if (ret < 0) - return ret; - if (!ret) { - leaf = p->nodes[0]; - if (p->slots[0] == btrfs_header_nritems(leaf)) - p->slots[0]--; - return 0; - } - if (!return_any) - return 1; - /* - * No lower item found, return the next higher instead - */ - return_any = 0; - find_higher = 1; - btrfs_release_path(p); - goto again; - } else { - --p->slots[0]; - } - } - return 0; + if (find_higher) { + if (p->slots[0] >= btrfs_header_nritems(leaf)) { + ret = btrfs_next_leaf(root, p); + if (ret <= 0) + return ret; + if (!return_any) + return 1; + /* + * no higher item found, return the next + * lower instead + */ + return_any = 0; + find_higher = 0; + btrfs_release_path(p); + goto again; + } + } else { + if (p->slots[0] == 0) { + ret = btrfs_prev_leaf(root, p); + if (ret < 0) + return ret; + if (!ret) { + leaf = p->nodes[0]; + if (p->slots[0] == btrfs_header_nritems(leaf)) + p->slots[0]--; + return 0; + } + if (!return_any) + return 1; + /* + * no lower item found, return the next + * higher instead + */ + return_any = 0; + find_higher = 1; + btrfs_release_path(p); + goto again; + } else { + --p->slots[0]; + } + } + return 0; +} + +/* + * Execute search and call btrfs_previous_item to traverse backwards if the item + * was not found. + * + * Return 0 if found, 1 if not found and < 0 if error. + */ +int btrfs_search_backwards(struct btrfs_root *root, struct btrfs_key *key, + struct btrfs_path *path) +{ + int ret; + + ret = btrfs_search_slot(NULL, root, key, path, 0, 0); + if (ret > 0) + ret = btrfs_previous_item(root, path, key->objectid, key->type); + + if (ret == 0) + btrfs_item_key_to_cpu(path->nodes[0], key, path->slots[0]); + + return ret; +} + +/* + * Search for a valid slot for the given path. + * + * @root: The root node of the tree. + * @key: Will contain a valid item if found. + * @path: The starting point to validate the slot. + * + * Return: 0 if the item is valid + * 1 if not found + * <0 if error. + */ +int btrfs_get_next_valid_item(struct btrfs_root *root, struct btrfs_key *key, + struct btrfs_path *path) +{ + while (1) { + int ret; + const int slot = path->slots[0]; + const struct extent_buffer *leaf = path->nodes[0]; + + /* This is where we start walking the path. */ + if (slot >= btrfs_header_nritems(leaf)) { + /* + * If we've reached the last slot in this leaf we need + * to go to the next leaf and reset the path. + */ + ret = btrfs_next_leaf(root, path); + if (ret) + return ret; + continue; + } + /* Store the found, valid item in @key. */ + btrfs_item_key_to_cpu(leaf, key, slot); + break; + } + return 0; } /* @@ -1191,18 +2525,24 @@ again: * This is used after shifting pointers to the left, so it stops * fixing up pointers when a given leaf/node is not in slot 0 of the * higher levels + * */ -static void fixup_low_keys(struct btrfs_path *path, struct btrfs_disk_key *key, - int level) +static void fixup_low_keys(struct btrfs_path *path, + struct btrfs_disk_key *key, int level) { int i; struct extent_buffer *t; + int ret; for (i = level; i < BTRFS_MAX_LEVEL; i++) { int tslot = path->slots[i]; + if (!path->nodes[i]) break; t = path->nodes[i]; + ret = btrfs_tree_mod_log_insert_key(t, tslot, + BTRFS_MOD_LOG_KEY_REPLACE); + BUG_ON(ret < 0); btrfs_set_node_key(t, key, tslot); btrfs_mark_buffer_dirty(path->nodes[i]); if (tslot != 0) @@ -1228,11 +2568,31 @@ void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, slot = path->slots[0]; if (slot > 0) { btrfs_item_key(eb, &disk_key, slot - 1); - BUG_ON(btrfs_comp_keys(&disk_key, new_key) >= 0); + if (unlikely(comp_keys(&disk_key, new_key) >= 0)) { + btrfs_crit(fs_info, + "slot %u key (%llu %u %llu) new key (%llu %u %llu)", + slot, btrfs_disk_key_objectid(&disk_key), + btrfs_disk_key_type(&disk_key), + btrfs_disk_key_offset(&disk_key), + new_key->objectid, new_key->type, + new_key->offset); + btrfs_print_leaf(eb); + BUG(); + } } if (slot < btrfs_header_nritems(eb) - 1) { btrfs_item_key(eb, &disk_key, slot + 1); - BUG_ON(btrfs_comp_keys(&disk_key, new_key) <= 0); + if (unlikely(comp_keys(&disk_key, new_key) <= 0)) { + btrfs_crit(fs_info, + "slot %u key (%llu %u %llu) new key (%llu %u %llu)", + slot, btrfs_disk_key_objectid(&disk_key), + btrfs_disk_key_type(&disk_key), + btrfs_disk_key_offset(&disk_key), + new_key->objectid, new_key->type, + new_key->offset); + btrfs_print_leaf(eb); + BUG(); + } } btrfs_cpu_key_to_disk(&disk_key, new_key); @@ -1242,6 +2602,58 @@ void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, fixup_low_keys(path, &disk_key, 1); } +/* + * Check key order of two sibling extent buffers. + * + * Return true if something is wrong. + * Return false if everything is fine. + * + * Tree-checker only works inside one tree block, thus the following + * corruption can not be detected by tree-checker: + * + * Leaf @left | Leaf @right + * -------------------------------------------------------------- + * | 1 | 2 | 3 | 4 | 5 | f6 | | 7 | 8 | + * + * Key f6 in leaf @left itself is valid, but not valid when the next + * key in leaf @right is 7. + * This can only be checked at tree block merge time. + * And since tree checker has ensured all key order in each tree block + * is correct, we only need to bother the last key of @left and the first + * key of @right. + */ +static bool check_sibling_keys(struct extent_buffer *left, + struct extent_buffer *right) +{ + struct btrfs_key left_last; + struct btrfs_key right_first; + int level = btrfs_header_level(left); + int nr_left = btrfs_header_nritems(left); + int nr_right = btrfs_header_nritems(right); + + /* No key to check in one of the tree blocks */ + if (!nr_left || !nr_right) + return false; + + if (level) { + btrfs_node_key_to_cpu(left, &left_last, nr_left - 1); + btrfs_node_key_to_cpu(right, &right_first, 0); + } else { + btrfs_item_key_to_cpu(left, &left_last, nr_left - 1); + btrfs_item_key_to_cpu(right, &right_first, 0); + } + + if (btrfs_comp_cpu_keys(&left_last, &right_first) >= 0) { + btrfs_crit(left->fs_info, +"bad key order, sibling blocks, left last (%llu %u %llu) right first (%llu %u %llu)", + left_last.objectid, left_last.type, + left_last.offset, right_first.objectid, + right_first.type, right_first.offset); + return true; + } + return false; +} + /* * try to push data from one node into the next node left in the * tree. @@ -1250,9 +2662,10 @@ void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, * error, and > 0 if there was no room in the left hand block. */ static int push_node_left(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct extent_buffer *dst, + struct extent_buffer *dst, struct extent_buffer *src, int empty) { + struct btrfs_fs_info *fs_info = trans->fs_info; int push_items = 0; int src_nritems; int dst_nritems; @@ -1260,16 +2673,15 @@ static int push_node_left(struct btrfs_trans_handle *trans, src_nritems = btrfs_header_nritems(src); dst_nritems = btrfs_header_nritems(dst); - push_items = BTRFS_NODEPTRS_PER_BLOCK(root->fs_info) - dst_nritems; + push_items = BTRFS_NODEPTRS_PER_BLOCK(fs_info) - dst_nritems; WARN_ON(btrfs_header_generation(src) != trans->transid); WARN_ON(btrfs_header_generation(dst) != trans->transid); if (!empty && src_nritems <= 8) return 1; - if (push_items <= 0) { + if (push_items <= 0) return 1; - } if (empty) { push_items = min(src_nritems, push_items); @@ -1286,12 +2698,27 @@ static int push_node_left(struct btrfs_trans_handle *trans, } else push_items = min(src_nritems - 8, push_items); + /* dst is the left eb, src is the middle eb */ + if (check_sibling_keys(dst, src)) { + ret = -EUCLEAN; + btrfs_abort_transaction(trans, ret); + return ret; + } + ret = btrfs_tree_mod_log_eb_copy(dst, src, dst_nritems, 0, push_items); + if (ret) { + btrfs_abort_transaction(trans, ret); + return ret; + } copy_extent_buffer(dst, src, btrfs_node_key_ptr_offset(dst, dst_nritems), btrfs_node_key_ptr_offset(src, 0), - push_items * sizeof(struct btrfs_key_ptr)); + push_items * sizeof(struct btrfs_key_ptr)); if (push_items < src_nritems) { + /* + * Don't call btrfs_tree_mod_log_insert_move() here, key removal + * was already fully logged by btrfs_tree_mod_log_eb_copy() above. + */ memmove_extent_buffer(src, btrfs_node_key_ptr_offset(src, 0), btrfs_node_key_ptr_offset(src, push_items), (src_nritems - push_items) * @@ -1315,10 +2742,10 @@ static int push_node_left(struct btrfs_trans_handle *trans, * this will only push up to 1/2 the contents of the left node over */ static int balance_node_right(struct btrfs_trans_handle *trans, - struct btrfs_root *root, struct extent_buffer *dst, struct extent_buffer *src) { + struct btrfs_fs_info *fs_info = trans->fs_info; int push_items = 0; int max_push; int src_nritems; @@ -1330,33 +2757,44 @@ static int balance_node_right(struct btrfs_trans_handle *trans, src_nritems = btrfs_header_nritems(src); dst_nritems = btrfs_header_nritems(dst); - push_items = BTRFS_NODEPTRS_PER_BLOCK(root->fs_info) - dst_nritems; - if (push_items <= 0) { + push_items = BTRFS_NODEPTRS_PER_BLOCK(fs_info) - dst_nritems; + if (push_items <= 0) return 1; - } - if (src_nritems < 4) { + if (src_nritems < 4) return 1; - } max_push = src_nritems / 2 + 1; /* don't try to empty the node */ - if (max_push >= src_nritems) { + if (max_push >= src_nritems) return 1; - } if (max_push < push_items) push_items = max_push; + /* dst is the right eb, src is the middle eb */ + if (check_sibling_keys(src, dst)) { + ret = -EUCLEAN; + btrfs_abort_transaction(trans, ret); + return ret; + } + ret = btrfs_tree_mod_log_insert_move(dst, push_items, 0, dst_nritems); + BUG_ON(ret < 0); memmove_extent_buffer(dst, btrfs_node_key_ptr_offset(dst, push_items), btrfs_node_key_ptr_offset(dst, 0), (dst_nritems) * sizeof(struct btrfs_key_ptr)); + ret = btrfs_tree_mod_log_eb_copy(dst, src, 0, src_nritems - push_items, + push_items); + if (ret) { + btrfs_abort_transaction(trans, ret); + return ret; + } copy_extent_buffer(dst, src, btrfs_node_key_ptr_offset(dst, 0), btrfs_node_key_ptr_offset(src, src_nritems - push_items), - push_items * sizeof(struct btrfs_key_ptr)); + push_items * sizeof(struct btrfs_key_ptr)); btrfs_set_header_nritems(src, src_nritems - push_items); btrfs_set_header_nritems(dst, dst_nritems + push_items); @@ -1374,15 +2812,17 @@ static int balance_node_right(struct btrfs_trans_handle *trans, * * returns zero on success or < 0 on failure. */ -static int noinline insert_new_root(struct btrfs_trans_handle *trans, +static noinline int insert_new_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; u64 lower_gen; struct extent_buffer *lower; struct extent_buffer *c; struct extent_buffer *old; struct btrfs_disk_key lower_key; + int ret; BUG_ON(path->nodes[level]); BUG_ON(path->nodes[level-1] != root->node); @@ -1395,28 +2835,13 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, c = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, &lower_key, level, root->node->start, 0, - BTRFS_NESTING_NORMAL); - + BTRFS_NESTING_NEW_ROOT); if (IS_ERR(c)) return PTR_ERR(c); - memset_extent_buffer(c, 0, 0, sizeof(struct btrfs_header)); + root_add_used(root, fs_info->nodesize); + btrfs_set_header_nritems(c, 1); - btrfs_set_header_level(c, level); - btrfs_set_header_bytenr(c, c->start); - btrfs_set_header_generation(c, trans->transid); - btrfs_set_header_backref_rev(c, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(c, root->root_key.objectid); - - root_add_used(root, root->fs_info->nodesize); - - write_extent_buffer(c, root->fs_info->fs_devices->metadata_uuid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); - - write_extent_buffer(c, root->fs_info->chunk_tree_uuid, - btrfs_header_chunk_tree_uuid(c), - BTRFS_UUID_SIZE); - btrfs_set_node_key(c, &lower_key, 0); btrfs_set_node_blockptr(c, 0, lower->start); lower_gen = btrfs_header_generation(lower); @@ -1427,14 +2852,17 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(c); old = root->node; - root->node = c; + ret = btrfs_tree_mod_log_insert_root(root->node, c, false); + BUG_ON(ret < 0); + rcu_assign_pointer(root->node, c); /* the super has an extra ref to root->node */ free_extent_buffer(old); add_root_to_dirty_list(root); - extent_buffer_get(c); + atomic_inc(&c->refs); path->nodes[level] = c; + path->locks[level] = BTRFS_WRITE_LOCK; path->slots[level] = 0; return 0; } @@ -1445,37 +2873,44 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, * * slot and level indicate where you want the key to go, and * blocknr is the block the key points to. - * - * returns zero on success and < 0 on any error */ -static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root - *root, struct btrfs_path *path, struct btrfs_disk_key - *key, u64 bytenr, int slot, int level) +static void insert_ptr(struct btrfs_trans_handle *trans, + struct btrfs_path *path, + struct btrfs_disk_key *key, u64 bytenr, + int slot, int level) { struct extent_buffer *lower; int nritems; + int ret; BUG_ON(!path->nodes[level]); + btrfs_assert_tree_write_locked(path->nodes[level]); lower = path->nodes[level]; nritems = btrfs_header_nritems(lower); - if (slot > nritems) - BUG(); - if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root->fs_info)) - BUG(); - if (slot < nritems) { - /* shift the items */ + BUG_ON(slot > nritems); + BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(trans->fs_info)); + if (slot != nritems) { + if (level) { + ret = btrfs_tree_mod_log_insert_move(lower, slot + 1, + slot, nritems - slot); + BUG_ON(ret < 0); + } memmove_extent_buffer(lower, btrfs_node_key_ptr_offset(lower, slot + 1), btrfs_node_key_ptr_offset(lower, slot), (nritems - slot) * sizeof(struct btrfs_key_ptr)); } + if (level) { + ret = btrfs_tree_mod_log_insert_key(lower, slot, + BTRFS_MOD_LOG_KEY_ADD); + BUG_ON(ret < 0); + } btrfs_set_node_key(lower, key, slot); btrfs_set_node_blockptr(lower, slot, bytenr); WARN_ON(trans->transid == 0); btrfs_set_node_ptr_generation(lower, slot, trans->transid); btrfs_set_header_nritems(lower, nritems + 1); btrfs_mark_buffer_dirty(lower); - return 0; } /* @@ -1487,21 +2922,31 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root * * returns 0 on success and < 0 on failure */ -static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root - *root, struct btrfs_path *path, int level) +static noinline int split_node(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, int level) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *c; struct extent_buffer *split; struct btrfs_disk_key disk_key; int mid; int ret; - int wret; u32 c_nritems; c = path->nodes[level]; WARN_ON(btrfs_header_generation(c) != trans->transid); if (c == root->node) { - /* trying to split the root, lets make a new one */ + /* + * trying to split the root, lets make a new one + * + * tree mod log: We don't log_removal old root in + * insert_new_root, because that root buffer will be kept as a + * normal node. We are going to log removal of half of the + * elements below with btrfs_tree_mod_log_eb_copy(). We're + * holding a tree lock on the buffer, which is why we cannot + * race with other tree_mod_log users. + */ ret = insert_new_root(trans, root, path, level + 1); if (ret) return ret; @@ -1509,7 +2954,7 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root ret = push_nodes_for_insert(trans, root, path, level); c = path->nodes[level]; if (!ret && btrfs_header_nritems(c) < - BTRFS_NODEPTRS_PER_BLOCK(root->fs_info) - 3) + BTRFS_NODEPTRS_PER_BLOCK(fs_info) - 3) return 0; if (ret < 0) return ret; @@ -1521,50 +2966,42 @@ static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root split = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, &disk_key, level, c->start, 0, - BTRFS_NESTING_NORMAL); + BTRFS_NESTING_SPLIT); if (IS_ERR(split)) return PTR_ERR(split); - memset_extent_buffer(split, 0, 0, sizeof(struct btrfs_header)); - btrfs_set_header_level(split, btrfs_header_level(c)); - btrfs_set_header_bytenr(split, split->start); - btrfs_set_header_generation(split, trans->transid); - btrfs_set_header_backref_rev(split, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(split, root->root_key.objectid); - write_extent_buffer(split, root->fs_info->fs_devices->metadata_uuid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); - write_extent_buffer(split, root->fs_info->chunk_tree_uuid, - btrfs_header_chunk_tree_uuid(split), - BTRFS_UUID_SIZE); - - root_add_used(root, root->fs_info->nodesize); + root_add_used(root, fs_info->nodesize); + ASSERT(btrfs_header_level(c) == level); + ret = btrfs_tree_mod_log_eb_copy(split, c, 0, mid, c_nritems - mid); + if (ret) { + btrfs_abort_transaction(trans, ret); + return ret; + } copy_extent_buffer(split, c, btrfs_node_key_ptr_offset(split, 0), btrfs_node_key_ptr_offset(c, mid), (c_nritems - mid) * sizeof(struct btrfs_key_ptr)); btrfs_set_header_nritems(split, c_nritems - mid); btrfs_set_header_nritems(c, mid); - ret = 0; btrfs_mark_buffer_dirty(c); btrfs_mark_buffer_dirty(split); - wret = insert_ptr(trans, root, path, &disk_key, split->start, - path->slots[level + 1] + 1, - level + 1); - if (wret) - ret = wret; + insert_ptr(trans, path, &disk_key, split->start, + path->slots[level + 1] + 1, level + 1); if (path->slots[level] >= mid) { path->slots[level] -= mid; + btrfs_tree_unlock(c); free_extent_buffer(c); path->nodes[level] = split; path->slots[level + 1] += 1; } else { + btrfs_tree_unlock(split); free_extent_buffer(split); } - return ret; + return 0; } /* @@ -1580,7 +3017,7 @@ static int leaf_space_used(struct extent_buffer *l, int start, int nr) if (!nr) return 0; - data_len = btrfs_item_data_end(l, start); + data_len = btrfs_item_offset(l, start) + btrfs_item_size(l, start); data_len = data_len - btrfs_item_offset(l, end); data_len += sizeof(struct btrfs_item) * nr; WARN_ON(data_len < 0); @@ -1592,103 +3029,78 @@ static int leaf_space_used(struct extent_buffer *l, int start, int nr) * the start of the leaf data. IOW, how much room * the leaf has left for both items and data */ -int btrfs_leaf_free_space(struct extent_buffer *leaf) +noinline int btrfs_leaf_free_space(struct extent_buffer *leaf) { + struct btrfs_fs_info *fs_info = leaf->fs_info; int nritems = btrfs_header_nritems(leaf); - u32 leaf_data_size; int ret; - BUG_ON(!leaf->fs_info); - BUG_ON(leaf->fs_info->nodesize != leaf->len); - leaf_data_size = BTRFS_LEAF_DATA_SIZE(leaf->fs_info); - ret = leaf_data_size - leaf_space_used(leaf, 0 ,nritems); + ret = BTRFS_LEAF_DATA_SIZE(fs_info) - leaf_space_used(leaf, 0, nritems); if (ret < 0) { - printk("leaf free space ret %d, leaf data size %u, used %d nritems %d\n", - ret, leaf_data_size, leaf_space_used(leaf, 0, nritems), - nritems); + btrfs_crit(fs_info, + "leaf free space ret %d, leaf data size %lu, used %d nritems %d", + ret, + (unsigned long) BTRFS_LEAF_DATA_SIZE(fs_info), + leaf_space_used(leaf, 0, nritems), nritems); } return ret; } /* - * push some data in the path leaf to the right, trying to free up at - * least data_size bytes. returns zero if the push worked, nonzero otherwise - * - * returns 1 if the push failed because the other node didn't have enough - * room, 0 if everything worked out and < 0 if there were major errors. + * min slot controls the lowest index we're willing to push to the + * right. We'll push up to and including min_slot, but no lower */ -static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root - *root, struct btrfs_path *path, int data_size, - int empty) +static noinline int __push_leaf_right(struct btrfs_trans_handle *trans, + struct btrfs_path *path, + int data_size, int empty, + struct extent_buffer *right, + int free_space, u32 left_nritems, + u32 min_slot) { + struct btrfs_fs_info *fs_info = right->fs_info; struct extent_buffer *left = path->nodes[0]; - struct extent_buffer *right; - struct extent_buffer *upper; + struct extent_buffer *upper = path->nodes[1]; + struct btrfs_map_token token; struct btrfs_disk_key disk_key; int slot; u32 i; - int free_space; int push_space = 0; int push_items = 0; - u32 left_nritems; u32 nr; u32 right_nritems; u32 data_end; u32 this_item_size; - int ret; - - slot = path->slots[1]; - if (!path->nodes[1]) { - return 1; - } - upper = path->nodes[1]; - if (slot >= btrfs_header_nritems(upper) - 1) - return 1; - - right = btrfs_read_node_slot(upper, slot + 1); - if (!extent_buffer_uptodate(right)) { - if (IS_ERR(right)) - return PTR_ERR(right); - return -EIO; - } - free_space = btrfs_leaf_free_space(right); - if (free_space < data_size) { - free_extent_buffer(right); - return 1; - } - - /* cow and double check */ - ret = btrfs_cow_block(trans, root, right, upper, - slot + 1, &right); - if (ret) { - free_extent_buffer(right); - return 1; - } - free_space = btrfs_leaf_free_space(right); - if (free_space < data_size) { - free_extent_buffer(right); - return 1; - } - - left_nritems = btrfs_header_nritems(left); - if (left_nritems == 0) { - free_extent_buffer(right); - return 1; - } if (empty) nr = 0; else - nr = 1; + nr = max_t(u32, 1, min_slot); + if (path->slots[0] >= left_nritems) + push_space += data_size; + + slot = path->slots[1]; i = left_nritems - 1; while (i >= nr) { + if (!empty && push_items > 0) { + if (path->slots[0] > i) + break; + if (path->slots[0] == i) { + int space = btrfs_leaf_free_space(left); + + if (space + push_space * 2 > free_space) + break; + } + } + if (path->slots[0] == i) - push_space += data_size + sizeof(struct btrfs_item); + push_space += data_size; this_item_size = btrfs_item_size(left, i); - if (this_item_size + sizeof(struct btrfs_item) + push_space > free_space) + if (this_item_size + sizeof(struct btrfs_item) + + push_space > free_space) break; + push_items++; push_space += this_item_size + sizeof(struct btrfs_item); if (i == 0) @@ -1696,13 +3108,10 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root i--; } - if (push_items == 0) { - free_extent_buffer(right); - return 1; - } + if (push_items == 0) + goto out_unlock; - if (!empty && push_items == left_nritems) - WARN_ON(1); + WARN_ON(!empty && push_items == left_nritems); /* push left to right */ right_nritems = btrfs_header_nritems(right); @@ -1712,32 +3121,26 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root /* make room in the right data area */ data_end = leaf_data_end(right); - memmove_extent_buffer(right, - btrfs_item_nr_offset(right, 0) + data_end - push_space, - btrfs_item_nr_offset(right, 0) + data_end, - BTRFS_LEAF_DATA_SIZE(root->fs_info) - data_end); + memmove_leaf_data(right, data_end - push_space, data_end, + BTRFS_LEAF_DATA_SIZE(fs_info) - data_end); /* copy from the left data area */ - copy_extent_buffer(right, left, btrfs_item_nr_offset(right, 0) + - BTRFS_LEAF_DATA_SIZE(root->fs_info) - push_space, - btrfs_item_nr_offset(left, 0) + leaf_data_end(left), push_space); + copy_leaf_data(right, left, BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, + leaf_data_end(left), push_space); - memmove_extent_buffer(right, btrfs_item_nr_offset(right, push_items), - btrfs_item_nr_offset(right, 0), - right_nritems * sizeof(struct btrfs_item)); + memmove_leaf_items(right, push_items, 0, right_nritems); /* copy the items from left to right */ - copy_extent_buffer(right, left, btrfs_item_nr_offset(right, 0), - btrfs_item_nr_offset(left, left_nritems - push_items), - push_items * sizeof(struct btrfs_item)); + copy_leaf_items(right, left, 0, left_nritems - push_items, push_items); /* update the item pointers */ + btrfs_init_map_token(&token, right); right_nritems += push_items; btrfs_set_header_nritems(right, right_nritems); - push_space = BTRFS_LEAF_DATA_SIZE(root->fs_info); + push_space = BTRFS_LEAF_DATA_SIZE(fs_info); for (i = 0; i < right_nritems; i++) { - push_space -= btrfs_item_size(right, i); - btrfs_set_item_offset(right, i, push_space); + push_space -= btrfs_token_item_size(&token, i); + btrfs_set_token_item_offset(&token, i, push_space); } left_nritems -= push_items; @@ -1745,6 +3148,9 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root if (left_nritems) btrfs_mark_buffer_dirty(left); + else + btrfs_clear_buffer_dirty(trans, left); + btrfs_mark_buffer_dirty(right); btrfs_item_key(right, &disk_key, 0); @@ -1754,36 +3160,259 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root /* then fixup the leaf pointer in the path */ if (path->slots[0] >= left_nritems) { path->slots[0] -= left_nritems; + if (btrfs_header_nritems(path->nodes[0]) == 0) + btrfs_clear_buffer_dirty(trans, path->nodes[0]); + btrfs_tree_unlock(path->nodes[0]); free_extent_buffer(path->nodes[0]); path->nodes[0] = right; path->slots[1] += 1; } else { + btrfs_tree_unlock(right); free_extent_buffer(right); } return 0; + +out_unlock: + btrfs_tree_unlock(right); + free_extent_buffer(right); + return 1; } + +/* + * push some data in the path leaf to the right, trying to free up at + * least data_size bytes. returns zero if the push worked, nonzero otherwise + * + * returns 1 if the push failed because the other node didn't have enough + * room, 0 if everything worked out and < 0 if there were major errors. + * + * this will push starting from min_slot to the end of the leaf. It won't + * push any slot lower than min_slot + */ +static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root + *root, struct btrfs_path *path, + int min_data_size, int data_size, + int empty, u32 min_slot) +{ + struct extent_buffer *left = path->nodes[0]; + struct extent_buffer *right; + struct extent_buffer *upper; + int slot; + int free_space; + u32 left_nritems; + int ret; + + if (!path->nodes[1]) + return 1; + + slot = path->slots[1]; + upper = path->nodes[1]; + if (slot >= btrfs_header_nritems(upper) - 1) + return 1; + + btrfs_assert_tree_write_locked(path->nodes[1]); + + right = btrfs_read_node_slot(upper, slot + 1); + if (IS_ERR(right)) + return PTR_ERR(right); + + __btrfs_tree_lock(right, BTRFS_NESTING_RIGHT); + + free_space = btrfs_leaf_free_space(right); + if (free_space < data_size) + goto out_unlock; + + ret = btrfs_cow_block(trans, root, right, upper, + slot + 1, &right, BTRFS_NESTING_RIGHT_COW); + if (ret) + goto out_unlock; + + left_nritems = btrfs_header_nritems(left); + if (left_nritems == 0) + goto out_unlock; + + if (check_sibling_keys(left, right)) { + ret = -EUCLEAN; + btrfs_tree_unlock(right); + free_extent_buffer(right); + return ret; + } + if (path->slots[0] == left_nritems && !empty) { + /* Key greater than all keys in the leaf, right neighbor has + * enough room for it and we're not emptying our leaf to delete + * it, therefore use right neighbor to insert the new item and + * no need to touch/dirty our left leaf. */ + btrfs_tree_unlock(left); + free_extent_buffer(left); + path->nodes[0] = right; + path->slots[0] = 0; + path->slots[1]++; + return 0; + } + + return __push_leaf_right(trans, path, min_data_size, empty, right, + free_space, left_nritems, min_slot); +out_unlock: + btrfs_tree_unlock(right); + free_extent_buffer(right); + return 1; +} + /* * push some data in the path leaf to the left, trying to free up at * least data_size bytes. returns zero if the push worked, nonzero otherwise + * + * max_slot can put a limit on how far into the leaf we'll push items. The + * item at 'max_slot' won't be touched. Use (u32)-1 to make us do all the + * items */ -static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root - *root, struct btrfs_path *path, int data_size, - int empty) +static noinline int __push_leaf_left(struct btrfs_trans_handle *trans, + struct btrfs_path *path, int data_size, + int empty, struct extent_buffer *left, + int free_space, u32 right_nritems, + u32 max_slot) { + struct btrfs_fs_info *fs_info = left->fs_info; struct btrfs_disk_key disk_key; struct extent_buffer *right = path->nodes[0]; - struct extent_buffer *left; - int slot; int i; - int free_space; int push_space = 0; int push_items = 0; u32 old_left_nritems; - u32 right_nritems; u32 nr; int ret = 0; u32 this_item_size; u32 old_left_item_size; + struct btrfs_map_token token; + + if (empty) + nr = min(right_nritems, max_slot); + else + nr = min(right_nritems - 1, max_slot); + + for (i = 0; i < nr; i++) { + if (!empty && push_items > 0) { + if (path->slots[0] < i) + break; + if (path->slots[0] == i) { + int space = btrfs_leaf_free_space(right); + + if (space + push_space * 2 > free_space) + break; + } + } + + if (path->slots[0] == i) + push_space += data_size; + + this_item_size = btrfs_item_size(right, i); + if (this_item_size + sizeof(struct btrfs_item) + push_space > + free_space) + break; + + push_items++; + push_space += this_item_size + sizeof(struct btrfs_item); + } + + if (push_items == 0) { + ret = 1; + goto out; + } + WARN_ON(!empty && push_items == btrfs_header_nritems(right)); + + /* push data from right to left */ + copy_leaf_items(left, right, btrfs_header_nritems(left), 0, push_items); + + push_space = BTRFS_LEAF_DATA_SIZE(fs_info) - + btrfs_item_offset(right, push_items - 1); + + copy_leaf_data(left, right, leaf_data_end(left) - push_space, + btrfs_item_offset(right, push_items - 1), push_space); + old_left_nritems = btrfs_header_nritems(left); + BUG_ON(old_left_nritems <= 0); + + btrfs_init_map_token(&token, left); + old_left_item_size = btrfs_item_offset(left, old_left_nritems - 1); + for (i = old_left_nritems; i < old_left_nritems + push_items; i++) { + u32 ioff; + + ioff = btrfs_token_item_offset(&token, i); + btrfs_set_token_item_offset(&token, i, + ioff - (BTRFS_LEAF_DATA_SIZE(fs_info) - old_left_item_size)); + } + btrfs_set_header_nritems(left, old_left_nritems + push_items); + + /* fixup right node */ + if (push_items > right_nritems) + WARN(1, KERN_CRIT "push items %d nr %u\n", push_items, + right_nritems); + + if (push_items < right_nritems) { + push_space = btrfs_item_offset(right, push_items - 1) - + leaf_data_end(right); + memmove_leaf_data(right, + BTRFS_LEAF_DATA_SIZE(fs_info) - push_space, + leaf_data_end(right), push_space); + + memmove_leaf_items(right, 0, push_items, + btrfs_header_nritems(right) - push_items); + } + + btrfs_init_map_token(&token, right); + right_nritems -= push_items; + btrfs_set_header_nritems(right, right_nritems); + push_space = BTRFS_LEAF_DATA_SIZE(fs_info); + for (i = 0; i < right_nritems; i++) { + push_space = push_space - btrfs_token_item_size(&token, i); + btrfs_set_token_item_offset(&token, i, push_space); + } + + btrfs_mark_buffer_dirty(left); + if (right_nritems) + btrfs_mark_buffer_dirty(right); + else + btrfs_clear_buffer_dirty(trans, right); + + btrfs_item_key(right, &disk_key, 0); + fixup_low_keys(path, &disk_key, 1); + + /* then fixup the leaf pointer in the path */ + if (path->slots[0] < push_items) { + path->slots[0] += old_left_nritems; + btrfs_tree_unlock(path->nodes[0]); + free_extent_buffer(path->nodes[0]); + path->nodes[0] = left; + path->slots[1] -= 1; + } else { + btrfs_tree_unlock(left); + free_extent_buffer(left); + path->slots[0] -= push_items; + } + BUG_ON(path->slots[0] < 0); + return ret; +out: + btrfs_tree_unlock(left); + free_extent_buffer(left); + return ret; +} + +/* + * push some data in the path leaf to the left, trying to free up at + * least data_size bytes. returns zero if the push worked, nonzero otherwise + * + * max_slot can put a limit on how far into the leaf we'll push items. The + * item at 'max_slot' won't be touched. Use (u32)-1 to make us push all the + * items + */ +static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root + *root, struct btrfs_path *path, int min_data_size, + int data_size, int empty, u32 max_slot) +{ + struct extent_buffer *right = path->nodes[0]; + struct extent_buffer *left; + int slot; + int free_space; + u32 right_nritems; + int ret = 0; slot = path->slots[1]; if (slot == 0) @@ -1792,198 +3421,165 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root return 1; right_nritems = btrfs_header_nritems(right); - if (right_nritems == 0) { + if (right_nritems == 0) return 1; - } + + btrfs_assert_tree_write_locked(path->nodes[1]); left = btrfs_read_node_slot(path->nodes[1], slot - 1); + if (IS_ERR(left)) + return PTR_ERR(left); + + __btrfs_tree_lock(left, BTRFS_NESTING_LEFT); + free_space = btrfs_leaf_free_space(left); if (free_space < data_size) { - free_extent_buffer(left); - return 1; + ret = 1; + goto out; } - /* cow and double check */ ret = btrfs_cow_block(trans, root, left, - path->nodes[1], slot - 1, &left); + path->nodes[1], slot - 1, &left, + BTRFS_NESTING_LEFT_COW); if (ret) { /* we hit -ENOSPC, but it isn't fatal here */ - free_extent_buffer(left); - return 1; + if (ret == -ENOSPC) + ret = 1; + goto out; } - free_space = btrfs_leaf_free_space(left); - if (free_space < data_size) { - free_extent_buffer(left); - return 1; + if (check_sibling_keys(left, right)) { + ret = -EUCLEAN; + goto out; } - - if (empty) - nr = right_nritems; - else - nr = right_nritems - 1; - - for (i = 0; i < nr; i++) { - if (path->slots[0] == i) - push_space += data_size + sizeof(struct btrfs_item); - - this_item_size = btrfs_item_size(right, i); - if (this_item_size + sizeof(struct btrfs_item) + push_space > free_space) - break; - - push_items++; - push_space += this_item_size + sizeof(struct btrfs_item); - } - - if (push_items == 0) { - free_extent_buffer(left); - return 1; - } - if (!empty && push_items == btrfs_header_nritems(right)) - WARN_ON(1); - - /* push data from right to left */ - copy_extent_buffer(left, right, - btrfs_item_nr_offset(left, btrfs_header_nritems(left)), - btrfs_item_nr_offset(right, 0), - push_items * sizeof(struct btrfs_item)); - - push_space = BTRFS_LEAF_DATA_SIZE(root->fs_info) - - btrfs_item_offset(right, push_items -1); - - copy_extent_buffer(left, right, btrfs_item_nr_offset(left, 0) + - leaf_data_end(left) - push_space, - btrfs_item_nr_offset(right, 0) + - btrfs_item_offset(right, push_items - 1), - push_space); - old_left_nritems = btrfs_header_nritems(left); - BUG_ON(old_left_nritems == 0); - - old_left_item_size = btrfs_item_offset(left, old_left_nritems - 1); - for (i = old_left_nritems; i < old_left_nritems + push_items; i++) { - u32 ioff; - - ioff = btrfs_item_offset(left, i); - btrfs_set_item_offset(left, i, - ioff - (BTRFS_LEAF_DATA_SIZE(root->fs_info) - - old_left_item_size)); - } - btrfs_set_header_nritems(left, old_left_nritems + push_items); - - /* fixup right node */ - if (push_items > right_nritems) { - printk("push items %d nr %u\n", push_items, right_nritems); - WARN_ON(1); - } - - if (push_items < right_nritems) { - push_space = btrfs_item_offset(right, push_items - 1) - - leaf_data_end(right); - memmove_extent_buffer(right, btrfs_item_nr_offset(right, 0) + - BTRFS_LEAF_DATA_SIZE(root->fs_info) - - push_space, - btrfs_item_nr_offset(right, 0) + - leaf_data_end(right), push_space); - - memmove_extent_buffer(right, btrfs_item_nr_offset(right, 0), - btrfs_item_nr_offset(right, push_items), - (btrfs_header_nritems(right) - push_items) * - sizeof(struct btrfs_item)); - } - right_nritems -= push_items; - btrfs_set_header_nritems(right, right_nritems); - push_space = BTRFS_LEAF_DATA_SIZE(root->fs_info); - for (i = 0; i < right_nritems; i++) { - push_space = push_space - btrfs_item_size(right, i); - btrfs_set_item_offset(right, i, push_space); - } - - btrfs_mark_buffer_dirty(left); - if (right_nritems) - btrfs_mark_buffer_dirty(right); - - btrfs_item_key(right, &disk_key, 0); - fixup_low_keys(path, &disk_key, 1); - - /* then fixup the leaf pointer in the path */ - if (path->slots[0] < push_items) { - path->slots[0] += old_left_nritems; - free_extent_buffer(path->nodes[0]); - path->nodes[0] = left; - path->slots[1] -= 1; - } else { - free_extent_buffer(left); - path->slots[0] -= push_items; - } - BUG_ON(path->slots[0] < 0); + return __push_leaf_left(trans, path, min_data_size, empty, left, + free_space, right_nritems, max_slot); +out: + btrfs_tree_unlock(left); + free_extent_buffer(left); return ret; } /* * split the path's leaf in two, making sure there is at least data_size * available for the resulting leaf level of the path. - * - * returns 0 if all went well and < 0 on failure. */ -static noinline int copy_for_split(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct btrfs_path *path, - struct extent_buffer *l, - struct extent_buffer *right, - int slot, int mid, int nritems) +static noinline void copy_for_split(struct btrfs_trans_handle *trans, + struct btrfs_path *path, + struct extent_buffer *l, + struct extent_buffer *right, + int slot, int mid, int nritems) { + struct btrfs_fs_info *fs_info = trans->fs_info; int data_copy_size; int rt_data_off; int i; - int ret = 0; - int wret; struct btrfs_disk_key disk_key; + struct btrfs_map_token token; nritems = nritems - mid; btrfs_set_header_nritems(right, nritems); data_copy_size = btrfs_item_data_end(l, mid) - leaf_data_end(l); - copy_extent_buffer(right, l, btrfs_item_nr_offset(right, 0), - btrfs_item_nr_offset(l, mid), - nritems * sizeof(struct btrfs_item)); + copy_leaf_items(right, l, 0, mid, nritems); - copy_extent_buffer(right, l, - btrfs_item_nr_offset(right, 0) + - BTRFS_LEAF_DATA_SIZE(root->fs_info) - data_copy_size, - btrfs_item_nr_offset(l, 0) + leaf_data_end(l), data_copy_size); + copy_leaf_data(right, l, BTRFS_LEAF_DATA_SIZE(fs_info) - data_copy_size, + leaf_data_end(l), data_copy_size); - rt_data_off = BTRFS_LEAF_DATA_SIZE(root->fs_info) - - btrfs_item_data_end(l, mid); + rt_data_off = BTRFS_LEAF_DATA_SIZE(fs_info) - btrfs_item_data_end(l, mid); + btrfs_init_map_token(&token, right); for (i = 0; i < nritems; i++) { - u32 ioff = btrfs_item_offset(right, i); - btrfs_set_item_offset(right, i, ioff + rt_data_off); + u32 ioff; + + ioff = btrfs_token_item_offset(&token, i); + btrfs_set_token_item_offset(&token, i, ioff + rt_data_off); } btrfs_set_header_nritems(l, mid); - ret = 0; btrfs_item_key(right, &disk_key, 0); - wret = insert_ptr(trans, root, path, &disk_key, right->start, - path->slots[1] + 1, 1); - if (wret) - ret = wret; + insert_ptr(trans, path, &disk_key, right->start, path->slots[1] + 1, 1); btrfs_mark_buffer_dirty(right); btrfs_mark_buffer_dirty(l); BUG_ON(path->slots[0] != slot); if (mid <= slot) { + btrfs_tree_unlock(path->nodes[0]); free_extent_buffer(path->nodes[0]); path->nodes[0] = right; path->slots[0] -= mid; path->slots[1] += 1; } else { + btrfs_tree_unlock(right); free_extent_buffer(right); } BUG_ON(path->slots[0] < 0); +} - return ret; +/* + * double splits happen when we need to insert a big item in the middle + * of a leaf. A double split can leave us with 3 mostly empty leaves: + * leaf: [ slots 0 - N] [ our target ] [ N + 1 - total in leaf ] + * A B C + * + * We avoid this by trying to push the items on either side of our target + * into the adjacent leaves. If all goes well we can avoid the double split + * completely. + */ +static noinline int push_for_double_split(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + int data_size) +{ + int ret; + int progress = 0; + int slot; + u32 nritems; + int space_needed = data_size; + + slot = path->slots[0]; + if (slot < btrfs_header_nritems(path->nodes[0])) + space_needed -= btrfs_leaf_free_space(path->nodes[0]); + + /* + * try to push all the items after our slot into the + * right leaf + */ + ret = push_leaf_right(trans, root, path, 1, space_needed, 0, slot); + if (ret < 0) + return ret; + + if (ret == 0) + progress++; + + nritems = btrfs_header_nritems(path->nodes[0]); + /* + * our goal is to get our slot at the start or end of a leaf. If + * we've done so we're done + */ + if (path->slots[0] == 0 || path->slots[0] == nritems) + return 0; + + if (btrfs_leaf_free_space(path->nodes[0]) >= data_size) + return 0; + + /* try to push all the items before our slot into the next leaf */ + slot = path->slots[0]; + space_needed = data_size; + if (slot > 0) + space_needed -= btrfs_leaf_free_space(path->nodes[0]); + ret = push_leaf_left(trans, root, path, 1, space_needed, 0, slot); + if (ret < 0) + return ret; + + if (ret == 0) + progress++; + + if (progress) + return 0; + return 1; } /* @@ -2004,24 +3600,36 @@ static noinline int split_leaf(struct btrfs_trans_handle *trans, int mid; int slot; struct extent_buffer *right; + struct btrfs_fs_info *fs_info = root->fs_info; int ret = 0; int wret; int split; int num_doubles = 0; + int tried_avoid_double = 0; l = path->nodes[0]; slot = path->slots[0]; if (extend && data_size + btrfs_item_size(l, slot) + - sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(root->fs_info)) + sizeof(struct btrfs_item) > BTRFS_LEAF_DATA_SIZE(fs_info)) return -EOVERFLOW; /* first try to make some room by pushing left and right */ - if (data_size && ins_key->type != BTRFS_DIR_ITEM_KEY) { - wret = push_leaf_right(trans, root, path, data_size, 0); + if (data_size && path->nodes[1]) { + int space_needed = data_size; + + if (slot < btrfs_header_nritems(l)) + space_needed -= btrfs_leaf_free_space(l); + + wret = push_leaf_right(trans, root, path, space_needed, + space_needed, 0, 0); if (wret < 0) return wret; if (wret) { - wret = push_leaf_left(trans, root, path, data_size, 0); + space_needed = data_size; + if (slot > 0) + space_needed -= btrfs_leaf_free_space(l); + wret = push_leaf_left(trans, root, path, space_needed, + space_needed, 0, (u32)-1); if (wret < 0) return wret; } @@ -2047,22 +3655,23 @@ again: if (mid <= slot) { if (nritems == 1 || leaf_space_used(l, mid, nritems - mid) + data_size > - BTRFS_LEAF_DATA_SIZE(root->fs_info)) { + BTRFS_LEAF_DATA_SIZE(fs_info)) { if (slot >= nritems) { split = 0; } else { mid = slot; if (mid != nritems && leaf_space_used(l, mid, nritems - mid) + - data_size > - BTRFS_LEAF_DATA_SIZE(root->fs_info)) { + data_size > BTRFS_LEAF_DATA_SIZE(fs_info)) { + if (data_size && !tried_avoid_double) + goto push_for_double; split = 2; } } } } else { if (leaf_space_used(l, 0, mid) + data_size > - BTRFS_LEAF_DATA_SIZE(root->fs_info)) { + BTRFS_LEAF_DATA_SIZE(fs_info)) { if (!extend && data_size && slot == 0) { split = 0; } else if ((extend || !data_size) && slot == 0) { @@ -2071,9 +3680,10 @@ again: mid = slot; if (mid != nritems && leaf_space_used(l, mid, nritems - mid) + - data_size > - BTRFS_LEAF_DATA_SIZE(root->fs_info)) { - split = 2 ; + data_size > BTRFS_LEAF_DATA_SIZE(fs_info)) { + if (data_size && !tried_avoid_double) + goto push_for_double; + split = 2; } } } @@ -2084,62 +3694,53 @@ again: else btrfs_item_key(l, &disk_key, mid); + /* + * We have to about BTRFS_NESTING_NEW_ROOT here if we've done a double + * split, because we're only allowed to have MAX_LOCKDEP_SUBCLASSES + * subclasses, which is 8 at the time of this patch, and we've maxed it + * out. In the future we could add a + * BTRFS_NESTING_SPLIT_THE_SPLITTENING if we need to, but for now just + * use BTRFS_NESTING_NEW_ROOT. + */ right = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid, &disk_key, 0, l->start, 0, - BTRFS_NESTING_NORMAL); - if (IS_ERR(right)) { - BUG_ON(1); + num_doubles ? BTRFS_NESTING_NEW_ROOT : + BTRFS_NESTING_SPLIT); + if (IS_ERR(right)) return PTR_ERR(right); - } - memset_extent_buffer(right, 0, 0, sizeof(struct btrfs_header)); - btrfs_set_header_bytenr(right, right->start); - btrfs_set_header_generation(right, trans->transid); - btrfs_set_header_backref_rev(right, BTRFS_MIXED_BACKREF_REV); - btrfs_set_header_owner(right, root->root_key.objectid); - btrfs_set_header_level(right, 0); - write_extent_buffer(right, root->fs_info->fs_devices->metadata_uuid, - btrfs_header_fsid(), BTRFS_FSID_SIZE); - - write_extent_buffer(right, root->fs_info->chunk_tree_uuid, - btrfs_header_chunk_tree_uuid(right), - BTRFS_UUID_SIZE); - - root_add_used(root, root->fs_info->nodesize); + root_add_used(root, fs_info->nodesize); if (split == 0) { if (mid <= slot) { btrfs_set_header_nritems(right, 0); - wret = insert_ptr(trans, root, path, - &disk_key, right->start, - path->slots[1] + 1, 1); - if (wret) - ret = wret; - + insert_ptr(trans, path, &disk_key, + right->start, path->slots[1] + 1, 1); + btrfs_tree_unlock(path->nodes[0]); free_extent_buffer(path->nodes[0]); path->nodes[0] = right; path->slots[0] = 0; path->slots[1] += 1; } else { btrfs_set_header_nritems(right, 0); - wret = insert_ptr(trans, root, path, - &disk_key, - right->start, - path->slots[1], 1); - if (wret) - ret = wret; + insert_ptr(trans, path, &disk_key, + right->start, path->slots[1], 1); + btrfs_tree_unlock(path->nodes[0]); free_extent_buffer(path->nodes[0]); path->nodes[0] = right; path->slots[0] = 0; if (path->slots[1] == 0) fixup_low_keys(path, &disk_key, 1); } - btrfs_mark_buffer_dirty(right); + /* + * We create a new leaf 'right' for the required ins_len and + * we'll do btrfs_mark_buffer_dirty() on this leaf after copying + * the content of ins_len to 'right'. + */ return ret; } - ret = copy_for_split(trans, root, path, l, right, slot, mid, nritems); - BUG_ON(ret); + copy_for_split(trans, path, l, right, slot, mid, nritems); if (split == 2) { BUG_ON(num_doubles != 0); @@ -2147,9 +3748,143 @@ again: goto again; } + return 0; + +push_for_double: + push_for_double_split(trans, root, path, data_size); + tried_avoid_double = 1; + if (btrfs_leaf_free_space(path->nodes[0]) >= data_size) + return 0; + goto again; +} + +static noinline int setup_leaf_for_split(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, int ins_len) +{ + struct btrfs_key key; + struct extent_buffer *leaf; + struct btrfs_file_extent_item *fi; + u64 extent_len = 0; + u32 item_size; + int ret; + + leaf = path->nodes[0]; + btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); + + BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY && + key.type != BTRFS_EXTENT_CSUM_KEY); + + if (btrfs_leaf_free_space(leaf) >= ins_len) + return 0; + + item_size = btrfs_item_size(leaf, path->slots[0]); + if (key.type == BTRFS_EXTENT_DATA_KEY) { + fi = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_file_extent_item); + extent_len = btrfs_file_extent_num_bytes(leaf, fi); + } + btrfs_release_path(path); + + path->keep_locks = 1; + path->search_for_split = 1; + ret = btrfs_search_slot(trans, root, &key, path, 0, 1); + path->search_for_split = 0; + if (ret > 0) + ret = -EAGAIN; + if (ret < 0) + goto err; + + ret = -EAGAIN; + leaf = path->nodes[0]; + /* if our item isn't there, return now */ + if (item_size != btrfs_item_size(leaf, path->slots[0])) + goto err; + + /* the leaf has changed, it now has room. return now */ + if (btrfs_leaf_free_space(path->nodes[0]) >= ins_len) + goto err; + + if (key.type == BTRFS_EXTENT_DATA_KEY) { + fi = btrfs_item_ptr(leaf, path->slots[0], + struct btrfs_file_extent_item); + if (extent_len != btrfs_file_extent_num_bytes(leaf, fi)) + goto err; + } + + ret = split_leaf(trans, root, &key, path, ins_len, 1); + if (ret) + goto err; + + path->keep_locks = 0; + btrfs_unlock_up_safe(path, 1); + return 0; +err: + path->keep_locks = 0; return ret; } +static noinline int split_item(struct btrfs_path *path, + const struct btrfs_key *new_key, + unsigned long split_offset) +{ + struct extent_buffer *leaf; + int orig_slot, slot; + char *buf; + u32 nritems; + u32 item_size; + u32 orig_offset; + struct btrfs_disk_key disk_key; + + leaf = path->nodes[0]; + BUG_ON(btrfs_leaf_free_space(leaf) < sizeof(struct btrfs_item)); + + orig_slot = path->slots[0]; + orig_offset = btrfs_item_offset(leaf, path->slots[0]); + item_size = btrfs_item_size(leaf, path->slots[0]); + + buf = kmalloc(item_size, GFP_NOFS); + if (!buf) + return -ENOMEM; + + read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf, + path->slots[0]), item_size); + + slot = path->slots[0] + 1; + nritems = btrfs_header_nritems(leaf); + if (slot != nritems) { + /* shift the items */ + memmove_leaf_items(leaf, slot + 1, slot, nritems - slot); + } + + btrfs_cpu_key_to_disk(&disk_key, new_key); + btrfs_set_item_key(leaf, &disk_key, slot); + + btrfs_set_item_offset(leaf, slot, orig_offset); + btrfs_set_item_size(leaf, slot, item_size - split_offset); + + btrfs_set_item_offset(leaf, orig_slot, + orig_offset + item_size - split_offset); + btrfs_set_item_size(leaf, orig_slot, split_offset); + + btrfs_set_header_nritems(leaf, nritems + 1); + + /* write the data for the start of the original item */ + write_extent_buffer(leaf, buf, + btrfs_item_ptr_offset(leaf, path->slots[0]), + split_offset); + + /* write the data for the new item */ + write_extent_buffer(leaf, buf + split_offset, + btrfs_item_ptr_offset(leaf, slot), + item_size - split_offset); + btrfs_mark_buffer_dirty(leaf); + + BUG_ON(btrfs_leaf_free_space(leaf) < 0); + kfree(buf); + return 0; +} + /* * This function splits a single item into two items, * giving 'new_key' to the new item and splitting the @@ -2168,99 +3903,25 @@ again: int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, - struct btrfs_key *new_key, + const struct btrfs_key *new_key, unsigned long split_offset) { - u32 item_size; - struct extent_buffer *leaf; - struct btrfs_key orig_key; - int ret = 0; - int slot; - u32 nritems; - u32 orig_offset; - struct btrfs_disk_key disk_key; - char *buf; + int ret; + ret = setup_leaf_for_split(trans, root, path, + sizeof(struct btrfs_item)); + if (ret) + return ret; - leaf = path->nodes[0]; - btrfs_item_key_to_cpu(leaf, &orig_key, path->slots[0]); - if (btrfs_leaf_free_space(leaf) >= - sizeof(struct btrfs_item)) - goto split; - - item_size = btrfs_item_size(leaf, path->slots[0]); - btrfs_release_path(path); - - path->search_for_split = 1; - - ret = btrfs_search_slot(trans, root, &orig_key, path, 0, 1); - path->search_for_split = 0; - - /* if our item isn't there or got smaller, return now */ - if (ret != 0 || item_size != btrfs_item_size(path->nodes[0], - path->slots[0])) { - return -EAGAIN; - } - - ret = split_leaf(trans, root, &orig_key, path, 0, 0); - BUG_ON(ret); - - BUG_ON(btrfs_leaf_free_space(leaf) < sizeof(struct btrfs_item)); - leaf = path->nodes[0]; - -split: - orig_offset = btrfs_item_offset(leaf, path->slots[0]); - item_size = btrfs_item_size(leaf, path->slots[0]); - - - buf = kmalloc(item_size, GFP_NOFS); - BUG_ON(!buf); - read_extent_buffer(leaf, buf, btrfs_item_ptr_offset(leaf, - path->slots[0]), item_size); - slot = path->slots[0] + 1; - leaf = path->nodes[0]; - - nritems = btrfs_header_nritems(leaf); - - if (slot < nritems) { - /* shift the items */ - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, slot + 1), - btrfs_item_nr_offset(leaf, slot), - (nritems - slot) * sizeof(struct btrfs_item)); - - } - - btrfs_cpu_key_to_disk(&disk_key, new_key); - btrfs_set_item_key(leaf, &disk_key, slot); - - btrfs_set_item_offset(leaf, slot, orig_offset); - btrfs_set_item_size(leaf, slot, item_size - split_offset); - - btrfs_set_item_offset(leaf, path->slots[0], - orig_offset + item_size - split_offset); - btrfs_set_item_size(leaf, path->slots[0], split_offset); - - btrfs_set_header_nritems(leaf, nritems + 1); - - /* write the data for the start of the original item */ - write_extent_buffer(leaf, buf, - btrfs_item_ptr_offset(leaf, path->slots[0]), - split_offset); - - /* write the data for the new item */ - write_extent_buffer(leaf, buf + split_offset, - btrfs_item_ptr_offset(leaf, slot), - item_size - split_offset); - btrfs_mark_buffer_dirty(leaf); - - ret = 0; - if (btrfs_leaf_free_space(leaf) < 0) { - btrfs_print_leaf(leaf); - BUG(); - } - kfree(buf); + ret = split_item(path, new_key, split_offset); return ret; } +/* + * make the item pointed to by the path smaller. new_size indicates + * how small to make it, and from_end tells us if we just chop bytes + * off the end of the item or if we shift the item to chop bytes off + * the front. + */ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) { int slot; @@ -2271,6 +3932,7 @@ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) unsigned int old_size; unsigned int size_diff; int i; + struct btrfs_map_token token; leaf = path->nodes[0]; slot = path->slots[0]; @@ -2293,17 +3955,18 @@ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) * item0..itemN ... dataN.offset..dataN.size .. data0.size */ /* first correct the data pointers */ + btrfs_init_map_token(&token, leaf); for (i = slot; i < nritems; i++) { u32 ioff; - ioff = btrfs_item_offset(leaf, i); - btrfs_set_item_offset(leaf, i, ioff + size_diff); + + ioff = btrfs_token_item_offset(&token, i); + btrfs_set_token_item_offset(&token, i, ioff + size_diff); } /* shift the data */ if (from_end) { - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, 0) + - data_end + size_diff, btrfs_item_nr_offset(leaf, 0) + - data_end, old_data_start + new_size - data_end); + memmove_leaf_data(leaf, data_end + size_diff, data_end, + old_data_start + new_size - data_end); } else { struct btrfs_disk_key disk_key; u64 offset; @@ -2323,15 +3986,13 @@ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) BTRFS_FILE_EXTENT_INLINE) { ptr = btrfs_item_ptr_offset(leaf, slot); memmove_extent_buffer(leaf, ptr, - (unsigned long)fi, - offsetof(struct btrfs_file_extent_item, - disk_bytenr)); + (unsigned long)fi, + BTRFS_FILE_EXTENT_INLINE_DATA_START); } } - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, 0) + - data_end + size_diff, btrfs_item_nr_offset(leaf, 0) + - data_end, old_data_start - data_end); + memmove_leaf_data(leaf, data_end + size_diff, data_end, + old_data_start - data_end); offset = btrfs_disk_key_offset(&disk_key); btrfs_set_disk_key_offset(&disk_key, offset + size_diff); @@ -2349,6 +4010,9 @@ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end) } } +/* + * make the item pointed to by the path bigger, data_size is the added size. + */ void btrfs_extend_item(struct btrfs_path *path, u32 data_size) { int slot; @@ -2358,6 +4022,7 @@ void btrfs_extend_item(struct btrfs_path *path, u32 data_size) unsigned int old_data; unsigned int old_size; int i; + struct btrfs_map_token token; leaf = path->nodes[0]; @@ -2374,24 +4039,26 @@ void btrfs_extend_item(struct btrfs_path *path, u32 data_size) BUG_ON(slot < 0); if (slot >= nritems) { btrfs_print_leaf(leaf); - printk("slot %d too large, nritems %u\n", slot, nritems); - BUG_ON(1); + btrfs_crit(leaf->fs_info, "slot %d too large, nritems %d", + slot, nritems); + BUG(); } /* * item0..itemN ... dataN.offset..dataN.size .. data0.size */ /* first correct the data pointers */ + btrfs_init_map_token(&token, leaf); for (i = slot; i < nritems; i++) { u32 ioff; - ioff = btrfs_item_offset(leaf, i); - btrfs_set_item_offset(leaf, i, ioff - data_size); + + ioff = btrfs_token_item_offset(&token, i); + btrfs_set_token_item_offset(&token, i, ioff - data_size); } /* shift the data */ - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, 0) + - data_end - data_size, btrfs_item_nr_offset(leaf, 0) + - data_end, old_data - data_end); + memmove_leaf_data(leaf, data_end - data_size, data_end, + old_data - data_end); data_end = old_data; old_size = btrfs_item_size(leaf, slot); @@ -2405,64 +4072,63 @@ void btrfs_extend_item(struct btrfs_path *path, u32 data_size) } /* - * Given a key and some data, insert an item into the tree. - * This does all the path init required, making room in the tree if needed. + * Make space in the node before inserting one or more items. + * + * @root: root we are inserting items to + * @path: points to the leaf/slot where we are going to insert new items + * @batch: information about the batch of items to insert + * + * Main purpose is to save stack depth by doing the bulk of the work in a + * function that doesn't call btrfs_search_slot */ -int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct btrfs_path *path, - struct btrfs_key *cpu_key, u32 *data_size, - int nr) +static void setup_items_for_insert(struct btrfs_root *root, struct btrfs_path *path, + const struct btrfs_item_batch *batch) { - struct extent_buffer *leaf; - int ret = 0; - int slot; + struct btrfs_fs_info *fs_info = root->fs_info; int i; u32 nritems; - u32 total_size = 0; - u32 total_data = 0; unsigned int data_end; struct btrfs_disk_key disk_key; + struct extent_buffer *leaf; + int slot; + struct btrfs_map_token token; + u32 total_size; - for (i = 0; i < nr; i++) { - total_data += data_size[i]; + /* + * Before anything else, update keys in the parent and other ancestors + * if needed, then release the write locks on them, so that other tasks + * can use them while we modify the leaf. + */ + if (path->slots[0] == 0) { + btrfs_cpu_key_to_disk(&disk_key, &batch->keys[0]); + fixup_low_keys(path, &disk_key, 1); } - - /* create a root if there isn't one */ - if (!root->node) - BUG(); - - total_size = total_data + nr * sizeof(struct btrfs_item); - ret = btrfs_search_slot(trans, root, cpu_key, path, total_size, 1); - if (ret == 0) { - return -EEXIST; - } - if (ret < 0) - goto out; + btrfs_unlock_up_safe(path, 1); leaf = path->nodes[0]; + slot = path->slots[0]; nritems = btrfs_header_nritems(leaf); data_end = leaf_data_end(leaf); + total_size = batch->total_data_size + (batch->nr * sizeof(struct btrfs_item)); if (btrfs_leaf_free_space(leaf) < total_size) { btrfs_print_leaf(leaf); - printk("not enough freespace need %u have %d\n", - total_size, btrfs_leaf_free_space(leaf)); + btrfs_crit(fs_info, "not enough freespace need %u have %d", + total_size, btrfs_leaf_free_space(leaf)); BUG(); } - slot = path->slots[0]; - BUG_ON(slot < 0); - - if (slot < nritems) { + btrfs_init_map_token(&token, leaf); + if (slot != nritems) { unsigned int old_data = btrfs_item_data_end(leaf, slot); if (old_data < data_end) { btrfs_print_leaf(leaf); - printk("slot %d old_data %u data_end %u\n", - slot, old_data, data_end); - BUG_ON(1); + btrfs_crit(fs_info, + "item at slot %d with data offset %u beyond data end of leaf %u", + slot, old_data, data_end); + BUG(); } /* * item0..itemN ... dataN.offset..dataN.size .. data0.size @@ -2471,55 +4137,94 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, for (i = slot; i < nritems; i++) { u32 ioff; - ioff = btrfs_item_offset(leaf, i); - btrfs_set_item_offset(leaf, i, ioff - total_data); + ioff = btrfs_token_item_offset(&token, i); + btrfs_set_token_item_offset(&token, i, + ioff - batch->total_data_size); } - /* shift the items */ - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, slot + nr), - btrfs_item_nr_offset(leaf, slot), - (nritems - slot) * sizeof(struct btrfs_item)); + memmove_leaf_items(leaf, slot + batch->nr, slot, nritems - slot); /* shift the data */ - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, 0) + - data_end - total_data, btrfs_item_nr_offset(leaf, 0) + - data_end, old_data - data_end); + memmove_leaf_data(leaf, data_end - batch->total_data_size, + data_end, old_data - data_end); data_end = old_data; } /* setup the item for the new data */ - for (i = 0; i < nr; i++) { - btrfs_cpu_key_to_disk(&disk_key, cpu_key + i); + for (i = 0; i < batch->nr; i++) { + btrfs_cpu_key_to_disk(&disk_key, &batch->keys[i]); btrfs_set_item_key(leaf, &disk_key, slot + i); - btrfs_set_item_offset(leaf, slot + i, data_end - data_size[i]); - data_end -= data_size[i]; - btrfs_set_item_size(leaf, slot + i, data_size[i]); + data_end -= batch->data_sizes[i]; + btrfs_set_token_item_offset(&token, slot + i, data_end); + btrfs_set_token_item_size(&token, slot + i, batch->data_sizes[i]); } - btrfs_set_header_nritems(leaf, nritems + nr); - btrfs_mark_buffer_dirty(leaf); - ret = 0; - if (slot == 0) { - btrfs_cpu_key_to_disk(&disk_key, cpu_key); - fixup_low_keys(path, &disk_key, 1); - } + btrfs_set_header_nritems(leaf, nritems + batch->nr); + btrfs_mark_buffer_dirty(leaf); if (btrfs_leaf_free_space(leaf) < 0) { btrfs_print_leaf(leaf); BUG(); } +} -out: - return ret; +/* + * Insert a new item into a leaf. + * + * @root: The root of the btree. + * @path: A path pointing to the target leaf and slot. + * @key: The key of the new item. + * @data_size: The size of the data associated with the new key. + */ +void btrfs_setup_item_for_insert(struct btrfs_root *root, + struct btrfs_path *path, + const struct btrfs_key *key, + u32 data_size) +{ + struct btrfs_item_batch batch; + + batch.keys = key; + batch.data_sizes = &data_size; + batch.total_data_size = data_size; + batch.nr = 1; + + setup_items_for_insert(root, path, &batch); +} + +/* + * Given a key and some data, insert items into the tree. + * This does all the path init required, making room in the tree if needed. + */ +int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + const struct btrfs_item_batch *batch) +{ + int ret = 0; + int slot; + u32 total_size; + + total_size = batch->total_data_size + (batch->nr * sizeof(struct btrfs_item)); + ret = btrfs_search_slot(trans, root, &batch->keys[0], path, total_size, 1); + if (ret == 0) + return -EEXIST; + if (ret < 0) + return ret; + + slot = path->slots[0]; + BUG_ON(slot < 0); + + setup_items_for_insert(root, path, batch); + return 0; } /* * Given a key and some data, insert an item into the tree. * This does all the path init required, making room in the tree if needed. */ -int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root - *root, struct btrfs_key *cpu_key, void *data, u32 - data_size) +int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, + const struct btrfs_key *cpu_key, void *data, + u32 data_size) { int ret = 0; struct btrfs_path *path; @@ -2529,7 +4234,6 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root path = btrfs_alloc_path(); if (!path) return -ENOMEM; - ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); if (!ret) { leaf = path->nodes[0]; @@ -2541,28 +4245,73 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root return ret; } +/* + * This function duplicates an item, giving 'new_key' to the new item. + * It guarantees both items live in the same tree leaf and the new item is + * contiguous with the original item. + * + * This allows us to split a file extent in place, keeping a lock on the leaf + * the entire time. + */ +int btrfs_duplicate_item(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + const struct btrfs_key *new_key) +{ + struct extent_buffer *leaf; + int ret; + u32 item_size; + + leaf = path->nodes[0]; + item_size = btrfs_item_size(leaf, path->slots[0]); + ret = setup_leaf_for_split(trans, root, path, + item_size + sizeof(struct btrfs_item)); + if (ret) + return ret; + + path->slots[0]++; + btrfs_setup_item_for_insert(root, path, new_key, item_size); + leaf = path->nodes[0]; + memcpy_extent_buffer(leaf, + btrfs_item_ptr_offset(leaf, path->slots[0]), + btrfs_item_ptr_offset(leaf, path->slots[0] - 1), + item_size); + return 0; +} + /* * delete the pointer from a given node. * - * If the delete empties a node, the node is removed from the tree, - * continuing all the way the root if required. The root is converted into - * a leaf if all the nodes are emptied. + * the tree should have been previously balanced so the deletion does not + * empty a node. + * + * This is exported for use inside btrfs-progs, don't un-export it. */ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, - int level, int slot) + int level, int slot) { struct extent_buffer *parent = path->nodes[level]; u32 nritems; + int ret; nritems = btrfs_header_nritems(parent); - if (slot < nritems - 1) { - /* shift the items */ + if (slot != nritems - 1) { + if (level) { + ret = btrfs_tree_mod_log_insert_move(parent, slot, + slot + 1, nritems - slot - 1); + BUG_ON(ret < 0); + } memmove_extent_buffer(parent, btrfs_node_key_ptr_offset(parent, slot), btrfs_node_key_ptr_offset(parent, slot + 1), sizeof(struct btrfs_key_ptr) * (nritems - slot - 1)); + } else if (level) { + ret = btrfs_tree_mod_log_insert_key(parent, slot, + BTRFS_MOD_LOG_KEY_REMOVE); + BUG_ON(ret < 0); } + nritems--; btrfs_set_header_nritems(parent, nritems); if (nritems == 0 && parent == root->node) { @@ -2588,23 +4337,26 @@ void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, * The path must have already been setup for deleting the leaf, including * all the proper balancing. path->nodes[1] must be locked. */ -static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct btrfs_path *path, - struct extent_buffer *leaf) +static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct btrfs_path *path, + struct extent_buffer *leaf) { - int ret; - WARN_ON(btrfs_header_generation(leaf) != trans->transid); btrfs_del_ptr(root, path, 1, path->slots[1]); + /* + * btrfs_free_extent is expensive, we want to make sure we + * aren't holding any locks when we call it + */ + btrfs_unlock_up_safe(path, 0); + root_sub_used(root, leaf->len); - ret = btrfs_free_extent(trans, leaf->start, leaf->len, 0, - root->root_key.objectid, 0, 0); - return ret; + atomic_inc(&leaf->refs); + btrfs_free_tree_block(trans, btrfs_root_id(root), leaf, 0, 1); + free_extent_buffer_stale(leaf); } - /* * delete the item at the leaf level in path. If that empties * the leaf, remove it from the tree @@ -2612,41 +4364,37 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int slot, int nr) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_buffer *leaf; - int last_off; - int dsize = 0; int ret = 0; int wret; - int i; u32 nritems; leaf = path->nodes[0]; - last_off = btrfs_item_offset(leaf, slot + nr - 1); - - for (i = 0; i < nr; i++) - dsize += btrfs_item_size(leaf, slot + i); - nritems = btrfs_header_nritems(leaf); if (slot + nr != nritems) { - int data_end = leaf_data_end(leaf); + const u32 last_off = btrfs_item_offset(leaf, slot + nr - 1); + const int data_end = leaf_data_end(leaf); + struct btrfs_map_token token; + u32 dsize = 0; + int i; - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, 0) + - data_end + dsize, - btrfs_item_nr_offset(leaf, 0) + data_end, - last_off - data_end); + for (i = 0; i < nr; i++) + dsize += btrfs_item_size(leaf, slot + i); + memmove_leaf_data(leaf, data_end + dsize, data_end, + last_off - data_end); + + btrfs_init_map_token(&token, leaf); for (i = slot + nr; i < nritems; i++) { u32 ioff; - ioff = btrfs_item_offset(leaf, i); - btrfs_set_item_offset(leaf, i, ioff + dsize); + ioff = btrfs_token_item_offset(&token, i); + btrfs_set_token_item_offset(&token, i, ioff + dsize); } - memmove_extent_buffer(leaf, btrfs_item_nr_offset(leaf, slot), - btrfs_item_nr_offset(leaf, slot + nr), - sizeof(struct btrfs_item) * - (nritems - slot - nr)); + memmove_leaf_items(leaf, slot, slot + nr, nritems - slot - nr); } btrfs_set_header_nritems(leaf, nritems - nr); nritems -= nr; @@ -2657,10 +4405,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, btrfs_set_header_level(leaf, 0); } else { btrfs_clear_buffer_dirty(trans, leaf); - wret = btrfs_del_leaf(trans, root, path, leaf); - BUG_ON(ret); - if (wret) - ret = wret; + btrfs_del_leaf(trans, root, path, leaf); } } else { int used = leaf_space_used(leaf, 0, nritems); @@ -2671,35 +4416,67 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, fixup_low_keys(path, &disk_key, 1); } - /* delete the leaf if it is mostly empty */ - if (used < BTRFS_LEAF_DATA_SIZE(root->fs_info) / 4) { + /* + * Try to delete the leaf if it is mostly empty. We do this by + * trying to move all its items into its left and right neighbours. + * If we can't move all the items, then we don't delete it - it's + * not ideal, but future insertions might fill the leaf with more + * items, or items from other leaves might be moved later into our + * leaf due to deletions on those leaves. + */ + if (used < BTRFS_LEAF_DATA_SIZE(fs_info) / 3) { + u32 min_push_space; + /* push_leaf_left fixes the path. * make sure the path still points to our leaf - * for possible call to del_ptr below + * for possible call to btrfs_del_ptr below */ slot = path->slots[1]; - extent_buffer_get(leaf); - - wret = push_leaf_left(trans, root, path, 1, 1); + atomic_inc(&leaf->refs); + /* + * We want to be able to at least push one item to the + * left neighbour leaf, and that's the first item. + */ + min_push_space = sizeof(struct btrfs_item) + + btrfs_item_size(leaf, 0); + wret = push_leaf_left(trans, root, path, 0, + min_push_space, 1, (u32)-1); if (wret < 0 && wret != -ENOSPC) ret = wret; if (path->nodes[0] == leaf && btrfs_header_nritems(leaf)) { - wret = push_leaf_right(trans, root, path, 1, 1); + /* + * If we were not able to push all items from our + * leaf to its left neighbour, then attempt to + * either push all the remaining items to the + * right neighbour or none. There's no advantage + * in pushing only some items, instead of all, as + * it's pointless to end up with a leaf having + * too few items while the neighbours can be full + * or nearly full. + */ + nritems = btrfs_header_nritems(leaf); + min_push_space = leaf_space_used(leaf, 0, nritems); + wret = push_leaf_right(trans, root, path, 0, + min_push_space, 1, 0); if (wret < 0 && wret != -ENOSPC) ret = wret; } if (btrfs_header_nritems(leaf) == 0) { - btrfs_clear_buffer_dirty(trans, leaf); path->slots[1] = slot; - ret = btrfs_del_leaf(trans, root, path, leaf); - BUG_ON(ret); + btrfs_del_leaf(trans, root, path, leaf); free_extent_buffer(leaf); - + ret = 0; } else { - btrfs_mark_buffer_dirty(leaf); + /* if we're still in the path, make sure + * we're dirty. Otherwise, one of the + * push_leaf functions must have already + * dirtied this buffer + */ + if (path->nodes[0] == leaf) + btrfs_mark_buffer_dirty(leaf); free_extent_buffer(leaf); } } else { @@ -2710,124 +4487,469 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, } /* - * walk up the tree as far as required to find the previous leaf. + * search the tree again to find a leaf with lesser keys * returns 0 if it found something or 1 if there are no lesser leaves. * returns < 0 on io errors. + * + * This may release the path, and so you may lose any locks held at the + * time you call it. */ int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path) { - int slot; - int level = 1; - struct extent_buffer *c; - struct extent_buffer *next = NULL; + struct btrfs_key key; + struct btrfs_disk_key found_key; + int ret; - while(level < BTRFS_MAX_LEVEL) { - if (!path->nodes[level]) - return 1; + btrfs_item_key_to_cpu(path->nodes[0], &key, 0); - slot = path->slots[level]; - c = path->nodes[level]; - if (slot == 0) { - level++; - if (level == BTRFS_MAX_LEVEL) - return 1; - continue; - } - slot--; - - next = btrfs_read_node_slot(c, slot); - if (!extent_buffer_uptodate(next)) { - if (IS_ERR(next)) - return PTR_ERR(next); - return -EIO; - } - break; + if (key.offset > 0) { + key.offset--; + } else if (key.type > 0) { + key.type--; + key.offset = (u64)-1; + } else if (key.objectid > 0) { + key.objectid--; + key.type = (u8)-1; + key.offset = (u64)-1; + } else { + return 1; } - path->slots[level] = slot; - while(1) { - level--; - c = path->nodes[level]; - free_extent_buffer(c); - slot = btrfs_header_nritems(next); - if (slot != 0) - slot--; - path->nodes[level] = next; - path->slots[level] = slot; - if (!level) - break; - next = btrfs_read_node_slot(next, slot); - if (!extent_buffer_uptodate(next)) { - if (IS_ERR(next)) - return PTR_ERR(next); - return -EIO; - } - } - return 0; + + btrfs_release_path(path); + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) + return ret; + btrfs_item_key(path->nodes[0], &found_key, 0); + ret = comp_keys(&found_key, &key); + /* + * We might have had an item with the previous key in the tree right + * before we released our path. And after we released our path, that + * item might have been pushed to the first slot (0) of the leaf we + * were holding due to a tree balance. Alternatively, an item with the + * previous key can exist as the only element of a leaf (big fat item). + * Therefore account for these 2 cases, so that our callers (like + * btrfs_previous_item) don't miss an existing item with a key matching + * the previous key we computed above. + */ + if (ret <= 0) + return 0; + return 1; } /* - * Walk up the tree as far as necessary to find the next sibling tree block. - * More generic version of btrfs_next_leaf(), as it could find sibling nodes - * if @path->lowest_level is not 0. + * A helper function to walk down the tree starting at min_key, and looking + * for nodes or leaves that are have a minimum transaction id. + * This is used by the btree defrag code, and tree logging * - * returns 0 if it found something or 1 if there are no greater leaves. - * returns < 0 on io errors. + * This does not cow, but it does stuff the starting key it finds back + * into min_key, so you can call btrfs_search_slot with cow=1 on the + * key and get a writable path. + * + * This honors path->lowest_level to prevent descent past a given level + * of the tree. + * + * min_trans indicates the oldest transaction that you are interested + * in walking through. Any nodes or leaves older than min_trans are + * skipped over (without reading them). + * + * returns zero if something useful was found, < 0 on error and 1 if there + * was nothing in the tree that matched the search criteria. */ -int btrfs_next_sibling_tree_block(struct btrfs_fs_info *fs_info, - struct btrfs_path *path) +int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, + struct btrfs_path *path, + u64 min_trans) +{ + struct extent_buffer *cur; + struct btrfs_key found_key; + int slot; + int sret; + u32 nritems; + int level; + int ret = 1; + int keep_locks = path->keep_locks; + + ASSERT(!path->nowait); + path->keep_locks = 1; +again: + cur = btrfs_read_lock_root_node(root); + level = btrfs_header_level(cur); + WARN_ON(path->nodes[level]); + path->nodes[level] = cur; + path->locks[level] = BTRFS_READ_LOCK; + + if (btrfs_header_generation(cur) < min_trans) { + ret = 1; + goto out; + } + while (1) { + nritems = btrfs_header_nritems(cur); + level = btrfs_header_level(cur); + sret = btrfs_bin_search(cur, 0, min_key, &slot); + if (sret < 0) { + ret = sret; + goto out; + } + + /* at the lowest level, we're done, setup the path and exit */ + if (level == path->lowest_level) { + if (slot >= nritems) + goto find_next_key; + ret = 0; + path->slots[level] = slot; + btrfs_item_key_to_cpu(cur, &found_key, slot); + goto out; + } + if (sret && slot > 0) + slot--; + /* + * check this node pointer against the min_trans parameters. + * If it is too old, skip to the next one. + */ + while (slot < nritems) { + u64 gen; + + gen = btrfs_node_ptr_generation(cur, slot); + if (gen < min_trans) { + slot++; + continue; + } + break; + } +find_next_key: + /* + * we didn't find a candidate key in this node, walk forward + * and find another one + */ + if (slot >= nritems) { + path->slots[level] = slot; + sret = btrfs_find_next_key(root, path, min_key, level, + min_trans); + if (sret == 0) { + btrfs_release_path(path); + goto again; + } else { + goto out; + } + } + /* save our key for returning back */ + btrfs_node_key_to_cpu(cur, &found_key, slot); + path->slots[level] = slot; + if (level == path->lowest_level) { + ret = 0; + goto out; + } + cur = btrfs_read_node_slot(cur, slot); + if (IS_ERR(cur)) { + ret = PTR_ERR(cur); + goto out; + } + + btrfs_tree_read_lock(cur); + + path->locks[level - 1] = BTRFS_READ_LOCK; + path->nodes[level - 1] = cur; + unlock_up(path, level, 1, 0, NULL); + } +out: + path->keep_locks = keep_locks; + if (ret == 0) { + btrfs_unlock_up_safe(path, path->lowest_level + 1); + memcpy(min_key, &found_key, sizeof(found_key)); + } + return ret; +} + +/* + * this is similar to btrfs_next_leaf, but does not try to preserve + * and fixup the path. It looks for and returns the next key in the + * tree based on the current path and the min_trans parameters. + * + * 0 is returned if another key is found, < 0 if there are any errors + * and 1 is returned if there are no higher keys in the tree + * + * path->keep_locks should be set to 1 on the search made before + * calling this function. + */ +int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, + struct btrfs_key *key, int level, u64 min_trans) { int slot; - int level = path->lowest_level + 1; struct extent_buffer *c; - struct extent_buffer *next = NULL; - BUG_ON(path->lowest_level + 1 >= BTRFS_MAX_LEVEL); - do { + WARN_ON(!path->keep_locks && !path->skip_locking); + while (level < BTRFS_MAX_LEVEL) { if (!path->nodes[level]) return 1; + slot = path->slots[level] + 1; + c = path->nodes[level]; +next: + if (slot >= btrfs_header_nritems(c)) { + int ret; + int orig_lowest; + struct btrfs_key cur_key; + if (level + 1 >= BTRFS_MAX_LEVEL || + !path->nodes[level + 1]) + return 1; + + if (path->locks[level + 1] || path->skip_locking) { + level++; + continue; + } + + slot = btrfs_header_nritems(c) - 1; + if (level == 0) + btrfs_item_key_to_cpu(c, &cur_key, slot); + else + btrfs_node_key_to_cpu(c, &cur_key, slot); + + orig_lowest = path->lowest_level; + btrfs_release_path(path); + path->lowest_level = level; + ret = btrfs_search_slot(NULL, root, &cur_key, path, + 0, 0); + path->lowest_level = orig_lowest; + if (ret < 0) + return ret; + + c = path->nodes[level]; + slot = path->slots[level]; + if (ret == 0) + slot++; + goto next; + } + + if (level == 0) + btrfs_item_key_to_cpu(c, key, slot); + else { + u64 gen = btrfs_node_ptr_generation(c, slot); + + if (gen < min_trans) { + slot++; + goto next; + } + btrfs_node_key_to_cpu(c, key, slot); + } + return 0; + } + return 1; +} + +int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, + u64 time_seq) +{ + int slot; + int level; + struct extent_buffer *c; + struct extent_buffer *next; + struct btrfs_fs_info *fs_info = root->fs_info; + struct btrfs_key key; + bool need_commit_sem = false; + u32 nritems; + int ret; + int i; + + /* + * The nowait semantics are used only for write paths, where we don't + * use the tree mod log and sequence numbers. + */ + if (time_seq) + ASSERT(!path->nowait); + + nritems = btrfs_header_nritems(path->nodes[0]); + if (nritems == 0) + return 1; + + btrfs_item_key_to_cpu(path->nodes[0], &key, nritems - 1); +again: + level = 1; + next = NULL; + btrfs_release_path(path); + + path->keep_locks = 1; + + if (time_seq) { + ret = btrfs_search_old_slot(root, &key, path, time_seq); + } else { + if (path->need_commit_sem) { + path->need_commit_sem = 0; + need_commit_sem = true; + if (path->nowait) { + if (!down_read_trylock(&fs_info->commit_root_sem)) { + ret = -EAGAIN; + goto done; + } + } else { + down_read(&fs_info->commit_root_sem); + } + } + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + } + path->keep_locks = 0; + + if (ret < 0) + goto done; + + nritems = btrfs_header_nritems(path->nodes[0]); + /* + * by releasing the path above we dropped all our locks. A balance + * could have added more items next to the key that used to be + * at the very end of the block. So, check again here and + * advance the path if there are now more items available. + */ + if (nritems > 0 && path->slots[0] < nritems - 1) { + if (ret == 0) + path->slots[0]++; + ret = 0; + goto done; + } + /* + * So the above check misses one case: + * - after releasing the path above, someone has removed the item that + * used to be at the very end of the block, and balance between leafs + * gets another one with bigger key.offset to replace it. + * + * This one should be returned as well, or we can get leaf corruption + * later(esp. in __btrfs_drop_extents()). + * + * And a bit more explanation about this check, + * with ret > 0, the key isn't found, the path points to the slot + * where it should be inserted, so the path->slots[0] item must be the + * bigger one. + */ + if (nritems > 0 && ret > 0 && path->slots[0] == nritems - 1) { + ret = 0; + goto done; + } + + while (level < BTRFS_MAX_LEVEL) { + if (!path->nodes[level]) { + ret = 1; + goto done; + } + slot = path->slots[level] + 1; c = path->nodes[level]; if (slot >= btrfs_header_nritems(c)) { level++; - if (level == BTRFS_MAX_LEVEL) - return 1; + if (level == BTRFS_MAX_LEVEL) { + ret = 1; + goto done; + } continue; } - if (path->reada) - reada_for_search(fs_info, path, level, slot, 0); - next = btrfs_read_node_slot(c, slot); - if (!extent_buffer_uptodate(next)) - return -EIO; + /* + * Our current level is where we're going to start from, and to + * make sure lockdep doesn't complain we need to drop our locks + * and nodes from 0 to our current level. + */ + for (i = 0; i < level; i++) { + if (path->locks[level]) { + btrfs_tree_read_unlock(path->nodes[i]); + path->locks[i] = 0; + } + free_extent_buffer(path->nodes[i]); + path->nodes[i] = NULL; + } + + next = c; + ret = read_block_for_search(root, path, &next, level, + slot, &key); + if (ret == -EAGAIN && !path->nowait) + goto again; + + if (ret < 0) { + btrfs_release_path(path); + goto done; + } + + if (!path->skip_locking) { + ret = btrfs_try_tree_read_lock(next); + if (!ret && path->nowait) { + ret = -EAGAIN; + goto done; + } + if (!ret && time_seq) { + /* + * If we don't get the lock, we may be racing + * with push_leaf_left, holding that lock while + * itself waiting for the leaf we've currently + * locked. To solve this situation, we give up + * on our lock and cycle. + */ + free_extent_buffer(next); + btrfs_release_path(path); + cond_resched(); + goto again; + } + if (!ret) + btrfs_tree_read_lock(next); + } break; - } while (level < BTRFS_MAX_LEVEL); + } path->slots[level] = slot; - while(1) { + while (1) { level--; - c = path->nodes[level]; - free_extent_buffer(c); path->nodes[level] = next; path->slots[level] = 0; - /* - * Fsck will happily load corrupt blocks in order to fix them, - * so we need an extra check just to make sure this block isn't - * marked uptodate but invalid. - */ - if (check_block(fs_info, path, level)) - return -EIO; - if (level == path->lowest_level) + if (!path->skip_locking) + path->locks[level] = BTRFS_READ_LOCK; + if (!level) break; - if (path->reada) - reada_for_search(fs_info, path, level, 0, 0); - next = btrfs_read_node_slot(next, 0); - if (!extent_buffer_uptodate(next)) - return -EIO; + + ret = read_block_for_search(root, path, &next, level, + 0, &key); + if (ret == -EAGAIN && !path->nowait) + goto again; + + if (ret < 0) { + btrfs_release_path(path); + goto done; + } + + if (!path->skip_locking) { + if (path->nowait) { + if (!btrfs_try_tree_read_lock(next)) { + ret = -EAGAIN; + goto done; + } + } else { + btrfs_tree_read_lock(next); + } + } } + ret = 0; +done: + unlock_up(path, 0, 1, 0, NULL); + if (need_commit_sem) { + int ret2; + + path->need_commit_sem = 1; + ret2 = finish_need_commit_sem_search(path); + up_read(&fs_info->commit_root_sem); + if (ret2) + ret = ret2; + } + + return ret; +} + +int btrfs_next_old_item(struct btrfs_root *root, struct btrfs_path *path, u64 time_seq) +{ + path->slots[0]++; + if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) + return btrfs_next_old_leaf(root, path, time_seq); return 0; } +/* + * this uses btrfs_prev_leaf to walk backwards in the tree, and keeps + * searching until it gets past min_objectid or finds an item of 'type' + * + * returns 0 if something is found, 1 if nothing was found and < 0 on error + */ int btrfs_previous_item(struct btrfs_root *root, struct btrfs_path *path, u64 min_objectid, int type) @@ -2837,7 +4959,7 @@ int btrfs_previous_item(struct btrfs_root *root, u32 nritems; int ret; - while(1) { + while (1) { if (path->slots[0] == 0) { ret = btrfs_prev_leaf(root, path); if (ret != 0) @@ -2866,7 +4988,7 @@ int btrfs_previous_item(struct btrfs_root *root, /* * search in extent tree to find a previous Metadata/Data extent item with - * min objectid. + * min objecitd. * * returns 0 if something is found, 1 if nothing was found and < 0 on error */ @@ -2905,3 +5027,25 @@ int btrfs_previous_extent_item(struct btrfs_root *root, } return 1; } + +/* + * MODIFIED: + * - This has to be called by open_ctree to make sure we can use stuff. + */ +int __init btrfs_ctree_init(void) +{ + if (btrfs_path_cachep) + return 0; + + btrfs_path_cachep = kmem_cache_create("btrfs_path", + sizeof(struct btrfs_path), 0, + SLAB_MEM_SPREAD, NULL); + if (!btrfs_path_cachep) + return -ENOMEM; + return 0; +} + +void __cold btrfs_ctree_exit(void) +{ + kmem_cache_destroy(btrfs_path_cachep); +} diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 376b8eca..20280ede 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -30,6 +30,7 @@ #include "accessors.h" #include "extent-io-tree.h" #include "locking.h" +#include "crypto/crc32c.h" struct btrfs_root; struct btrfs_trans_handle; @@ -320,6 +321,9 @@ struct btrfs_fs_info { struct extent_io_tree extent_ins; struct extent_io_tree *excluded_extents; + spinlock_t trans_lock; + struct rw_semaphore commit_root_sem; + struct rb_root block_group_cache_tree; /* logical->physical extent mapping */ struct btrfs_mapping_tree mapping_tree; @@ -865,8 +869,19 @@ static inline int __btrfs_fs_compat_ro(struct btrfs_fs_info *fs_info, u64 flag) return !!(btrfs_super_compat_ro_flags(disk_super) & flag); } -u64 btrfs_name_hash(const char *name, int len); -u64 btrfs_extref_hash(u64 parent_objectid, const char *name, int len); +static inline u64 btrfs_name_hash(const char *name, int len) +{ + return crc32c((u32)~1, name, len); +} + +/* + * Figure the key offset of an extended inode ref + */ +static inline u64 btrfs_extref_hash(u64 parent_objectid, const char *name, + int len) +{ + return (u64) crc32c(parent_objectid, name, len); +} /* extent-tree.c */ int btrfs_reserve_extent(struct btrfs_trans_handle *trans, @@ -940,6 +955,8 @@ u64 hash_extent_data_ref(u64 root_objectid, u64 owner, u64 offset); int btrfs_convert_one_bg(struct btrfs_trans_handle *trans, u64 bytenr); /* ctree.c */ +int __init btrfs_ctree_init(void); +struct extent_buffer *btrfs_root_node(struct btrfs_root *root); int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2); void btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot); @@ -953,7 +970,8 @@ int btrfs_previous_extent_item(struct btrfs_root *root, int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, struct extent_buffer *parent, int parent_slot, - struct extent_buffer **cow_ret); + struct extent_buffer **cow_ret, + enum btrfs_lock_nesting nest); int btrfs_copy_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, @@ -963,7 +981,7 @@ void btrfs_truncate_item(struct btrfs_path *path, u32 new_size, int from_end); int btrfs_split_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, - struct btrfs_key *new_key, + const struct btrfs_key *new_key, unsigned long split_offset); int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root, const struct btrfs_key *key, @@ -990,24 +1008,58 @@ static inline int btrfs_del_item(struct btrfs_trans_handle *trans, return btrfs_del_items(trans, root, path, path->slots[0], 1); } -int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root - *root, struct btrfs_key *key, void *data, u32 data_size); +/* + * Describes a batch of items to insert in a btree. This is used by + * btrfs_insert_empty_items(). + */ +struct btrfs_item_batch { + /* + * Pointer to an array containing the keys of the items to insert (in + * sorted order). + */ + const struct btrfs_key *keys; + /* Pointer to an array containing the data size for each item to insert. */ + const u32 *data_sizes; + /* + * The sum of data sizes for all items. The caller can compute this while + * setting up the data_sizes array, so it ends up being more efficient + * than having btrfs_insert_empty_items() or setup_item_for_insert() + * doing it, as it would avoid an extra loop over a potentially large + * array, and in the case of setup_item_for_insert(), we would be doing + * it while holding a write lock on a leaf and often on upper level nodes + * too, unnecessarily increasing the size of a critical section. + */ + u32 total_data_size; + /* Size of the keys and data_sizes arrays (number of items in the batch). */ + int nr; +}; + +int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, + const struct btrfs_key *key, void *data, u32 data_size); int btrfs_insert_empty_items(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, - struct btrfs_key *cpu_key, u32 *data_size, int nr); + const struct btrfs_item_batch *batch); static inline int btrfs_insert_empty_item(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, - struct btrfs_key *key, + const struct btrfs_key *key, u32 data_size) { - return btrfs_insert_empty_items(trans, root, path, key, &data_size, 1); + struct btrfs_item_batch batch; + + batch.keys = key; + batch.data_sizes = &data_size; + batch.total_data_size = data_size; + batch.nr = 1; + + return btrfs_insert_empty_items(trans, root, path, &batch); } -int btrfs_next_sibling_tree_block(struct btrfs_fs_info *fs_info, - struct btrfs_path *path); +int btrfs_next_old_leaf(struct btrfs_root *root, struct btrfs_path *path, + u64 time_seq); +int btrfs_next_old_item(struct btrfs_root *root, struct btrfs_path *path, u64 time_seq); /* * Walk up the tree as far as necessary to find the next leaf. @@ -1018,26 +1070,13 @@ int btrfs_next_sibling_tree_block(struct btrfs_fs_info *fs_info, static inline int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) { - path->lowest_level = 0; - return btrfs_next_sibling_tree_block(root->fs_info, path); + return btrfs_next_old_leaf(root, path, 0); } static inline int btrfs_next_item(struct btrfs_root *root, struct btrfs_path *p) { - ++p->slots[0]; - if (p->slots[0] >= btrfs_header_nritems(p->nodes[0])) { - int ret; - ret = btrfs_next_leaf(root, p); - /* - * Revert the increased slot, or the path may point to - * an invalid item. - */ - if (ret) - p->slots[0]--; - return ret; - } - return 0; + return btrfs_next_old_item(root, p, 0); } int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path); @@ -1045,8 +1084,10 @@ int btrfs_leaf_free_space(struct extent_buffer *leaf); void btrfs_set_item_key_safe(struct btrfs_fs_info *fs_info, struct btrfs_path *path, const struct btrfs_key *new_key); +int btrfs_find_next_key(struct btrfs_root *root, struct btrfs_path *path, + struct btrfs_key *key, int level, u64 min_trans); -u16 btrfs_super_csum_size(const struct btrfs_super_block *s); +int btrfs_super_csum_size(const struct btrfs_super_block *s); const char *btrfs_super_csum_name(u16 csum_type); u16 btrfs_csum_type_size(u16 csum_type); diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index bdf77d50..f9e11d5b 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -898,6 +898,9 @@ struct btrfs_fs_info *btrfs_new_fs_info(int writable, u64 sb_bytenr) INIT_LIST_HEAD(&fs_info->space_info); INIT_LIST_HEAD(&fs_info->recow_ebs); + spin_lock_init(&fs_info->trans_lock); + init_rwsem(&fs_info->commit_root_sem); + if (!writable) fs_info->readonly = 1; @@ -1478,6 +1481,8 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, struct open_ctree_flags *oc unsigned flags = ocf->flags; u64 sb_bytenr = ocf->sb_bytenr; + btrfs_ctree_init(); + if (sb_bytenr == 0) sb_bytenr = BTRFS_SUPER_INFO_OFFSET; diff --git a/kernel-shared/locking.c b/kernel-shared/locking.c index c4138e68..42b82afe 100644 --- a/kernel-shared/locking.c +++ b/kernel-shared/locking.c @@ -8,15 +8,15 @@ struct extent_buffer *btrfs_read_lock_root_node(struct btrfs_root *root) { - return root->node; + return btrfs_root_node(root); } struct extent_buffer *btrfs_try_read_lock_root_node(struct btrfs_root *root) { - return root->node; + return btrfs_root_node(root); } struct extent_buffer *btrfs_lock_root_node(struct btrfs_root *root) { - return root->node; + return btrfs_root_node(root); } diff --git a/kernel-shared/transaction.c b/kernel-shared/transaction.c index 1e1ec85b..5edd19ea 100644 --- a/kernel-shared/transaction.c +++ b/kernel-shared/transaction.c @@ -20,6 +20,7 @@ #include "kernel-shared/delayed-ref.h" #include "kernel-shared/zoned.h" #include "common/messages.h" +#include "kernel-lib/bitops.h" struct btrfs_trans_handle* btrfs_start_transaction(struct btrfs_root *root, int num_blocks) @@ -99,7 +100,8 @@ int commit_tree_roots(struct btrfs_trans_handle *trans, eb = fs_info->tree_root->node; extent_buffer_get(eb); - ret = btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb); + ret = btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb, + BTRFS_NESTING_NORMAL); free_extent_buffer(eb); if (ret) return ret; @@ -119,6 +121,7 @@ int commit_tree_roots(struct btrfs_trans_handle *trans, next = fs_info->dirty_cowonly_roots.next; list_del_init(next); root = list_entry(next, struct btrfs_root, dirty_list); + clear_bit(BTRFS_ROOT_DIRTY, &root->state); ret = update_cowonly_root(trans, root); free_extent_buffer(root->commit_root); root->commit_root = NULL;