mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-12-09 00:00:17 +03:00
cmd_show_super: Look up and print names of member devices
bch2_sb_to_text_with_names(): print device paths and models of each member. Fixes: https://github.com/koverstreet/bcachefs/issues/801 Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
4174fe0bae
commit
6704e252ef
@ -85,6 +85,7 @@ fn main() {
|
|||||||
.opaque_type("gc_stripe")
|
.opaque_type("gc_stripe")
|
||||||
.opaque_type("open_bucket.*")
|
.opaque_type("open_bucket.*")
|
||||||
.opaque_type("replicas_delta_list")
|
.opaque_type("replicas_delta_list")
|
||||||
|
.allowlist_type("sb_names")
|
||||||
.no_copy("btree_trans")
|
.no_copy("btree_trans")
|
||||||
.no_copy("printbuf")
|
.no_copy("printbuf")
|
||||||
.no_partialeq("bkey")
|
.no_partialeq("bkey")
|
||||||
|
|||||||
@ -13,6 +13,7 @@
|
|||||||
#include "include/linux/blkdev.h"
|
#include "include/linux/blkdev.h"
|
||||||
#include "cmds.h"
|
#include "cmds.h"
|
||||||
#include "raid/raid.h"
|
#include "raid/raid.h"
|
||||||
|
#include "src/rust_to_c.h"
|
||||||
|
|
||||||
/* Fix753 is a workaround for https://github.com/rust-lang/rust-bindgen/issues/753
|
/* Fix753 is a workaround for https://github.com/rust-lang/rust-bindgen/issues/753
|
||||||
* Functional macro are not expanded with bindgen, e.g. ioctl are automatically ignored
|
* Functional macro are not expanded with bindgen, e.g. ioctl are automatically ignored
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
#include "cmds.h"
|
#include "cmds.h"
|
||||||
|
#include "cmd_super.h"
|
||||||
#include "tools-util.h"
|
#include "tools-util.h"
|
||||||
#include "posix_to_bcachefs.h"
|
#include "posix_to_bcachefs.h"
|
||||||
#include "libbcachefs.h"
|
#include "libbcachefs.h"
|
||||||
@ -293,7 +294,7 @@ int cmd_format(int argc, char *argv[])
|
|||||||
struct printbuf buf = PRINTBUF;
|
struct printbuf buf = PRINTBUF;
|
||||||
buf.human_readable_units = true;
|
buf.human_readable_units = true;
|
||||||
|
|
||||||
bch2_sb_to_text(&buf, sb, false, 1 << BCH_SB_FIELD_members_v2);
|
bch2_sb_to_text_with_names(&buf, sb, false, 1 << BCH_SB_FIELD_members_v2, -1);
|
||||||
printf("%s", buf.buf);
|
printf("%s", buf.buf);
|
||||||
printbuf_exit(&buf);
|
printbuf_exit(&buf);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
|
|
||||||
#include "cmds.h"
|
#include "cmds.h"
|
||||||
|
#include "cmd_super.h"
|
||||||
#include "libbcachefs.h"
|
#include "libbcachefs.h"
|
||||||
#include "libbcachefs/opts.h"
|
#include "libbcachefs/opts.h"
|
||||||
#include "libbcachefs/super-io.h"
|
#include "libbcachefs/super-io.h"
|
||||||
@ -28,6 +29,8 @@
|
|||||||
|
|
||||||
#include "libbcachefs/darray.h"
|
#include "libbcachefs/darray.h"
|
||||||
|
|
||||||
|
#include "src/rust_to_c.h"
|
||||||
|
|
||||||
static void show_super_usage(void)
|
static void show_super_usage(void)
|
||||||
{
|
{
|
||||||
puts("bcachefs show-super \n"
|
puts("bcachefs show-super \n"
|
||||||
@ -42,6 +45,72 @@ static void show_super_usage(void)
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct sb_name *sb_dev_to_name(sb_names sb_names, unsigned idx)
|
||||||
|
{
|
||||||
|
darray_for_each(sb_names, i)
|
||||||
|
if (i->sb.sb->dev_idx == idx)
|
||||||
|
return i;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_one_member(struct printbuf *out, sb_names sb_names,
|
||||||
|
struct bch_sb *sb,
|
||||||
|
struct bch_sb_field_disk_groups *gi,
|
||||||
|
struct bch_member m, unsigned idx)
|
||||||
|
{
|
||||||
|
struct sb_name *name = sb_dev_to_name(sb_names, idx);
|
||||||
|
prt_printf(out, "Device %u:\t%s\t", idx, name ? name->name : "(not found)");
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
char *model = fd_to_dev_model(name->sb.bdev->bd_fd);
|
||||||
|
prt_str(out, model);
|
||||||
|
free(model);
|
||||||
|
}
|
||||||
|
prt_newline(out);
|
||||||
|
|
||||||
|
printbuf_indent_add(out, 2);
|
||||||
|
bch2_member_to_text(out, &m, gi, sb, idx);
|
||||||
|
printbuf_indent_sub(out, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bch2_sb_to_text_with_names(struct printbuf *out, struct bch_sb *sb,
|
||||||
|
bool print_layout, unsigned fields, int field_only)
|
||||||
|
{
|
||||||
|
CLASS(printbuf, uuid_buf)();
|
||||||
|
prt_str(&uuid_buf, "UUID=");
|
||||||
|
pr_uuid(&uuid_buf, sb->user_uuid.b);
|
||||||
|
|
||||||
|
sb_names sb_names = {};
|
||||||
|
bch2_scan_device_sbs(uuid_buf.buf, &sb_names);
|
||||||
|
|
||||||
|
if (field_only >= 0) {
|
||||||
|
struct bch_sb_field *f = bch2_sb_field_get_id(sb, field_only);
|
||||||
|
|
||||||
|
if (f)
|
||||||
|
__bch2_sb_field_to_text(out, sb, f);
|
||||||
|
} else {
|
||||||
|
printbuf_tabstop_push(out, 44);
|
||||||
|
|
||||||
|
bch2_sb_to_text(out, sb, print_layout,
|
||||||
|
fields & ~(BIT(BCH_SB_FIELD_members_v1)|
|
||||||
|
BIT(BCH_SB_FIELD_members_v2)));
|
||||||
|
|
||||||
|
struct bch_sb_field_disk_groups *gi = bch2_sb_field_get(sb, disk_groups);
|
||||||
|
|
||||||
|
struct bch_sb_field_members_v1 *mi1;
|
||||||
|
if ((fields & BIT(BCH_SB_FIELD_members_v1)) &&
|
||||||
|
(mi1 = bch2_sb_field_get(sb, members_v1)))
|
||||||
|
for (unsigned i = 0; i < sb->nr_devices; i++)
|
||||||
|
print_one_member(out, sb_names, sb, gi, bch2_members_v1_get(mi1, i), i);
|
||||||
|
|
||||||
|
struct bch_sb_field_members_v2 *mi2;
|
||||||
|
if ((fields & BIT(BCH_SB_FIELD_members_v2)) &&
|
||||||
|
(mi2 = bch2_sb_field_get(sb, members_v2)))
|
||||||
|
for (unsigned i = 0; i < sb->nr_devices; i++)
|
||||||
|
print_one_member(out, sb_names, sb, gi, bch2_members_v2_get(mi2, i), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int cmd_show_super(int argc, char *argv[])
|
int cmd_show_super(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
static const struct option longopts[] = {
|
static const struct option longopts[] = {
|
||||||
@ -98,32 +167,16 @@ int cmd_show_super(int argc, char *argv[])
|
|||||||
|
|
||||||
if (print_default_fields) {
|
if (print_default_fields) {
|
||||||
fields |= bch2_sb_field_get(sb.sb, members_v2)
|
fields |= bch2_sb_field_get(sb.sb, members_v2)
|
||||||
? 1 << BCH_SB_FIELD_members_v2
|
? BIT(BCH_SB_FIELD_members_v2)
|
||||||
: 1 << BCH_SB_FIELD_members_v1;
|
: BIT(BCH_SB_FIELD_members_v1);
|
||||||
fields |= 1 << BCH_SB_FIELD_errors;
|
fields |= BIT(BCH_SB_FIELD_errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct printbuf buf = PRINTBUF;
|
struct printbuf buf = PRINTBUF;
|
||||||
|
|
||||||
buf.human_readable_units = true;
|
buf.human_readable_units = true;
|
||||||
|
|
||||||
if (field_only >= 0) {
|
bch2_sb_to_text_with_names(&buf, sb.sb, print_layout, fields, field_only);
|
||||||
struct bch_sb_field *f = bch2_sb_field_get_id(sb.sb, field_only);
|
|
||||||
|
|
||||||
if (f)
|
|
||||||
__bch2_sb_field_to_text(&buf, sb.sb, f);
|
|
||||||
} else {
|
|
||||||
printbuf_tabstop_push(&buf, 44);
|
|
||||||
|
|
||||||
char *model = fd_to_dev_model(sb.bdev->bd_fd);
|
|
||||||
prt_str(&buf, "Device:");
|
|
||||||
prt_tab(&buf);
|
|
||||||
prt_str(&buf, model);
|
|
||||||
prt_newline(&buf);
|
|
||||||
free(model);
|
|
||||||
|
|
||||||
bch2_sb_to_text(&buf, sb.sb, print_layout, fields);
|
|
||||||
}
|
|
||||||
printf("%s", buf.buf);
|
printf("%s", buf.buf);
|
||||||
|
|
||||||
bch2_free_super(&sb);
|
bch2_free_super(&sb);
|
||||||
|
|||||||
8
c_src/cmd_super.h
Normal file
8
c_src/cmd_super.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _TOOLS_CMD_SHOW_SUPER_H
|
||||||
|
#define _TOOLS_CMD_SHOW_SUPER_H
|
||||||
|
|
||||||
|
#include "libbcachefs/super-io.h"
|
||||||
|
|
||||||
|
void bch2_sb_to_text_with_names(struct printbuf *, struct bch_sb *, bool, unsigned, int);
|
||||||
|
|
||||||
|
#endif /* _TOOLS_CMD_SHOW_SUPER_H */
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
ffi::{CStr, CString, c_char},
|
ffi::{CStr, CString, c_char, c_int},
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
env,
|
env,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
@ -7,7 +7,12 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bch_bindgen::{bcachefs, bcachefs::bch_sb_handle, opt_set};
|
use bch_bindgen::{bcachefs, opt_set};
|
||||||
|
use bcachefs::{
|
||||||
|
bch_sb_handle,
|
||||||
|
sb_name,
|
||||||
|
sb_names,
|
||||||
|
};
|
||||||
use bcachefs::bch_opts;
|
use bcachefs::bch_opts;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
@ -185,13 +190,39 @@ pub fn scan_devices(device: &String, opts: &bch_opts) -> Result<String> {
|
|||||||
Ok(joined_device_str(&sbs))
|
Ok(joined_device_str(&sbs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn bch2_scan_device_sbs(device: *const c_char, ret: *mut sb_names) -> c_int {
|
||||||
|
let device = unsafe { CStr::from_ptr(device) };
|
||||||
|
let device = device.to_str().unwrap().to_string();
|
||||||
|
|
||||||
|
// how to initialize to default/empty?
|
||||||
|
let opts = bch_bindgen::opts::parse_mount_opts(None, None, true).unwrap_or_default();
|
||||||
|
|
||||||
|
let sbs = scan_sbs(&device, &opts).unwrap();
|
||||||
|
|
||||||
|
let mut sbs = sbs.iter()
|
||||||
|
.map(|(name, sb)| sb_name {
|
||||||
|
name: CString::new(name.clone().into_os_string().into_string().unwrap()).unwrap().into_raw(),
|
||||||
|
sb: *sb } )
|
||||||
|
.collect::<Vec<sb_name>>();
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
(*ret).data = sbs.as_mut_ptr();
|
||||||
|
(*ret).nr = sbs.len();
|
||||||
|
(*ret).size = sbs.capacity();
|
||||||
|
|
||||||
|
std::mem::forget(sbs);
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn bch2_scan_devices(device: *const c_char) -> *mut c_char {
|
pub extern "C" fn bch2_scan_devices(device: *const c_char) -> *mut c_char {
|
||||||
let device = unsafe { CStr::from_ptr(device) };
|
let device = unsafe { CStr::from_ptr(device) };
|
||||||
let device = device.to_str().unwrap().to_string();
|
let device = device.to_str().unwrap().to_string();
|
||||||
|
|
||||||
let opts = bch_bindgen::opts::parse_mount_opts(None, None, true)
|
// how to initialize to default/empty?
|
||||||
.unwrap_or_default();
|
let opts = bch_bindgen::opts::parse_mount_opts(None, None, true).unwrap_or_default();
|
||||||
|
|
||||||
CString::new(scan_devices(&device, &opts).unwrap()).unwrap().into_raw()
|
CString::new(scan_devices(&device, &opts).unwrap()).unwrap().into_raw()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,17 @@
|
|||||||
#ifndef _BCACHEFS_TOOLS_RUST_TO_C_H
|
#ifndef _BCACHEFS_TOOLS_RUST_TO_C_H
|
||||||
#define _BCACHEFS_TOOLS_RUST_TO_C_H
|
#define _BCACHEFS_TOOLS_RUST_TO_C_H
|
||||||
|
|
||||||
|
#include "libbcachefs/super_types.h"
|
||||||
|
#include "libbcachefs/darray.h"
|
||||||
|
|
||||||
|
struct sb_name {
|
||||||
|
const char *name;
|
||||||
|
struct bch_sb_handle sb;
|
||||||
|
};
|
||||||
|
typedef DARRAY(struct sb_name) sb_names;
|
||||||
|
|
||||||
|
int bch2_scan_device_sbs(char *, sb_names *ret);
|
||||||
|
|
||||||
char *bch2_scan_devices(char *);
|
char *bch2_scan_devices(char *);
|
||||||
|
|
||||||
#endif /* _BCACHEFS_TOOLS_RUST_TO_C_H */
|
#endif /* _BCACHEFS_TOOLS_RUST_TO_C_H */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user