From patchwork Tue May 2 01:01:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 13228406 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 470D0C77B7C for ; Tue, 2 May 2023 01:02:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233143AbjEBBCV (ORCPT ); Mon, 1 May 2023 21:02:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50446 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233001AbjEBBCS (ORCPT ); Mon, 1 May 2023 21:02:18 -0400 Received: from smtp-out2.suse.de (smtp-out2.suse.de [IPv6:2001:67c:2178:6::1d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE01A30FD for ; Mon, 1 May 2023 18:02:13 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 34F511F750 for ; Tue, 2 May 2023 01:02:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1682989326; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KQFOWl5yImWUrr851ma5uRnf4/xSDJVtb1nDqWikIPg=; b=DdPVvC7uLEchZn1CR+8XSp2X+e5D4mZn+TjD1CNMuGlmKYnMCDXysvJC8S5Q8TwGm9//TU I3O/Gyy2WOkvhecYWWzQ3ex7UuLbjg6yNf9nkTNs5YS2mQe52mm/zmDJbcRfk42sXQHatV I4GWNZV6uuvi4mwAlOnV9iZzTcs+cAo= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 7D24613580 for ; Tue, 2 May 2023 01:02:05 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id sPUMEQ1hUGTldQAAMHmgww (envelope-from ) for ; Tue, 02 May 2023 01:02:05 +0000 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH 1/3] btrfs-progs: make check/clear-cache.c to be separate from check/main.c Date: Tue, 2 May 2023 09:01:44 +0800 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Currently check/clear-cache.c still uses a lot of global variables like gfs_info and g_task_ctx, which are only implemented in check/main.c. Since we have separated clear-cache code into its own c and header files, we should not utilize those global variables. Or it would lead to compiling errors for any tools which only has check/clear-cache.o linked: /usr/bin/ld: check/clear-cache.o: in function `clear_free_space_cache': /home/adam/btrfs/btrfs-progs/check/clear-cache.c:46: undefined reference to `gfs_info' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:56: undefined reference to `gfs_info' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:67: undefined reference to `gfs_info' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:73: undefined reference to `gfs_info' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:84: undefined reference to `gfs_info' /usr/bin/ld: check/clear-cache.o:/home/adam/btrfs/btrfs-progs/check/clear-cache.c:85: more undefined references to `gfs_info' follow /usr/bin/ld: check/clear-cache.o: in function `check_space_cache': /home/adam/btrfs/btrfs-progs/check/clear-cache.c:357: undefined reference to `g_task_ctx' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:357: undefined reference to `g_task_ctx' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:358: undefined reference to `gfs_info' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:365: undefined reference to `gfs_info' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:373: undefined reference to `gfs_info' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:374: undefined reference to `gfs_info' /usr/bin/ld: /home/adam/btrfs/btrfs-progs/check/clear-cache.c:382: undefined reference to `gfs_info' /usr/bin/ld: check/clear-cache.o:/home/adam/btrfs/btrfs-progs/check/clear-cache.c:383: more undefined references to `gfs_info' follow collect2: error: ld returned 1 exit status This provides the basis for later clear cache usage out of check realm. Signed-off-by: Qu Wenruo --- check/clear-cache.c | 84 ++++++++++++++++++++++++--------------------- check/clear-cache.h | 8 +++-- check/main.c | 6 ++-- 3 files changed, 52 insertions(+), 46 deletions(-) diff --git a/check/clear-cache.c b/check/clear-cache.c index 0a3001a4a6aa..772d920fd397 100644 --- a/check/clear-cache.c +++ b/check/clear-cache.c @@ -35,7 +35,7 @@ */ #define NR_BLOCK_GROUP_CLUSTER (16) -static int clear_free_space_cache(void) +static int clear_free_space_cache(struct btrfs_fs_info *fs_info) { struct btrfs_trans_handle *trans; struct btrfs_block_group *bg_cache; @@ -43,7 +43,7 @@ static int clear_free_space_cache(void) u64 current = 0; int ret = 0; - trans = btrfs_start_transaction(gfs_info->tree_root, 0); + trans = btrfs_start_transaction(fs_info->tree_root, 0); if (IS_ERR(trans)) { ret = PTR_ERR(trans); errno = -ret; @@ -53,7 +53,7 @@ static int clear_free_space_cache(void) /* Clear all free space cache inodes and its extent data */ while (1) { - bg_cache = btrfs_lookup_first_block_group(gfs_info, current); + bg_cache = btrfs_lookup_first_block_group(fs_info, current); if (!bg_cache) break; ret = btrfs_clear_free_space_cache(trans, bg_cache); @@ -64,13 +64,13 @@ static int clear_free_space_cache(void) nr_handled++; if (nr_handled == NR_BLOCK_GROUP_CLUSTER) { - ret = btrfs_commit_transaction(trans, gfs_info->tree_root); + ret = btrfs_commit_transaction(trans, fs_info->tree_root); if (ret < 0) { errno = -ret; error_msg(ERROR_MSG_START_TRANS, "%m"); return ret; } - trans = btrfs_start_transaction(gfs_info->tree_root, 0); + trans = btrfs_start_transaction(fs_info->tree_root, 0); if (IS_ERR(trans)) { ret = PTR_ERR(trans); errno = -ret; @@ -81,8 +81,8 @@ static int clear_free_space_cache(void) current = bg_cache->start + bg_cache->length; } - btrfs_set_super_cache_generation(gfs_info->super_copy, (u64)-1); - ret = btrfs_commit_transaction(trans, gfs_info->tree_root); + btrfs_set_super_cache_generation(fs_info->super_copy, (u64)-1); + ret = btrfs_commit_transaction(trans, fs_info->tree_root); if (ret < 0) { errno = -ret; error_msg(ERROR_MSG_START_TRANS, "%m"); @@ -90,16 +90,17 @@ static int clear_free_space_cache(void) return ret; } -int do_clear_free_space_cache(int clear_version) +int do_clear_free_space_cache(struct btrfs_fs_info *fs_info, + int clear_version) { int ret = 0; if (clear_version == 1) { - if (btrfs_fs_compat_ro(gfs_info, FREE_SPACE_TREE)) + if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) warning( "free space cache v2 detected, use --clear-space-cache v2, proceeding with clearing v1"); - ret = clear_free_space_cache(); + ret = clear_free_space_cache(fs_info); if (ret) { error("failed to clear free space cache"); ret = 1; @@ -107,13 +108,13 @@ int do_clear_free_space_cache(int clear_version) printf("Free space cache cleared\n"); } } else if (clear_version == 2) { - if (!btrfs_fs_compat_ro(gfs_info, FREE_SPACE_TREE)) { + if (!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { printf("no free space cache v2 to clear\n"); ret = 0; goto close_out; } printf("Clear free space cache v2\n"); - ret = btrfs_clear_free_space_tree(gfs_info); + ret = btrfs_clear_free_space_tree(fs_info); if (ret) { error("failed to clear free space cache v2: %d", ret); ret = 1; @@ -127,6 +128,7 @@ close_out: static int check_free_space_tree(struct btrfs_root *root) { + struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_key key = { 0 }; struct btrfs_path path; int ret = 0; @@ -158,7 +160,7 @@ static int check_free_space_tree(struct btrfs_root *root) goto out; } - bg = btrfs_lookup_first_block_group(gfs_info, key.objectid); + bg = btrfs_lookup_first_block_group(fs_info, key.objectid); if (!bg) { fprintf(stderr, "We have a space info key for a block group that doesn't exist\n"); @@ -187,7 +189,7 @@ static int check_free_space_trees(struct btrfs_root *root) }; int ret = 0; - free_space_root = btrfs_global_root(gfs_info, &key); + free_space_root = btrfs_global_root(root->fs_info, &key); while (1) { ret = check_free_space_tree(free_space_root); if (ret) @@ -214,7 +216,7 @@ static int check_cache_range(struct btrfs_root *root, for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { bytenr = btrfs_sb_offset(i); - ret = btrfs_rmap_block(gfs_info, + ret = btrfs_rmap_block(root->fs_info, cache->start, bytenr, &logical, &nr, &stripe_len); if (ret) @@ -340,8 +342,9 @@ static int verify_space_cache(struct btrfs_root *root, return ret; } -static int check_space_cache(struct btrfs_root *root) +static int check_space_cache(struct btrfs_root *root, struct task_ctx *task_ctx) { + struct btrfs_fs_info *fs_info = root->fs_info; struct extent_io_tree used; struct btrfs_block_group *cache; u64 start = BTRFS_SUPER_INFO_OFFSET + BTRFS_SUPER_INFO_SIZE; @@ -349,20 +352,20 @@ static int check_space_cache(struct btrfs_root *root) int error = 0; extent_io_tree_init(&used); - ret = btrfs_mark_used_blocks(gfs_info, &used); + ret = btrfs_mark_used_blocks(fs_info, &used); if (ret) return ret; while (1) { - g_task_ctx.item_count++; - cache = btrfs_lookup_first_block_group(gfs_info, start); + task_ctx->item_count++; + cache = btrfs_lookup_first_block_group(fs_info, start); if (!cache) break; start = cache->start + cache->length; if (!cache->free_space_ctl) { if (btrfs_init_free_space_ctl(cache, - gfs_info->sectorsize)) { + fs_info->sectorsize)) { ret = -ENOMEM; break; } @@ -370,8 +373,8 @@ static int check_space_cache(struct btrfs_root *root) btrfs_remove_free_space_cache(cache); } - if (btrfs_fs_compat_ro(gfs_info, FREE_SPACE_TREE)) { - ret = exclude_super_stripes(gfs_info, cache); + if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { + ret = exclude_super_stripes(fs_info, cache); if (ret) { errno = -ret; fprintf(stderr, @@ -379,8 +382,8 @@ static int check_space_cache(struct btrfs_root *root) error++; continue; } - ret = load_free_space_tree(gfs_info, cache); - free_excluded_extents(gfs_info, cache); + ret = load_free_space_tree(fs_info, cache); + free_excluded_extents(fs_info, cache); if (ret < 0) { errno = -ret; fprintf(stderr, @@ -390,7 +393,7 @@ static int check_space_cache(struct btrfs_root *root) } error += ret; } else { - ret = load_free_space_cache(gfs_info, cache); + ret = load_free_space_cache(fs_info, cache); if (ret < 0) error++; if (ret <= 0) @@ -409,33 +412,34 @@ static int check_space_cache(struct btrfs_root *root) } -int validate_free_space_cache(struct btrfs_root *root) +int validate_free_space_cache(struct btrfs_root *root, struct task_ctx *task_ctx) { + struct btrfs_fs_info *fs_info = root->fs_info; int ret; /* * If cache generation is between 0 and -1ULL, sb generation must be * equal to sb cache generation or the v1 space caches are outdated. */ - if (btrfs_super_cache_generation(gfs_info->super_copy) != -1ULL && - btrfs_super_cache_generation(gfs_info->super_copy) != 0 && - btrfs_super_generation(gfs_info->super_copy) != - btrfs_super_cache_generation(gfs_info->super_copy)) { + if (btrfs_super_cache_generation(fs_info->super_copy) != -1ULL && + btrfs_super_cache_generation(fs_info->super_copy) != 0 && + btrfs_super_generation(fs_info->super_copy) != + btrfs_super_cache_generation(fs_info->super_copy)) { printf( "cache and super generation don't match, space cache will be invalidated\n"); return 0; } - ret = check_space_cache(root); - if (!ret && btrfs_fs_compat_ro(gfs_info, FREE_SPACE_TREE)) + ret = check_space_cache(root, task_ctx); + if (!ret && btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) ret = check_free_space_trees(root); - if (ret && btrfs_fs_compat_ro(gfs_info, FREE_SPACE_TREE) && + if (ret && btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE) && opt_check_repair) { - ret = do_clear_free_space_cache(2); + ret = do_clear_free_space_cache(fs_info, 2); if (ret) goto out; - ret = btrfs_create_free_space_tree(gfs_info); + ret = btrfs_create_free_space_tree(fs_info); if (ret) error("couldn't repair freespace tree"); } @@ -539,7 +543,7 @@ out: return ret; } -int clear_ino_cache_items(void) +int clear_ino_cache_items(struct btrfs_fs_info *fs_info) { int ret; struct btrfs_path path; @@ -550,7 +554,7 @@ int clear_ino_cache_items(void) key.offset = 0; btrfs_init_path(&path); - ret = btrfs_search_slot(NULL, gfs_info->tree_root, &key, &path, 0, 0); + ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, &path, 0, 0); if (ret < 0) return ret; @@ -563,7 +567,7 @@ int clear_ino_cache_items(void) struct btrfs_root *root; found_key.offset = (u64)-1; - root = btrfs_read_fs_root(gfs_info, &found_key); + root = btrfs_read_fs_root(fs_info, &found_key); if (IS_ERR(root)) goto next; ret = truncate_free_ino_items(root); @@ -586,12 +590,12 @@ next: if (key.objectid == BTRFS_FS_TREE_OBJECTID) { key.objectid = BTRFS_FIRST_FREE_OBJECTID; btrfs_release_path(&path); - ret = btrfs_search_slot(NULL, gfs_info->tree_root, &key, + ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, &path, 0, 0); if (ret < 0) return ret; } else { - ret = btrfs_next_item(gfs_info->tree_root, &path); + ret = btrfs_next_item(fs_info->tree_root, &path); if (ret < 0) { goto out; } else if (ret > 0) { diff --git a/check/clear-cache.h b/check/clear-cache.h index b8b71a89df93..78845e8d9557 100644 --- a/check/clear-cache.h +++ b/check/clear-cache.h @@ -17,11 +17,13 @@ #ifndef __BTRFS_CHECK_CLEAR_CACHE_H__ #define __BTRFS_CHECK_CLEAR_CACHE_H__ +struct btrfs_fs_info; struct btrfs_root; +struct task_ctx; -int do_clear_free_space_cache(int clear_version); -int validate_free_space_cache(struct btrfs_root *root); +int do_clear_free_space_cache(struct btrfs_fs_info *fs_info, int clear_version); +int validate_free_space_cache(struct btrfs_root *root, struct task_ctx *task_ctx); int truncate_free_ino_items(struct btrfs_root *root); -int clear_ino_cache_items(void); +int clear_ino_cache_items(struct btrfs_fs_info *fs_info); #endif diff --git a/check/main.c b/check/main.c index 523d800fae2f..1a09701dd898 100644 --- a/check/main.c +++ b/check/main.c @@ -10237,13 +10237,13 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv) } if (clear_space_cache) { - ret = do_clear_free_space_cache(clear_space_cache); + ret = do_clear_free_space_cache(gfs_info, clear_space_cache); err |= !!ret; goto close_out; } if (clear_ino_cache) { - ret = clear_ino_cache_items(); + ret = clear_ino_cache_items(gfs_info); err = ret; goto close_out; } @@ -10409,7 +10409,7 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv) task_start(g_task_ctx.info, &g_task_ctx.start_time, &g_task_ctx.item_count); } - ret = validate_free_space_cache(root); + ret = validate_free_space_cache(root, &g_task_ctx); task_stop(g_task_ctx.info); err |= !!ret; From patchwork Tue May 2 01:01:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 13228405 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 9E07BC7EE21 for ; Tue, 2 May 2023 01:02:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233128AbjEBBCU (ORCPT ); Mon, 1 May 2023 21:02:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50440 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232991AbjEBBCS (ORCPT ); Mon, 1 May 2023 21:02:18 -0400 Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C774B3581 for ; Mon, 1 May 2023 18:02:13 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 5391022516 for ; Tue, 2 May 2023 01:02:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1682989327; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=TUcJVh/B4eJCR+B/LCdw6Xc0ScSbXPQUcD+61xs5nCU=; b=XmT5imTwmIuX/2kvmdgWLvT5Glhzs8TLfsGmHgkZ5CHaY8wa58Wa+EHruiEyI+H5JUSfjU snn6ynMz6akQdWNYxmg+wZjp4P/TSjjjbCaFsOUQIq138xkKkeUnKz9CcMAQTiC/ghFv+f 0K8kvGUzXLuDVRsfA8V6BD4n66W0qTQ= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 9E7AD13580 for ; Tue, 2 May 2023 01:02:06 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id IDdTGQ5hUGTldQAAMHmgww (envelope-from ) for ; Tue, 02 May 2023 01:02:06 +0000 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH 2/3] btrfs-progs: tune: add --convert-to-free-space-tree option Date: Tue, 2 May 2023 09:01:45 +0800 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org From the very beginning of free-space-tree feature, we allow mount option "space_cache=v2" to convert the filesystem to the new feature. But this is not the proper practice for new features (no matter if it's incompat or compat_ro). This is already making the clear_cache/space_cache mount option more complex. Thus this patch introduces the proper way to enable free-space-tree, and I hope one day we can deprecate the "space_cache=" mount option. Signed-off-by: Qu Wenruo --- Documentation/btrfstune.rst | 5 ++++ Makefile | 2 +- check/clear-cache.c | 4 +-- check/clear-cache.h | 1 + tune/main.c | 57 +++++++++++++++++++++++++++++++++++-- 5 files changed, 64 insertions(+), 5 deletions(-) diff --git a/Documentation/btrfstune.rst b/Documentation/btrfstune.rst index d3543a47012e..9907c0535e4e 100644 --- a/Documentation/btrfstune.rst +++ b/Documentation/btrfstune.rst @@ -37,6 +37,11 @@ OPTIONS Convert block groups tracked in standalone block group tree back to extent tree and remove 'block-group-tree' feature bit from the filesystem. +--convert-to-free-space-tree + (since kernel 4.5) + + Convert to free space cache feature (v2 space cache). + -f Allow dangerous changes, e.g. clear the seeding flag or change fsid. Make sure that you are aware of the dangers. diff --git a/Makefile b/Makefile index 4b0a869b6ca5..b03367f26158 100644 --- a/Makefile +++ b/Makefile @@ -250,7 +250,7 @@ convert_objects = convert/main.o convert/common.o convert/source-fs.o \ mkfs_objects = mkfs/main.o mkfs/common.o mkfs/rootdir.o image_objects = image/main.o image/sanitize.o tune_objects = tune/main.o tune/seeding.o tune/change-uuid.o tune/change-metadata-uuid.o \ - tune/convert-bgt.o tune/change-csum.o + tune/convert-bgt.o tune/change-csum.o check/clear-cache.o all_objects = $(objects) $(cmds_objects) $(libbtrfs_objects) $(convert_objects) \ $(mkfs_objects) $(image_objects) $(tune_objects) $(libbtrfsutil_objects) diff --git a/check/clear-cache.c b/check/clear-cache.c index 772d920fd397..8d06640cb826 100644 --- a/check/clear-cache.c +++ b/check/clear-cache.c @@ -35,7 +35,7 @@ */ #define NR_BLOCK_GROUP_CLUSTER (16) -static int clear_free_space_cache(struct btrfs_fs_info *fs_info) +int btrfs_clear_v1_cache(struct btrfs_fs_info *fs_info) { struct btrfs_trans_handle *trans; struct btrfs_block_group *bg_cache; @@ -100,7 +100,7 @@ int do_clear_free_space_cache(struct btrfs_fs_info *fs_info, warning( "free space cache v2 detected, use --clear-space-cache v2, proceeding with clearing v1"); - ret = clear_free_space_cache(fs_info); + ret = btrfs_clear_v1_cache(fs_info); if (ret) { error("failed to clear free space cache"); ret = 1; diff --git a/check/clear-cache.h b/check/clear-cache.h index 78845e8d9557..1cdf49051244 100644 --- a/check/clear-cache.h +++ b/check/clear-cache.h @@ -21,6 +21,7 @@ struct btrfs_fs_info; struct btrfs_root; struct task_ctx; +int btrfs_clear_v1_cache(struct btrfs_fs_info *fs_info); int do_clear_free_space_cache(struct btrfs_fs_info *fs_info, int clear_version); int validate_free_space_cache(struct btrfs_root *root, struct task_ctx *task_ctx); int truncate_free_ino_items(struct btrfs_root *root); diff --git a/tune/main.c b/tune/main.c index 891bea14ee5e..55ecae784ada 100644 --- a/tune/main.c +++ b/tune/main.c @@ -28,6 +28,8 @@ #include "kernel-shared/disk-io.h" #include "kernel-shared/transaction.h" #include "kernel-shared/volumes.h" +#include "kernel-shared/free-space-cache.h" +#include "kernel-shared/free-space-tree.h" #include "common/utils.h" #include "common/open-utils.h" #include "common/parse-utils.h" @@ -38,6 +40,7 @@ #include "common/box.h" #include "cmds/commands.h" #include "tune/tune.h" +#include "check/clear-cache.h" static char *device; static int force = 0; @@ -60,6 +63,36 @@ static int set_super_incompat_flags(struct btrfs_root *root, u64 flags) return ret; } +static int convert_to_fst(struct btrfs_fs_info *fs_info) +{ + int ret; + + /* We may have invalid old v2 cache, clear them first. */ + if (btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE)) { + ret = btrfs_clear_free_space_tree(fs_info); + if (ret < 0) { + errno = -ret; + error("failed to clear stale v2 free space cache: %m"); + return ret; + } + } + ret = btrfs_clear_v1_cache(fs_info); + if (ret < 0) { + errno = -ret; + error("failed to clear v1 free space cache: %m"); + return ret; + } + + ret = btrfs_create_free_space_tree(fs_info); + if (ret < 0) { + errno = -ret; + error("failed to create free space tree: %m"); + return ret; + } + printf("Converted to free space tree feature\n"); + return ret; +} + static const char * const tune_usage[] = { "btrfstune [options] device", "Tune settings of filesystem features on an unmounted device", @@ -75,6 +108,8 @@ static const char * const tune_usage[] = { OPTLINE("--convert-from-block-group-tree", "convert the block group tree back to extent tree (remove the incompat bit)"), "", + OPTLINE("--convert-to-free-space-tree", + "convert filesystem to use free space tree (v2 cache)"), "UUID changes:", OPTLINE("-u", "rewrite fsid, use a random one"), OPTLINE("-U UUID", "rewrite fsid to UUID"), @@ -108,6 +143,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[]) int change_metadata_uuid = 0; bool to_extent_tree = false; bool to_bg_tree = false; + bool to_fst = false; int csum_type = -1; char *new_fsid_str = NULL; int ret; @@ -119,13 +155,16 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[]) while(1) { enum { GETOPT_VAL_CSUM = GETOPT_VAL_FIRST, GETOPT_VAL_ENABLE_BLOCK_GROUP_TREE, - GETOPT_VAL_DISABLE_BLOCK_GROUP_TREE }; + GETOPT_VAL_DISABLE_BLOCK_GROUP_TREE, + GETOPT_VAL_ENABLE_FREE_SPACE_TREE }; static const struct option long_options[] = { { "help", no_argument, NULL, GETOPT_VAL_HELP}, { "convert-to-block-group-tree", no_argument, NULL, GETOPT_VAL_ENABLE_BLOCK_GROUP_TREE}, { "convert-from-block-group-tree", no_argument, NULL, GETOPT_VAL_DISABLE_BLOCK_GROUP_TREE}, + { "convert-to-free-space-tree", no_argument, NULL, + GETOPT_VAL_ENABLE_FREE_SPACE_TREE}, #if EXPERIMENTAL { "csum", required_argument, NULL, GETOPT_VAL_CSUM }, #endif @@ -175,6 +214,9 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[]) case GETOPT_VAL_DISABLE_BLOCK_GROUP_TREE: to_extent_tree = true; break; + case GETOPT_VAL_ENABLE_FREE_SPACE_TREE: + to_fst = true; + break; #if EXPERIMENTAL case GETOPT_VAL_CSUM: btrfs_warn_experimental( @@ -200,7 +242,7 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[]) } if (!super_flags && !seeding_flag && !(random_fsid || new_fsid_str) && !change_metadata_uuid && csum_type == -1 && !to_bg_tree && - !to_extent_tree) { + !to_extent_tree && !to_fst) { error("at least one option should be specified"); usage(&tune_cmd, 1); return 1; @@ -269,6 +311,17 @@ int BOX_MAIN(btrfstune)(int argc, char *argv[]) } goto out; } + if (to_fst) { + if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE_VALID)) { + error("filesystem already has free-space-tree feature"); + ret = 1; + goto out; + } + ret = convert_to_fst(root->fs_info); + if (ret < 0) + error("failed to convert the filesystem to free-space-tree feature"); + goto out; + } if (to_extent_tree) { if (to_bg_tree) { error("option --convert-to-block-group-tree conflicts with --convert-from-block-group-tree"); From patchwork Tue May 2 01:01:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 13228403 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 946FFC77B7C for ; Tue, 2 May 2023 01:02:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232467AbjEBBCQ (ORCPT ); Mon, 1 May 2023 21:02:16 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50354 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230202AbjEBBCP (ORCPT ); Mon, 1 May 2023 21:02:15 -0400 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BE67C30F6 for ; Mon, 1 May 2023 18:02:09 -0700 (PDT) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 727111F854 for ; Tue, 2 May 2023 01:02:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1682989328; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=m40easRD3g+cccI1U1Ub9+cOATt2e81kaIk0ouUp6fY=; b=qVqV2tyFI9WaTus1rj4AZrxMcsIg025CXYADuEsiCQc7j36wVbdPT4jwrK4QQoETe40k+H V0VJ7jQzxLPLLmN1gnq8GTHzJIiqx5g6VrM1P82qHe1sgiKlHWIz5EFCSd2Tu+oY4I2nYy SIDBLGS9A0mlhsMltQHg70Vf8HTU/0k= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id BD5D913580 for ; Tue, 2 May 2023 01:02:07 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id kJnYIA9hUGTldQAAMHmgww (envelope-from ) for ; Tue, 02 May 2023 01:02:07 +0000 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH 3/3] btrfs-progs: misc-tests: add test case to verify btrfstune --convert-to-free-space-tree option Date: Tue, 2 May 2023 09:01:46 +0800 Message-Id: X-Mailer: git-send-email 2.39.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org The new test case would create a fs without free space tree, then popluate it, convert to free-space-tree feature, and make sure everything is fine. Signed-off-by: Qu Wenruo --- .../057-btrfstune-free-space-tree/test.sh | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100755 tests/misc-tests/057-btrfstune-free-space-tree/test.sh diff --git a/tests/misc-tests/057-btrfstune-free-space-tree/test.sh b/tests/misc-tests/057-btrfstune-free-space-tree/test.sh new file mode 100755 index 000000000000..c69f99cfbd38 --- /dev/null +++ b/tests/misc-tests/057-btrfstune-free-space-tree/test.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# test btrfstune --convert-to-free-space-tree option + +source "$TEST_TOP/common" || exit +source "$TEST_TOP/common.convert" || exit + +check_prereq mkfs.btrfs +check_prereq btrfstune +check_prereq btrfs + +setup_root_helper +prepare_test_dev + +run_check_mkfs_test_dev -O ^free-space-tree +run_check_mount_test_dev +populate_fs +run_check_umount_test_dev + +run_check $SUDO_HELPER "$TOP/btrfstune" --convert-to-free-space-tree $TEST_DEV + +run_check "$TOP/btrfs" check "$TEST_DEV"