From patchwork Mon Nov 14 18:43:21 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Sandoval X-Patchwork-Id: 9428239 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 44AF960755 for ; Mon, 14 Nov 2016 18:43:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3417B28A66 for ; Mon, 14 Nov 2016 18:43:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 28F3328ABA; Mon, 14 Nov 2016 18:43:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D30628A92 for ; Mon, 14 Nov 2016 18:43:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933642AbcKNSnl (ORCPT ); Mon, 14 Nov 2016 13:43:41 -0500 Received: from mail-pf0-f169.google.com ([209.85.192.169]:35517 "EHLO mail-pf0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933399AbcKNSnf (ORCPT ); Mon, 14 Nov 2016 13:43:35 -0500 Received: by mail-pf0-f169.google.com with SMTP id i88so30825684pfk.2 for ; Mon, 14 Nov 2016 10:43:35 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=osandov-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=MoU47cAgdiUPoX08kCxptrv63+BkU8Pje3K8rZjzG14=; b=yNrzIvY/ribvaJxC0kpkPs39aiooXfHmGxIOUqLvFaQX4z2GaDwnrG85hIRq08zpYC /n2mxAOsPVavVKi+oTdmx2UAfykKwLggifgmfOjU+UNDwR3pXW4FyfBqTwg4y6Nfy5Am 1PNkGmTv8TBgwPy9PHWM+/7jo176cgOMehajEDrefKf58vaDIhRovYmBPoCVFVUpdB6O Otgv0Ymcsy71WbKqWC0qxNklUluTwtszLtOZLuMEHQ3z2d0/r9hGTuhffikyYCk72+kD H7nCUvwubOuL+FYyHuOzFevehokyKbZZunaDF0Qad/w2TeezQCm5tw5aUV0hqcJcc3uM 69Rw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=MoU47cAgdiUPoX08kCxptrv63+BkU8Pje3K8rZjzG14=; b=Fm0H5h2Pn2EQdKr+qSEdXgpvKvWXY7ztVjArMnvwKjzLxMp8ThRhxmuqVl4VxC+cmk ARPATToVlcYwA3BC7CH1totePy1/FMvagkoy8ezahJzie4oTuX/r+U6/ZgJLf9LBBEIW DS2r7ceNFKPn2U2UmbndjeaDOVZvaP2o7I0ID3QUGjYdXc0iV+f406AsgktOWNTZLULA 9y3H8RR/s4biNLPUoessrs/x3TrhuAx5U496Vu9AobezMt1lERjiZOQ3qu95qZTzxEzX USXAANBww58bOzdiUAk7+pLlS01gGej2sbgVDwPIS18qI1Lo0Nf725NHNLiwFhYy4Fry z5yw== X-Gm-Message-State: ABUngvcx5IvTiZG3WM5sWLJ6PFemGql+iG9wAIjfeIvXsuYvJePkNE4mqhHDZEZWrrw7MCWa X-Received: by 10.98.59.82 with SMTP id i79mr38273685pfa.147.1479149014437; Mon, 14 Nov 2016 10:43:34 -0800 (PST) Received: from vader.thefacebook.com ([2620:10d:c090:200::a:38b9]) by smtp.gmail.com with ESMTPSA id v76sm15488481pfk.77.2016.11.14.10.43.33 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 14 Nov 2016 10:43:34 -0800 (PST) From: Omar Sandoval To: linux-btrfs@vger.kernel.org Cc: kernel-team@fb.com Subject: [PATCH v2 4/6] btrfs-progs: add btrfs_clear_free_space_tree() from the kernel Date: Mon, 14 Nov 2016 10:43:21 -0800 Message-Id: X-Mailer: git-send-email 2.10.2 In-Reply-To: References: In-Reply-To: References: Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Omar Sandoval Reviewed-by: Qu Wenruo Signed-off-by: Omar Sandoval --- ctree.h | 6 ++++ extent-tree.c | 11 +++++++ free-space-tree.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ free-space-tree.h | 1 + root-tree.c | 25 +++++++++++++++ 5 files changed, 134 insertions(+) diff --git a/ctree.h b/ctree.h index d67b852..b433bca 100644 --- a/ctree.h +++ b/ctree.h @@ -2504,6 +2504,10 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, int record_parent); int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, int record_parent); +int btrfs_free_tree_block(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *buf, + u64 parent, int last_ref); int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 parent, @@ -2664,6 +2668,8 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, struct btrfs_root_item *item); +int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, + struct btrfs_key *key); int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_key *key, struct btrfs_root_item *item); diff --git a/extent-tree.c b/extent-tree.c index 3b1577e..b52c515 100644 --- a/extent-tree.c +++ b/extent-tree.c @@ -2467,6 +2467,17 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct return err; } + +int btrfs_free_tree_block(struct btrfs_trans_handle *trans, + struct btrfs_root *root, + struct extent_buffer *buf, + u64 parent, int last_ref) +{ + return btrfs_free_extent(trans, root, buf->start, buf->len, parent, + root->root_key.objectid, + btrfs_header_level(buf), 0); +} + /* * remove an extent from the root, returns 0 on success */ diff --git a/free-space-tree.c b/free-space-tree.c index 3c7a246..b9e21f7 100644 --- a/free-space-tree.c +++ b/free-space-tree.c @@ -20,6 +20,7 @@ #include "disk-io.h" #include "free-space-cache.h" #include "free-space-tree.h" +#include "transaction.h" static struct btrfs_free_space_info * search_free_space_info(struct btrfs_trans_handle *trans, @@ -67,6 +68,96 @@ static int free_space_test_bit(struct btrfs_block_group_cache *block_group, return !!extent_buffer_test_bit(leaf, ptr, i); } +static int clear_free_space_tree(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + struct btrfs_path *path; + struct btrfs_key key; + int nr; + int ret; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + + key.objectid = 0; + key.type = 0; + key.offset = 0; + + while (1) { + ret = btrfs_search_slot(trans, root, &key, path, -1, 1); + if (ret < 0) + goto out; + + nr = btrfs_header_nritems(path->nodes[0]); + if (!nr) + break; + + path->slots[0] = 0; + ret = btrfs_del_items(trans, root, path, 0, nr); + if (ret) + goto out; + + btrfs_release_path(path); + } + + ret = 0; +out: + btrfs_free_path(path); + return ret; +} + +int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info) +{ + struct btrfs_trans_handle *trans; + struct btrfs_root *tree_root = fs_info->tree_root; + struct btrfs_root *free_space_root = fs_info->free_space_root; + int ret; + u64 features; + + trans = btrfs_start_transaction(tree_root, 0); + if (IS_ERR(trans)) + return PTR_ERR(trans); + + + features = btrfs_super_compat_ro_flags(fs_info->super_copy); + features &= ~(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID | + BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE); + btrfs_set_super_compat_ro_flags(fs_info->super_copy, features); + fs_info->free_space_root = NULL; + + ret = clear_free_space_tree(trans, free_space_root); + if (ret) + goto abort; + + ret = btrfs_del_root(trans, tree_root, &free_space_root->root_key); + if (ret) + goto abort; + + list_del(&free_space_root->dirty_list); + + ret = clean_tree_block(trans, tree_root, free_space_root->node); + if (ret) + goto abort; + ret = btrfs_free_tree_block(trans, free_space_root, + free_space_root->node, 0, 1); + if (ret) + goto abort; + + free_extent_buffer(free_space_root->node); + free_extent_buffer(free_space_root->commit_root); + kfree(free_space_root); + + ret = btrfs_commit_transaction(trans, tree_root); + if (ret) + return ret; + + return 0; + +abort: + return ret; +} + static int load_free_space_bitmaps(struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group, struct btrfs_path *path, diff --git a/free-space-tree.h b/free-space-tree.h index 7529a46..4845f13 100644 --- a/free-space-tree.h +++ b/free-space-tree.h @@ -19,6 +19,7 @@ #ifndef __BTRFS_FREE_SPACE_TREE_H__ #define __BTRFS_FREE_SPACE_TREE_H__ +int btrfs_clear_free_space_tree(struct btrfs_fs_info *fs_info); int load_free_space_tree(struct btrfs_fs_info *fs_info, struct btrfs_block_group_cache *block_group); diff --git a/root-tree.c b/root-tree.c index cca424e..ab01a14 100644 --- a/root-tree.c +++ b/root-tree.c @@ -143,6 +143,31 @@ int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root return ret; } +/* drop the root item for 'key' from 'root' */ +int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root, + struct btrfs_key *key) +{ + struct btrfs_path *path; + int ret; + + path = btrfs_alloc_path(); + if (!path) + return -ENOMEM; + ret = btrfs_search_slot(trans, root, key, path, -1, 1); + if (ret < 0) + goto out; + + if (ret != 0) { + ret = -ENOENT; + goto out; + } + + ret = btrfs_del_item(trans, root, path); +out: + btrfs_free_path(path); + return ret; +} + /* * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY * or BTRFS_ROOT_BACKREF_KEY.