mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-12-08 00:00:12 +03:00
cmd_strip_alloc
Add a command for stripping allocation info for a filesystem. This is primarily to test codepaths used by the new image creation tool. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
3f66d905c0
commit
f2d9a55b1b
@ -36,6 +36,7 @@ void bcachefs_usage(void)
|
||||
" recover-super Attempt to recover overwritten superblock from backups\n"
|
||||
" set-fs-option Set a filesystem option\n"
|
||||
" reset-counters Reset all counters on an unmounted device\n"
|
||||
" strip-alloc Strip alloc info on a filesystem to be used read-only\n"
|
||||
"\n"
|
||||
"Mount:\n"
|
||||
" mount Mount a filesystem\n"
|
||||
|
||||
142
c_src/cmd_strip_alloc.c
Normal file
142
c_src/cmd_strip_alloc.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Authors: Kent Overstreet <kent.overstreet@linux.dev>
|
||||
*
|
||||
* GPLv2
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include "cmds.h"
|
||||
#include "cmd_strip_alloc.h"
|
||||
#include "libbcachefs/errcode.h"
|
||||
#include "libbcachefs/opts.h"
|
||||
#include "libbcachefs/journal.h"
|
||||
#include "libbcachefs/sb-clean.h"
|
||||
#include "libbcachefs/super-io.h"
|
||||
#include "libbcachefs/util.h"
|
||||
|
||||
#include "libbcachefs/darray.h"
|
||||
|
||||
void strip_fs_alloc(struct bch_fs *c)
|
||||
{
|
||||
struct bch_sb_field_clean *clean = bch2_sb_field_get(c->disk_sb.sb, clean);
|
||||
struct jset_entry *entry = clean->start;
|
||||
|
||||
unsigned u64s = clean->field.u64s;
|
||||
while (entry != vstruct_end(&clean->field)) {
|
||||
if (entry->type == BCH_JSET_ENTRY_btree_root &&
|
||||
btree_id_is_alloc(entry->btree_id)) {
|
||||
clean->field.u64s -= jset_u64s(entry->u64s);
|
||||
memmove(entry,
|
||||
vstruct_next(entry),
|
||||
vstruct_end(&clean->field) - (void *) vstruct_next(entry));
|
||||
} else {
|
||||
entry = vstruct_next(entry);
|
||||
}
|
||||
}
|
||||
|
||||
swap(u64s, clean->field.u64s);
|
||||
bch2_sb_field_resize(&c->disk_sb, clean, u64s);
|
||||
|
||||
bch2_sb_field_resize(&c->disk_sb, replicas_v0, 0);
|
||||
bch2_sb_field_resize(&c->disk_sb, replicas, 0);
|
||||
|
||||
for_each_online_member(c, ca, 0) {
|
||||
bch2_sb_field_resize(&c->disk_sb, journal, 0);
|
||||
bch2_sb_field_resize(&c->disk_sb, journal_v2, 0);
|
||||
}
|
||||
|
||||
for_each_member_device(c, ca) {
|
||||
struct bch_member *m = bch2_members_v2_get_mut(c->disk_sb.sb, ca->dev_idx);
|
||||
SET_BCH_MEMBER_FREESPACE_INITIALIZED(m, false);
|
||||
}
|
||||
|
||||
c->disk_sb.sb->features[0] |= cpu_to_le64(BIT_ULL(BCH_FEATURE_no_alloc_info));
|
||||
}
|
||||
|
||||
static void strip_alloc_usage(void)
|
||||
{
|
||||
puts("bcachefs strip-alloc - remove alloc info and journal from a filesystem\n"
|
||||
"Removes metadata unneeded for running in read-only mode\n"
|
||||
"Alloc info and journal will be recreated on first RW mount\n"
|
||||
"Usage: bcachefs strip_alloc [OPTION]... <devices>\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help Display this help and exit\n"
|
||||
"Report bugs to <linux-bcachefs@vger.kernel.org>");
|
||||
}
|
||||
|
||||
int cmd_strip_alloc(int argc, char *argv[])
|
||||
{
|
||||
static const struct option longopts[] = {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ NULL }
|
||||
};
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt_long(argc, argv, "h", longopts, NULL)) != -1)
|
||||
switch (opt) {
|
||||
case 'h':
|
||||
strip_alloc_usage();
|
||||
exit(16);
|
||||
}
|
||||
args_shift(optind);
|
||||
|
||||
if (!argc) {
|
||||
fprintf(stderr, "Please supply device(s)\n");
|
||||
exit(8);
|
||||
}
|
||||
|
||||
darray_const_str devs = get_or_split_cmdline_devs(argc, argv);
|
||||
|
||||
struct bch_opts opts = bch2_opts_empty();
|
||||
opt_set(opts, nostart, true);
|
||||
reopen:
|
||||
struct bch_fs *c = bch2_fs_open(&devs, &opts);
|
||||
int ret = PTR_ERR_OR_ZERO(c);
|
||||
if (ret)
|
||||
die("Error opening filesystem: %s", bch2_err_str(ret));
|
||||
|
||||
if (!c->sb.clean) {
|
||||
printf("Filesystem not clean, running recovery");
|
||||
ret = bch2_fs_start(c);
|
||||
if (ret) {
|
||||
fprintf(stderr, "Error starting filesystem: %s\n", bch2_err_str(ret));
|
||||
goto err_stop;
|
||||
}
|
||||
bch2_fs_stop(c);
|
||||
goto reopen;
|
||||
}
|
||||
|
||||
u64 capacity = 0;
|
||||
for_each_member_device(c, ca)
|
||||
capacity += ca->mi.nbuckets * (ca->mi.bucket_size << 9);
|
||||
|
||||
if (capacity > 1ULL << 40) {
|
||||
fprintf(stderr, "capacity too large for alloc info reconstruction, exiting\n");
|
||||
goto err_stop;
|
||||
}
|
||||
|
||||
printf("Stripping alloc info from %s\n", argv[0]);
|
||||
|
||||
mutex_lock(&c->sb_lock);
|
||||
strip_fs_alloc(c);
|
||||
bch2_write_super(c);
|
||||
mutex_unlock(&c->sb_lock);
|
||||
err_stop:
|
||||
bch2_fs_stop(c);
|
||||
return ret;
|
||||
}
|
||||
7
c_src/cmd_strip_alloc.h
Normal file
7
c_src/cmd_strip_alloc.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef _TOOLS_CMD_STRIP_ALLOC_H
|
||||
#define _TOOLS_CMD_STRIP_ALLOC_H
|
||||
|
||||
void strip_fs_alloc(struct bch_fs *);
|
||||
|
||||
#endif /* _TOOLS_CMD_STRIP_ALLOC_H */
|
||||
|
||||
@ -13,6 +13,7 @@ int cmd_format(int argc, char *argv[]);
|
||||
int cmd_show_super(int argc, char *argv[]);
|
||||
int cmd_recover_super(int argc, char *argv[]);
|
||||
int cmd_reset_counters(int argc, char *argv[]);
|
||||
int cmd_strip_alloc(int argc, char *argv[]);
|
||||
int cmd_set_option(int argc, char *argv[]);
|
||||
|
||||
int fs_usage(void);
|
||||
|
||||
@ -61,6 +61,7 @@ fn handle_c_command(mut argv: Vec<String>, symlink_cmd: Option<&str>) -> i32 {
|
||||
"set-file-option" => c::cmd_setattr(argc, argv),
|
||||
"show-super" => c::cmd_show_super(argc, argv),
|
||||
"recover-super" => c::cmd_recover_super(argc, argv),
|
||||
"strip-alloc" => c::cmd_strip_alloc(argc, argv),
|
||||
"unlock" => c::cmd_unlock(argc, argv),
|
||||
"version" => c::cmd_version(argc, argv),
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user