public inbox for linux-bcachefs@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH TOOLS v2 0/5] new debug command
@ 2024-07-14 20:02 Thomas Bertschinger
  2024-07-14 20:02 ` [PATCH TOOLS v2 1/5] include debuginfo in bcachefs binary by default Thomas Bertschinger
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Thomas Bertschinger @ 2024-07-14 20:02 UTC (permalink / raw)
  To: kent.overstreet, linux-bcachefs, bfoster; +Cc: Thomas Bertschinger

This introduces a new command, "debug", to the bcachefs tool.

Changes in v2:
- minor fixups
- added "field+=value" to increment a field's value, in addition to
  "field=value"

Thomas Bertschinger (5):
  include debuginfo in bcachefs binary by default
  update minimum Rust version to 1.74.0
  introduce "list_bkeys" command
  introduce "debug" command and "dump" subcommand
  introduce new "debug update" command

 Cargo.lock                       | 374 ++++++++++++++++++++++---------
 Cargo.toml                       |   9 +-
 c_src/bcachefs.c                 |   4 +-
 c_src/cmd_debug.c                | 145 ++++++++++++
 c_src/cmds.h                     |  18 ++
 src/bcachefs.rs                  |   5 +-
 src/commands/debug/bkey_types.rs | 340 ++++++++++++++++++++++++++++
 src/commands/debug/mod.rs        | 173 ++++++++++++++
 src/commands/debug/parser.rs     | 105 +++++++++
 src/commands/mod.rs              |   3 +
 10 files changed, 1061 insertions(+), 115 deletions(-)
 create mode 100644 c_src/cmd_debug.c
 create mode 100644 src/commands/debug/bkey_types.rs
 create mode 100644 src/commands/debug/mod.rs
 create mode 100644 src/commands/debug/parser.rs

--
2.45.2


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH TOOLS v2 1/5] include debuginfo in bcachefs binary by default
  2024-07-14 20:02 [PATCH TOOLS v2 0/5] new debug command Thomas Bertschinger
@ 2024-07-14 20:02 ` Thomas Bertschinger
  2024-07-14 20:20   ` Kent Overstreet
  2024-07-14 20:02 ` [PATCH TOOLS v2 2/5] update minimum Rust version to 1.74.0 Thomas Bertschinger
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 9+ messages in thread
From: Thomas Bertschinger @ 2024-07-14 20:02 UTC (permalink / raw)
  To: kent.overstreet, linux-bcachefs, bfoster; +Cc: Thomas Bertschinger

The debuginfo is used by the "bcachefs debug" and "bcachefs list_bkeys"
commands.

Rust 1.77 [1] changed Cargo's release profile to strip debuginfo by default,
but we always want it included.

[1] https://github.com/rust-lang/cargo/pull/13257

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
---
 Cargo.toml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/Cargo.toml b/Cargo.toml
index 9d1756fd..d56d6272 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -30,3 +30,6 @@ zeroize = { version = "1", features = ["std", "zeroize_derive"] }
 version = "0.10"
 default-features = false
 features = ["auto-color"]
+
+[profile.release]
+strip = "none"
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH TOOLS v2 2/5] update minimum Rust version to 1.74.0
  2024-07-14 20:02 [PATCH TOOLS v2 0/5] new debug command Thomas Bertschinger
  2024-07-14 20:02 ` [PATCH TOOLS v2 1/5] include debuginfo in bcachefs binary by default Thomas Bertschinger
@ 2024-07-14 20:02 ` Thomas Bertschinger
  2024-07-14 20:02 ` [PATCH TOOLS v2 3/5] introduce "list_bkeys" command Thomas Bertschinger
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Thomas Bertschinger @ 2024-07-14 20:02 UTC (permalink / raw)
  To: kent.overstreet, linux-bcachefs, bfoster; +Cc: Thomas Bertschinger

The new debug command needs RFC 2145 [1], "Replace old private-in-public
diagnostic with type privacy lints", in order to build succesfully. An
error was reported incorrectly for `parse_command()` in the
`debug::parser` module. This is fixed in Rust version 1.74.0.

[1] https://rust-lang.github.io/rfcs/2145-type-privacy.html

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
---
 Cargo.lock | 233 ++++++++++++++++++++++++++++-------------------------
 Cargo.toml |   2 +-
 2 files changed, 123 insertions(+), 112 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 1e109998..9b781755 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,56 +4,57 @@ version = 3
 
 [[package]]
 name = "aho-corasick"
-version = "1.1.2"
+version = "1.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "anstream"
-version = "0.6.11"
+version = "0.6.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
 dependencies = [
  "anstyle",
  "anstyle-parse",
  "anstyle-query",
  "anstyle-wincon",
  "colorchoice",
+ "is_terminal_polyfill",
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle"
-version = "1.0.6"
+version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.3"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
 dependencies = [
  "utf8parse",
 ]
 
 [[package]]
 name = "anstyle-query"
-version = "1.0.2"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391"
 dependencies = [
  "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "anstyle-wincon"
-version = "3.0.2"
+version = "3.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
 dependencies = [
  "anstyle",
  "windows-sys 0.52.0",
@@ -61,15 +62,15 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.79"
+version = "1.0.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
 
 [[package]]
 name = "autocfg"
-version = "1.1.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
 
 [[package]]
 name = "bcachefs-tools"
@@ -114,7 +115,7 @@ version = "0.69.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0"
 dependencies = [
- "bitflags 2.4.2",
+ "bitflags 2.6.0",
  "cexpr",
  "clang-sys",
  "itertools",
@@ -145,9 +146,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.4.2"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
 
 [[package]]
 name = "byteorder"
@@ -157,12 +158,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "cc"
-version = "1.0.83"
+version = "1.0.104"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
-dependencies = [
- "libc",
-]
+checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490"
 
 [[package]]
 name = "cexpr"
@@ -181,9 +179,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "clang-sys"
-version = "1.7.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
+checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
 dependencies = [
  "glob",
  "libc",
@@ -192,9 +190,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.4.18"
+version = "4.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
+checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -202,9 +200,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.4.18"
+version = "4.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
+checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
 dependencies = [
  "anstream",
  "anstyle",
@@ -215,18 +213,18 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.4.10"
+version = "4.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb745187d7f4d76267b37485a65e0149edd0e91a4cfcdd3f27524ad86cee9f3"
+checksum = "1d598e88f6874d4b888ed40c71efbcbf4076f1dfbae128a08a8c9e45f710605d"
 dependencies = [
  "clap",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.4.7"
+version = "4.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -236,21 +234,21 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.6.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70"
 
 [[package]]
 name = "colorchoice"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
 
 [[package]]
 name = "either"
-version = "1.9.0"
+version = "1.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
 
 [[package]]
 name = "env_logger"
@@ -276,9 +274,9 @@ dependencies = [
 
 [[package]]
 name = "errno"
-version = "0.3.8"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
 dependencies = [
  "libc",
  "windows-sys 0.52.0",
@@ -302,9 +300,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 
 [[package]]
 name = "heck"
-version = "0.4.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
 name = "hermit-abi"
@@ -332,6 +330,12 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
 [[package]]
 name = "itertools"
 version = "0.12.1"
@@ -343,9 +347,9 @@ dependencies = [
 
 [[package]]
 name = "lazy_static"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "lazycell"
@@ -355,18 +359,18 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "libc"
-version = "0.2.153"
+version = "0.2.155"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
 
 [[package]]
 name = "libloading"
-version = "0.8.1"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
+checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d"
 dependencies = [
  "cfg-if",
- "windows-sys 0.48.0",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -381,9 +385,9 @@ dependencies = [
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.4.13"
+version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
 
 [[package]]
 name = "log"
@@ -393,9 +397,9 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
 
 [[package]]
 name = "memchr"
-version = "2.7.1"
+version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
 [[package]]
 name = "memoffset"
@@ -430,21 +434,21 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "paste"
-version = "1.0.14"
+version = "1.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
+checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
 
 [[package]]
 name = "pkg-config"
-version = "0.3.29"
+version = "0.3.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
+checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
 
 [[package]]
 name = "prettyplease"
-version = "0.2.16"
+version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"
+checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e"
 dependencies = [
  "proc-macro2",
  "syn",
@@ -452,27 +456,27 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.78"
+version = "1.0.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.35"
+version = "1.0.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
 name = "regex"
-version = "1.10.3"
+version = "1.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
+checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -482,9 +486,9 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.5"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -493,9 +497,9 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.8.2"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
 
 [[package]]
 name = "rpassword"
@@ -526,12 +530,12 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
 name = "rustix"
-version = "0.38.31"
+version = "0.38.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
 dependencies = [
- "bitflags 2.4.2",
- "errno 0.3.8",
+ "bitflags 2.6.0",
+ "errno 0.3.9",
  "libc",
  "linux-raw-sys",
  "windows-sys 0.52.0",
@@ -551,24 +555,24 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
 [[package]]
 name = "strsim"
-version = "0.10.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
 
 [[package]]
 name = "strum"
-version = "0.26.2"
+version = "0.26.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
+checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
 dependencies = [
  "strum_macros",
 ]
 
 [[package]]
 name = "strum_macros"
-version = "0.26.2"
+version = "0.26.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"
+checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -579,9 +583,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.48"
+version = "2.0.68"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
+checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -626,15 +630,15 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
 [[package]]
 name = "utf8parse"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
 name = "uuid"
-version = "1.7.0"
+version = "1.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
+checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439"
 
 [[package]]
 name = "which"
@@ -694,7 +698,7 @@ version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets 0.52.0",
+ "windows-targets 0.52.6",
 ]
 
 [[package]]
@@ -714,17 +718,18 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
 dependencies = [
- "windows_aarch64_gnullvm 0.52.0",
- "windows_aarch64_msvc 0.52.0",
- "windows_i686_gnu 0.52.0",
- "windows_i686_msvc 0.52.0",
- "windows_x86_64_gnu 0.52.0",
- "windows_x86_64_gnullvm 0.52.0",
- "windows_x86_64_msvc 0.52.0",
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
 ]
 
 [[package]]
@@ -735,9 +740,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
 
 [[package]]
 name = "windows_aarch64_msvc"
@@ -747,9 +752,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
 
 [[package]]
 name = "windows_i686_gnu"
@@ -759,9 +764,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
 
 [[package]]
 name = "windows_i686_msvc"
@@ -771,9 +782,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
 
 [[package]]
 name = "windows_x86_64_gnu"
@@ -783,9 +794,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
@@ -795,9 +806,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
 
 [[package]]
 name = "windows_x86_64_msvc"
@@ -807,9 +818,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.52.0"
+version = "0.52.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
 name = "zeroize"
diff --git a/Cargo.toml b/Cargo.toml
index d56d6272..d3b0e753 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,7 +3,7 @@ name = "bcachefs-tools"
 version = "1.9.1"
 authors = ["Yuxuan Shui <yshuiv7@gmail.com>", "Kayla Firestack <dev@kaylafire.me>", "Kent Overstreet <kent.overstreet@linux.dev>" ]
 edition = "2021"
-rust-version = "1.70"
+rust-version = "1.74"
 
 [[bin]]
 name = "bcachefs"
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH TOOLS v2 3/5] introduce "list_bkeys" command
  2024-07-14 20:02 [PATCH TOOLS v2 0/5] new debug command Thomas Bertschinger
  2024-07-14 20:02 ` [PATCH TOOLS v2 1/5] include debuginfo in bcachefs binary by default Thomas Bertschinger
  2024-07-14 20:02 ` [PATCH TOOLS v2 2/5] update minimum Rust version to 1.74.0 Thomas Bertschinger
@ 2024-07-14 20:02 ` Thomas Bertschinger
  2024-07-14 20:02 ` [PATCH TOOLS v2 4/5] introduce "debug" command and "dump" subcommand Thomas Bertschinger
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Thomas Bertschinger @ 2024-07-14 20:02 UTC (permalink / raw)
  To: kent.overstreet, linux-bcachefs, bfoster; +Cc: Thomas Bertschinger

This introduces a new command, "list_bkeys", which is used to list the
known bkey types as well as their fields. This will be used by debug
tooling introduced in a subsequent change.

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
---
 Cargo.lock                       | 141 ++++++++++++++
 Cargo.toml                       |   4 +
 src/bcachefs.rs                  |   4 +-
 src/commands/debug/bkey_types.rs | 320 +++++++++++++++++++++++++++++++
 src/commands/debug/mod.rs        |   9 +
 src/commands/mod.rs              |   2 +
 6 files changed, 478 insertions(+), 2 deletions(-)
 create mode 100644 src/commands/debug/bkey_types.rs
 create mode 100644 src/commands/debug/mod.rs

diff --git a/Cargo.lock b/Cargo.lock
index 9b781755..b9e35816 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,12 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
 [[package]]
 name = "aho-corasick"
 version = "1.1.3"
@@ -84,8 +90,12 @@ dependencies = [
  "either",
  "env_logger",
  "errno 0.2.8",
+ "gimli",
  "libc",
  "log",
+ "memmap2",
+ "nom",
+ "object",
  "rpassword",
  "strum",
  "strum_macros",
@@ -244,6 +254,26 @@ version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
 
+[[package]]
+name = "crc32fast"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "derive_more"
+version = "0.99.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "either"
 version = "1.13.0"
@@ -261,6 +291,12 @@ dependencies = [
  "termcolor",
 ]
 
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
 [[package]]
 name = "errno"
 version = "0.2.8"
@@ -292,12 +328,45 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "fallible-iterator"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+
+[[package]]
+name = "flate2"
+version = "1.0.30"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "gimli"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+dependencies = [
+ "fallible-iterator",
+ "indexmap",
+ "stable_deref_trait",
+]
+
 [[package]]
 name = "glob"
 version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 
+[[package]]
+name = "hashbrown"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+
 [[package]]
 name = "heck"
 version = "0.5.0"
@@ -319,6 +388,16 @@ dependencies = [
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "indexmap"
+version = "2.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
 [[package]]
 name = "is-terminal"
 version = "0.4.12"
@@ -401,6 +480,15 @@ version = "2.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
 
+[[package]]
+name = "memmap2"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "memoffset"
 version = "0.8.0"
@@ -416,6 +504,15 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
+[[package]]
+name = "miniz_oxide"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
+dependencies = [
+ "adler",
+]
+
 [[package]]
 name = "nom"
 version = "7.1.3"
@@ -426,6 +523,17 @@ dependencies = [
  "minimal-lexical",
 ]
 
+[[package]]
+name = "object"
+version = "0.35.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e"
+dependencies = [
+ "flate2",
+ "memchr",
+ "ruzstd",
+]
+
 [[package]]
 name = "once_cell"
 version = "1.19.0"
@@ -547,12 +655,35 @@ version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
 
+[[package]]
+name = "ruzstd"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5174a470eeb535a721ae9fdd6e291c2411a906b96592182d05217591d5c5cf7b"
+dependencies = [
+ "byteorder",
+ "derive_more",
+ "twox-hash",
+]
+
 [[package]]
 name = "shlex"
 version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
 
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
 [[package]]
 name = "strsim"
 version = "0.11.1"
@@ -611,6 +742,16 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "twox-hash"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
+dependencies = [
+ "cfg-if",
+ "static_assertions",
+]
+
 [[package]]
 name = "udev"
 version = "0.7.0"
diff --git a/Cargo.toml b/Cargo.toml
index d3b0e753..50527ea7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -25,6 +25,10 @@ byteorder = "1.3"
 strum = { version = "0.26", features = ["derive"] }
 strum_macros = "0.26"
 zeroize = { version = "1", features = ["std", "zeroize_derive"] }
+gimli = "0.29.0"
+object = "0.35.0"
+memmap2 = "0.9.4"
+nom = "7.1.3"
 
 [dependencies.env_logger]
 version = "0.10"
diff --git a/src/bcachefs.rs b/src/bcachefs.rs
index 26422abd..4b8cef49 100644
--- a/src/bcachefs.rs
+++ b/src/bcachefs.rs
@@ -28,9 +28,8 @@ fn handle_c_command(mut argv: Vec<String>, symlink_cmd: Option<&str>) -> i32 {
 
     let argc: i32 = argv.len().try_into().unwrap();
 
-    let argv: Vec<_> = argv.into_iter().map(|s| CString::new(s).unwrap()).collect();
+    let argv = argv.into_iter().map(|s| CString::new(s).unwrap());
     let mut argv = argv
-        .into_iter()
         .map(|s| Box::into_raw(s.into_boxed_c_str()).cast::<c_char>())
         .collect::<Box<[*mut c_char]>>();
     let argv = argv.as_mut_ptr();
@@ -108,6 +107,7 @@ fn main() -> ExitCode {
             ExitCode::SUCCESS
         }
         "list" => commands::list(args[1..].to_vec()).report(),
+        "list_bkeys" => commands::list_bkeys().report(),
         "mount" => commands::mount(args, symlink_cmd).report(),
         "subvolume" => commands::subvolume(args[1..].to_vec()).report(),
         _ => ExitCode::from(u8::try_from(handle_c_command(args, symlink_cmd)).unwrap()),
diff --git a/src/commands/debug/bkey_types.rs b/src/commands/debug/bkey_types.rs
new file mode 100644
index 00000000..680d4410
--- /dev/null
+++ b/src/commands/debug/bkey_types.rs
@@ -0,0 +1,320 @@
+//! Representation of the bcachefs bkey types, derived from DWARF debug info.
+
+use anyhow::{anyhow, Result};
+use object::{Object, ObjectSection};
+use std::collections::HashSet;
+use std::{borrow, error, fs};
+
+/// A list of the known bcachefs bkey types.
+#[derive(Debug)]
+pub struct BkeyTypes(Vec<BchStruct>);
+
+impl BkeyTypes {
+    pub fn new() -> Self {
+        BkeyTypes(Vec::new())
+    }
+}
+
+impl std::fmt::Display for BkeyTypes {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        for bkey in self.0.iter() {
+            for memb in bkey.members.iter() {
+                writeln!(
+                    f,
+                    "{} {} {} {}",
+                    bkey.name, memb.name, memb.size, memb.offset
+                )?;
+            }
+            writeln!(f)?;
+        }
+        Ok(())
+    }
+}
+
+/// The representation of a struct type. The only information we need
+/// is the type's name and a list of its members.
+#[derive(Debug)]
+pub struct BchStruct {
+    name: String,
+    pub members: Vec<BchMember>,
+}
+
+/// The representation of a struct member. We need its name, size, and offset
+/// within the parent struct.
+#[derive(Debug)]
+pub struct BchMember {
+    name: String,
+    size: u64,
+    offset: u64,
+}
+
+// The section data that will be stored in `DwarfSections` and `DwarfPackageSections`.
+#[derive(Default)]
+struct Section<'data> {
+    data: borrow::Cow<'data, [u8]>,
+}
+
+type Reader<'data> = gimli::EndianSlice<'data, gimli::RunTimeEndian>;
+
+fn process_file(
+    object: &object::File,
+    struct_list: &mut BkeyTypes,
+) -> Result<(), Box<dyn error::Error>> {
+    let endian = if object.is_little_endian() {
+        gimli::RunTimeEndian::Little
+    } else {
+        gimli::RunTimeEndian::Big
+    };
+
+    fn load_section<'data>(
+        object: &object::File<'data>,
+        name: &str,
+    ) -> Result<Section<'data>, Box<dyn error::Error>> {
+        Ok(match object.section_by_name(name) {
+            Some(section) => Section {
+                data: section.uncompressed_data()?,
+            },
+            None => Default::default(),
+        })
+    }
+
+    let dwarf_sections = gimli::DwarfSections::load(|id| load_section(object, id.name()))?;
+
+    let dwarf = dwarf_sections
+        .borrow(|section| gimli::EndianSlice::new(borrow::Cow::as_ref(&section.data), endian));
+
+    let mut bkey_types = HashSet::new();
+    load_bkey_types(&mut bkey_types);
+
+    let mut iter = dwarf.units();
+    while let Some(header) = iter.next()? {
+        let unit = dwarf.unit(header)?;
+        process_unit(&dwarf, &unit, struct_list, &mut bkey_types)?;
+    }
+
+    Ok(())
+}
+
+fn load_bkey_types(bkey_types: &mut HashSet<String>) {
+    let mut ptr: *const *const i8 = unsafe { bch_bindgen::c::bch2_bkey_types.as_ptr() };
+    unsafe {
+        while !(*ptr).is_null() {
+            let mut bkey_name = String::from("bch_");
+            bkey_name.push_str(std::ffi::CStr::from_ptr(*ptr).to_str().unwrap());
+            bkey_types.insert(bkey_name);
+            ptr = ptr.offset(1);
+        }
+    }
+
+    // This key type is not included in BCH2_BKEY_TYPES.
+    bkey_types.insert("bch_inode_unpacked".to_string());
+}
+
+fn process_unit(
+    dwarf: &gimli::Dwarf<Reader>,
+    unit: &gimli::Unit<Reader>,
+    struct_list: &mut BkeyTypes,
+    bkey_types: &mut HashSet<String>,
+) -> Result<(), gimli::Error> {
+    let mut tree = unit.entries_tree(None)?;
+
+    process_tree(dwarf, unit, tree.root()?, struct_list, bkey_types)?;
+
+    Ok(())
+}
+
+#[derive(Clone, Copy)]
+enum CompType {
+    Union,
+    Struct,
+}
+
+/// Used to keep track of info needed for structs that contain
+/// other compound types.
+struct ParentInfo<'a> {
+    ty: CompType,
+    starting_offset: u64,
+    member_prefix: &'a str,
+}
+
+fn entry_name(
+    dwarf: &gimli::Dwarf<Reader>,
+    unit: &gimli::Unit<Reader>,
+    entry: &gimli::DebuggingInformationEntry<Reader>,
+) -> Option<String> {
+    entry.attr(gimli::DW_AT_name).ok()?.and_then(|name| {
+        Some(
+            dwarf
+                .attr_string(unit, name.value())
+                .ok()?
+                .to_string_lossy()
+                .into_owned(),
+        )
+    })
+}
+
+fn process_tree(
+    dwarf: &gimli::Dwarf<Reader>,
+    unit: &gimli::Unit<Reader>,
+    node: gimli::EntriesTreeNode<Reader>,
+    struct_list: &mut BkeyTypes,
+    bkey_types: &mut HashSet<String>,
+) -> gimli::Result<()> {
+    let entry = node.entry();
+    if entry.tag() == gimli::DW_TAG_structure_type {
+        let name = entry_name(dwarf, unit, entry);
+        let Some(name) = name else {
+            return Ok(());
+        };
+
+        if bkey_types.remove(&name) {
+            let mut members: Vec<BchMember> = Vec::new();
+            let parent_info = ParentInfo {
+                ty: CompType::Struct,
+                starting_offset: 0,
+                member_prefix: "",
+            };
+            process_compound_type(dwarf, unit, node, &mut members, &parent_info)?;
+            struct_list.0.push(BchStruct { name, members });
+        }
+    } else {
+        let mut children = node.children();
+        while let Some(child) = children.next()? {
+            process_tree(dwarf, unit, child, struct_list, bkey_types)?;
+        }
+    }
+    Ok(())
+}
+
+fn process_compound_type(
+    dwarf: &gimli::Dwarf<Reader>,
+    unit: &gimli::Unit<Reader>,
+    node: gimli::EntriesTreeNode<Reader>,
+    members: &mut Vec<BchMember>,
+    parent: &ParentInfo,
+) -> gimli::Result<()> {
+    let mut children = node.children();
+    while let Some(child) = children.next()? {
+        process_comp_member(dwarf, unit, child, members, parent)?;
+    }
+
+    Ok(())
+}
+
+/// Given a DIE, checks if that DIE has a reference to a compound type (i.e., struct or union) and
+/// if so, returns the offset in the DIE tree for that type, and the kind of compound type it is.
+fn get_comp_ref(
+    unit: &gimli::Unit<Reader>,
+    entry: &gimli::DebuggingInformationEntry<Reader>,
+) -> Option<(gimli::UnitOffset, CompType)> {
+    let ref_type = entry.attr(gimli::DW_AT_type).ok()??;
+    let ref_offset = match ref_type.value() {
+        gimli::AttributeValue::UnitRef(offset) => offset,
+        _ => return None,
+    };
+
+    let mut ty_entry = unit.entries_at_offset(ref_offset).ok()?;
+    ty_entry.next_entry().ok()??;
+    let ty_entry = ty_entry.current()?;
+
+    match ty_entry.tag() {
+        gimli::DW_TAG_structure_type => Some((ty_entry.offset(), CompType::Struct)),
+        gimli::DW_TAG_union_type => Some((ty_entry.offset(), CompType::Union)),
+        _ => None,
+    }
+}
+
+fn process_comp_member(
+    dwarf: &gimli::Dwarf<Reader>,
+    unit: &gimli::Unit<Reader>,
+    node: gimli::EntriesTreeNode<Reader>,
+    members: &mut Vec<BchMember>,
+    parent: &ParentInfo,
+) -> gimli::Result<()> {
+    let entry = node.entry().clone();
+
+    let Some(offset) = (match parent.ty {
+        CompType::Union => Some(0),
+        CompType::Struct => entry
+            .attr(gimli::DW_AT_data_member_location)?
+            .and_then(|offset| offset.value().udata_value()),
+    }) else {
+        return Ok(());
+    };
+
+    let name = entry_name(dwarf, unit, &entry);
+
+    if let Some((ref_type, comp)) = get_comp_ref(unit, &entry) {
+        let prefix = if let Some(ref name) = name {
+            let mut prefix = name.clone();
+            prefix.push('.');
+            prefix
+        } else {
+            String::from("")
+        };
+        let parent = ParentInfo {
+            ty: comp,
+            starting_offset: offset,
+            member_prefix: &prefix,
+        };
+        let mut tree = unit.entries_tree(Some(ref_type))?;
+        process_compound_type(dwarf, unit, tree.root()?, members, &parent)?;
+
+        return Ok(());
+    };
+
+    let Some(size) = get_size(unit, &entry) else {
+        return Ok(());
+    };
+
+    let Some(name) = name else { return Ok(()) };
+    let mut name_with_prefix = String::from(parent.member_prefix);
+    name_with_prefix.push_str(&name);
+
+    members.push(BchMember {
+        name: name_with_prefix,
+        offset: offset + parent.starting_offset,
+        size,
+    });
+
+    Ok(())
+}
+
+fn get_size(
+    unit: &gimli::Unit<Reader>,
+    entry: &gimli::DebuggingInformationEntry<Reader>,
+) -> Option<u64> {
+    if let Some(size) = entry.attr(gimli::DW_AT_byte_size).ok()? {
+        return size.udata_value();
+    }
+
+    let ref_type = entry.attr(gimli::DW_AT_type).ok()??;
+    if let gimli::AttributeValue::UnitRef(offset) = ref_type.value() {
+        let mut type_entry = unit.entries_at_offset(offset).ok()?;
+        type_entry.next_entry().ok()?;
+        if let Some(t) = type_entry.current() {
+            return get_size(unit, t);
+        }
+    }
+
+    None
+}
+
+/// Return a list of the known bkey types and information on their field layout.
+pub fn get_bkey_type_info() -> Result<BkeyTypes> {
+    let path = fs::read_link("/proc/self/exe").unwrap();
+    let file = fs::File::open(path).unwrap();
+    let mmap = unsafe { memmap2::Mmap::map(&file).unwrap() };
+    let object = object::File::parse(&*mmap).unwrap();
+
+    let mut struct_list = BkeyTypes::new();
+    process_file(&object, &mut struct_list).unwrap();
+
+    if struct_list.0.is_empty() {
+        Err(anyhow!(
+            "Could not find bkey debug info.\nWas the bcachefs binary compiled with debug info?"
+        ))
+    } else {
+        Ok(struct_list)
+    }
+}
diff --git a/src/commands/debug/mod.rs b/src/commands/debug/mod.rs
new file mode 100644
index 00000000..30ffd16b
--- /dev/null
+++ b/src/commands/debug/mod.rs
@@ -0,0 +1,9 @@
+mod bkey_types;
+
+use anyhow::Result;
+
+pub fn list_bkeys() -> Result<()> {
+    print!("{}", bkey_types::get_bkey_type_info()?);
+
+    Ok(())
+}
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 7f466f92..9365f981 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -1,11 +1,13 @@
 use clap::Subcommand;
 
 pub mod completions;
+pub mod debug;
 pub mod list;
 pub mod mount;
 pub mod subvolume;
 
 pub use completions::completions;
+pub use debug::list_bkeys;
 pub use list::list;
 pub use mount::mount;
 pub use subvolume::subvolume;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH TOOLS v2 4/5] introduce "debug" command and "dump" subcommand
  2024-07-14 20:02 [PATCH TOOLS v2 0/5] new debug command Thomas Bertschinger
                   ` (2 preceding siblings ...)
  2024-07-14 20:02 ` [PATCH TOOLS v2 3/5] introduce "list_bkeys" command Thomas Bertschinger
@ 2024-07-14 20:02 ` Thomas Bertschinger
  2024-07-14 20:19   ` Kent Overstreet
  2024-07-14 20:02 ` [PATCH TOOLS v2 5/5] introduce new "debug update" command Thomas Bertschinger
  2024-07-14 20:21 ` [PATCH TOOLS v2 0/5] new debug command Kent Overstreet
  5 siblings, 1 reply; 9+ messages in thread
From: Thomas Bertschinger @ 2024-07-14 20:02 UTC (permalink / raw)
  To: kent.overstreet, linux-bcachefs, bfoster; +Cc: Thomas Bertschinger

This introduces a new command, "debug", that is used for directly
manipulating bkeys in the underlying btrees.

It has a subcommand, "dump", which takes a btree and bpos and
prints the data from that bkey.

For example:

$ bcachefs debug ~/test-img -c "dump inodes 0:4096:U32_MAX"
u64s 17 type inode_v3 0:4096:U32_MAX len 0 ver 0:   mode=40755
  flags= (16300000)
  journal_seq=9
  ...

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
---
 c_src/bcachefs.c             |   4 +-
 c_src/cmd_debug.c            |  38 ++++++++++++
 c_src/cmds.h                 |   2 +
 src/bcachefs.rs              |   1 +
 src/commands/debug/mod.rs    | 108 +++++++++++++++++++++++++++++++++++
 src/commands/debug/parser.rs |  57 ++++++++++++++++++
 src/commands/mod.rs          |   1 +
 7 files changed, 210 insertions(+), 1 deletion(-)
 create mode 100644 c_src/cmd_debug.c
 create mode 100644 src/commands/debug/parser.rs

diff --git a/c_src/bcachefs.c b/c_src/bcachefs.c
index c5b61097..311de278 100644
--- a/c_src/bcachefs.c
+++ b/c_src/bcachefs.c
@@ -86,6 +86,7 @@ void bcachefs_usage(void)
 	     "\n"
 	     "Debug:\n"
 	     "These commands work on offline, unmounted filesystems\n"
+	     "  debug                    Operate directly on the underlying btrees of a filesystem\n"
 	     "  dump                     Dump filesystem metadata to a qcow2 image\n"
 	     "  list                     List filesystem metadata in textual form\n"
 	     "  list_journal             List contents of journal\n"
@@ -94,7 +95,8 @@ void bcachefs_usage(void)
 	     "  fusemount                Mount a filesystem via FUSE\n"
 	     "\n"
 	     "Miscellaneous:\n"
-         "  completions              Generate shell completions\n"
+	     "  completions              Generate shell completions\n"
+	     "  list_bkeys               List all bkey types known to the current bcachefs version\n"
 	     "  version                  Display the version of the invoked bcachefs tool\n");
 }
 
diff --git a/c_src/cmd_debug.c b/c_src/cmd_debug.c
new file mode 100644
index 00000000..73ba3995
--- /dev/null
+++ b/c_src/cmd_debug.c
@@ -0,0 +1,38 @@
+#include <stdio.h>
+
+#include "libbcachefs/bkey_types.h"
+#include "libbcachefs/btree_update.h"
+#include "libbcachefs/printbuf.h"
+
+#include "cmds.h"
+
+int cmd_dump_bkey(struct bch_fs *c, enum btree_id id, struct bpos pos)
+{
+	struct btree_trans *trans = bch2_trans_get(c);
+	struct btree_iter iter = { NULL };
+	struct printbuf buf = PRINTBUF;
+	int ret = 0;
+
+	bch2_trans_iter_init(trans, &iter, id, pos, BTREE_ITER_all_snapshots);
+
+	struct bkey_s_c k = bch2_btree_iter_peek(&iter);
+	if ((ret = bkey_err(k))) {
+		fprintf(stderr, "bch2_btree_iter_peek() failed: %s\n", bch2_err_str(ret));
+		goto out;
+	}
+	if (!k.k || !bpos_eq(pos, k.k->p)) {
+		bch2_bpos_to_text(&buf, pos);
+		printf("no key at pos %s\n", buf.buf);
+		ret = 1;
+		goto out;
+	}
+
+	bch2_bkey_val_to_text(&buf, c, k);
+	printf("%s\n", buf.buf);
+
+out:
+	bch2_trans_iter_exit(trans, &iter);
+	bch2_trans_put(trans);
+
+	return ret;
+}
diff --git a/c_src/cmds.h b/c_src/cmds.h
index 64267dc4..d55a1440 100644
--- a/c_src/cmds.h
+++ b/c_src/cmds.h
@@ -54,6 +54,8 @@ int cmd_subvolume_snapshot(int argc, char *argv[]);
 
 int cmd_fusemount(int argc, char *argv[]);
 
+int cmd_dump_bkey(struct bch_fs *, enum btree_id, struct bpos);
+
 void bcachefs_usage(void);
 int device_cmds(int argc, char *argv[]);
 int fs_cmds(int argc, char *argv[]);
diff --git a/src/bcachefs.rs b/src/bcachefs.rs
index 4b8cef49..0087334d 100644
--- a/src/bcachefs.rs
+++ b/src/bcachefs.rs
@@ -102,6 +102,7 @@ fn main() -> ExitCode {
     };
 
     match cmd {
+        "debug" => commands::debug(args[1..].to_vec()).report(),
         "completions" => {
             commands::completions(args[1..].to_vec());
             ExitCode::SUCCESS
diff --git a/src/commands/debug/mod.rs b/src/commands/debug/mod.rs
index 30ffd16b..31b23c7e 100644
--- a/src/commands/debug/mod.rs
+++ b/src/commands/debug/mod.rs
@@ -1,7 +1,115 @@
+use clap::Parser;
+use std::io::{BufRead, Write};
+
+use bch_bindgen::bcachefs;
+use bch_bindgen::c;
+use bch_bindgen::fs::Fs;
+
 mod bkey_types;
+mod parser;
+
+use bch_bindgen::c::bpos;
 
 use anyhow::Result;
 
+/// Debug a bcachefs filesystem.
+#[derive(Parser, Debug)]
+pub struct Cli {
+    #[arg(required(true))]
+    devices: Vec<std::path::PathBuf>,
+
+    #[arg(short, long)]
+    command: Option<String>,
+}
+
+#[derive(Debug)]
+enum DebugCommand {
+    Dump(DumpCommand),
+}
+
+#[derive(Debug)]
+struct DumpCommand {
+    btree: String,
+    bpos: bpos,
+}
+
+fn dump(fs: &Fs, cmd: DumpCommand) {
+    let id: bch_bindgen::c::btree_id = match cmd.btree.parse() {
+        Ok(b) => b,
+        Err(_) => {
+            eprintln!("unknown btree '{}'", cmd.btree);
+            return;
+        }
+    };
+
+    unsafe {
+        c::cmd_dump_bkey(fs.raw, id, cmd.bpos);
+    }
+}
+
+fn usage() {
+    println!("Usage:");
+    println!("    dump <btree_type> <bpos>");
+}
+
+fn do_command(fs: &Fs, cmd: &str) -> i32 {
+    match parser::parse_command(cmd) {
+        Ok(cmd) => {
+            match cmd {
+                DebugCommand::Dump(cmd) => dump(fs, cmd),
+            };
+
+            0
+        }
+        Err(e) => {
+            println!("{e}");
+            usage();
+
+            1
+        }
+    }
+}
+
+pub fn debug(argv: Vec<String>) -> Result<()> {
+    fn prompt() {
+        print!("bcachefs> ");
+        std::io::stdout().flush().unwrap();
+    }
+
+    let opt = Cli::parse_from(argv);
+    let fs_opts: bcachefs::bch_opts = Default::default();
+
+    if let Some(cmd) = opt.command {
+        return match parser::parse_command(&cmd) {
+            Ok(cmd) => {
+                let fs = Fs::open(&opt.devices, fs_opts)?;
+                match cmd {
+                    DebugCommand::Dump(cmd) => dump(&fs, cmd),
+                }
+
+                Ok(())
+            }
+            Err(e) => {
+                println!("{e}");
+                usage();
+
+                Ok(())
+            }
+        };
+    }
+
+    let fs = Fs::open(&opt.devices, fs_opts)?;
+
+    prompt();
+    let stdin = std::io::stdin();
+    for line in stdin.lock().lines() {
+        do_command(&fs, &line.unwrap());
+        prompt();
+    }
+
+    Ok(())
+}
+
 pub fn list_bkeys() -> Result<()> {
     print!("{}", bkey_types::get_bkey_type_info()?);
 
diff --git a/src/commands/debug/parser.rs b/src/commands/debug/parser.rs
new file mode 100644
index 00000000..fa036447
--- /dev/null
+++ b/src/commands/debug/parser.rs
@@ -0,0 +1,57 @@
+use nom::branch::alt;
+use nom::bytes::complete::tag;
+use nom::character::complete::{alpha1, char, space1, u32, u64};
+use nom::combinator::{all_consuming, value};
+use nom::sequence::tuple;
+use nom::IResult;
+
+use bch_bindgen::c::bpos;
+
+use crate::commands::debug::{DebugCommand, DumpCommand};
+
+fn parse_bpos(input: &str) -> IResult<&str, bpos> {
+    let (input, (inode, _, offset, _, snapshot)) = tuple((
+        u64,
+        char(':'),
+        u64,
+        char(':'),
+        alt((u32, value(u32::MAX, tag("U32_MAX")))),
+    ))(input)?;
+
+    Ok((
+        input,
+        bpos {
+            inode,
+            offset,
+            snapshot,
+        },
+    ))
+}
+
+fn parse_dump_cmd(input: &str) -> IResult<&str, DebugCommand> {
+    let (input, (_, btree, _, bpos)) =
+        all_consuming(tuple((space1, alpha1, space1, parse_bpos)))(input)?;
+
+    Ok((
+        input,
+        DebugCommand::Dump(DumpCommand {
+            btree: btree.to_string(),
+            bpos,
+        }),
+    ))
+}
+
+fn parse_command_inner(input: &str) -> IResult<&str, DebugCommand> {
+    let (input, _) = tag("dump")(input)?;
+
+    parse_dump_cmd(input)
+}
+
+/// Given an input string, tries to parse it into a valid
+/// command to the debug tool.
+pub fn parse_command(input: &str) -> anyhow::Result<DebugCommand> {
+    match parse_command_inner(input) {
+        Ok((_, c)) => Ok(c),
+        Err(e) => Err(anyhow::anyhow!("{e}")),
+    }
+}
diff --git a/src/commands/mod.rs b/src/commands/mod.rs
index 9365f981..425e0849 100644
--- a/src/commands/mod.rs
+++ b/src/commands/mod.rs
@@ -7,6 +7,7 @@ pub mod mount;
 pub mod subvolume;
 
 pub use completions::completions;
+pub use debug::debug;
 pub use debug::list_bkeys;
 pub use list::list;
 pub use mount::mount;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH TOOLS v2 5/5] introduce new "debug update" command
  2024-07-14 20:02 [PATCH TOOLS v2 0/5] new debug command Thomas Bertschinger
                   ` (3 preceding siblings ...)
  2024-07-14 20:02 ` [PATCH TOOLS v2 4/5] introduce "debug" command and "dump" subcommand Thomas Bertschinger
@ 2024-07-14 20:02 ` Thomas Bertschinger
  2024-07-14 20:21 ` [PATCH TOOLS v2 0/5] new debug command Kent Overstreet
  5 siblings, 0 replies; 9+ messages in thread
From: Thomas Bertschinger @ 2024-07-14 20:02 UTC (permalink / raw)
  To: kent.overstreet, linux-bcachefs, bfoster; +Cc: Thomas Bertschinger

This introduces a new subcommand, "update", which is used to update a
given field of a key to a value. For example:

$ bcachefs debug ~/test-img -c "update inodes 0:4096:U32_MAX bch_inode_unpacked.bi_nlink=35"

$ bcachefs debug ~/test-img -c "dump inodes 0:4096:U32_MAX" | grep nlink
  bi_nlink=35

Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
---
 c_src/cmd_debug.c                | 107 +++++++++++++++++++++++++++++++
 c_src/cmds.h                     |  16 +++++
 src/commands/debug/bkey_types.rs |  20 ++++++
 src/commands/debug/mod.rs        |  62 +++++++++++++++++-
 src/commands/debug/parser.rs     |  58 +++++++++++++++--
 5 files changed, 255 insertions(+), 8 deletions(-)

diff --git a/c_src/cmd_debug.c b/c_src/cmd_debug.c
index 73ba3995..9eec1ddb 100644
--- a/c_src/cmd_debug.c
+++ b/c_src/cmd_debug.c
@@ -3,9 +3,41 @@
 #include "libbcachefs/bkey_types.h"
 #include "libbcachefs/btree_update.h"
 #include "libbcachefs/printbuf.h"
+#include "libbcachefs/inode.h"
 
 #include "cmds.h"
 
+void write_field(enum bkey_update_op op, void *base, u64 size, u64 offset,
+		 u64 value)
+{
+#define x(_size, _bits)								\
+	u##_bits *field_##_bits;						\
+	case _size:								\
+		field_##_bits = (u##_bits *) ((u8 *)base + offset);		\
+		switch (op) {							\
+		case BKEY_CMD_SET:						\
+			*field_##_bits = (u##_bits) value;			\
+			break;							\
+		case BKEY_CMD_ADD:						\
+			*field_##_bits += (u##_bits) value;			\
+			break;							\
+		default:							\
+			fprintf(stderr, "invalid operation: %d\n", op);		\
+			break;							\
+		}								\
+		break;
+
+	switch (size) {
+		x(1, 8)
+		x(2, 16)
+		x(4, 32)
+		x(8, 64)
+	default:
+		fprintf(stderr, "invalid size: %llu\n", size);
+	}
+#undef x
+}
+
 int cmd_dump_bkey(struct bch_fs *c, enum btree_id id, struct bpos pos)
 {
 	struct btree_trans *trans = bch2_trans_get(c);
@@ -36,3 +68,78 @@ out:
 
 	return ret;
 }
+
+int cmd_update_bkey(struct bch_fs *c, struct bkey_update u, struct bpos pos)
+{
+	struct btree_trans *trans = bch2_trans_get(c);
+	struct btree_iter iter = { NULL };
+	struct printbuf buf = PRINTBUF;
+	int ret = 0;
+
+	set_bit(BCH_FS_no_invalid_checks, &c->flags);
+
+	bch2_trans_iter_init(trans, &iter, u.id, pos, BTREE_ITER_all_snapshots);
+
+	struct bkey_s_c k = bch2_btree_iter_peek(&iter);
+	if ((ret = bkey_err(k))) {
+		fprintf(stderr, "bch2_btree_iter_peek() failed: %s\n", bch2_err_str(ret));
+		goto out;
+	}
+	if (!k.k || !bpos_eq(pos, k.k->p)) {
+		bch2_bpos_to_text(&buf, pos);
+		printf("no key at pos %s\n", buf.buf);
+		ret = 1;
+		goto out;
+	}
+
+	if (u.inode_unpacked) {
+		if (k.k->type != KEY_TYPE_inode_v2 && k.k->type != KEY_TYPE_inode_v3) {
+			fprintf(stderr, "Wanted bch_inode_unpacked, got 'bch_%s'\n",
+				bch2_bkey_types[k.k->type]);
+			goto out;
+		}
+
+		struct bch_inode_unpacked inode;
+		ret = bch2_inode_unpack(k, &inode);
+		if (ret != 0) {
+			fprintf(stderr, "bch2_inode_unpack() failed: %s\n", bch2_err_str(ret));
+			goto out;
+		}
+
+		write_field(u.op, &inode, u.size, u.offset, u.value);
+
+		ret = bch2_inode_write(trans, &iter, &inode) ?:
+		      bch2_trans_commit(trans, NULL, NULL, 0);
+		if (ret != 0) {
+			fprintf(stderr, "inode update failed: %s\n", bch2_err_str(ret));
+		}
+	} else {
+		if (u.bkey != k.k->type) {
+			fprintf(stderr, "Wanted type 'bch_%s', got type 'bch_%s'\n",
+				bch2_bkey_types[u.bkey], bch2_bkey_types[k.k->type]);
+			goto out;
+		}
+
+		bch2_trans_unlock(trans);
+
+		struct bkey_i *n = bch2_bkey_make_mut_noupdate(trans, k);
+		if ((ret = PTR_ERR_OR_ZERO(n))) {
+			fprintf(stderr, "bch2_bkey_make_mut_noupdate() failed: %s\n",
+				bch2_err_str(ret));
+			goto out;
+		}
+
+		write_field(u.op, &n->v, u.size, u.offset, u.value);
+
+		ret = bch2_btree_insert(c, u.id, n, NULL, 0, 0);
+		if (ret != 0) {
+			fprintf(stderr, "bch2_btree_insert() failed: %s\n", bch2_err_str(ret));
+		}
+	}
+
+out:
+	bch2_trans_iter_exit(trans, &iter);
+	bch2_trans_put(trans);
+
+	return ret;
+}
diff --git a/c_src/cmds.h b/c_src/cmds.h
index d55a1440..8e744e3f 100644
--- a/c_src/cmds.h
+++ b/c_src/cmds.h
@@ -9,6 +9,21 @@
 
 #include "tools-util.h"
 
+enum bkey_update_op {
+	BKEY_CMD_SET,
+	BKEY_CMD_ADD,
+};
+
+struct bkey_update {
+	enum btree_id id;
+	enum bch_bkey_type bkey;
+	enum bkey_update_op op;
+	bool inode_unpacked;
+	u64 offset;
+	u64 size;
+	u64 value;
+};
+
 int cmd_format(int argc, char *argv[]);
 int cmd_show_super(int argc, char *argv[]);
 int cmd_reset_counters(int argc, char *argv[]);
@@ -55,6 +70,7 @@ int cmd_subvolume_snapshot(int argc, char *argv[]);
 int cmd_fusemount(int argc, char *argv[]);
 
 int cmd_dump_bkey(struct bch_fs *, enum btree_id, struct bpos);
+int cmd_update_bkey(struct bch_fs *, struct bkey_update, struct bpos);
 
 void bcachefs_usage(void);
 int device_cmds(int argc, char *argv[]);
diff --git a/src/commands/debug/bkey_types.rs b/src/commands/debug/bkey_types.rs
index 680d4410..9bb39669 100644
--- a/src/commands/debug/bkey_types.rs
+++ b/src/commands/debug/bkey_types.rs
@@ -13,6 +13,15 @@ impl BkeyTypes {
     pub fn new() -> Self {
         BkeyTypes(Vec::new())
     }
+
+    /// Given a struct name and a member name, return the size and offset of
+    /// the member within the struct, or None if it does not exist.
+    pub fn get_member_layout(&self, outer: &str, member: &str) -> Option<(u64, u64)> {
+        self.0
+            .iter()
+            .find(|i| i.name == *outer)
+            .and_then(|i| i.member_layout(member))
+    }
 }
 
 impl std::fmt::Display for BkeyTypes {
@@ -39,6 +48,17 @@ pub struct BchStruct {
     pub members: Vec<BchMember>,
 }
 
+impl BchStruct {
+    /// Given a struct member name, return the size and offset of the member
+    /// within its parent, or None if there is no member with the given name.
+    pub fn member_layout(&self, name: &str) -> Option<(u64, u64)> {
+        self.members
+            .iter()
+            .find(|i| i.name == *name)
+            .map(|i| (i.size, i.offset))
+    }
+}
+
 /// The representation of a struct member. We need its name, size, and offset
 /// within the parent struct.
 #[derive(Debug)]
diff --git a/src/commands/debug/mod.rs b/src/commands/debug/mod.rs
index 31b23c7e..813b80d5 100644
--- a/src/commands/debug/mod.rs
+++ b/src/commands/debug/mod.rs
@@ -8,7 +8,7 @@ use bch_bindgen::fs::Fs;
 mod bkey_types;
 mod parser;
 
-use bch_bindgen::c::bpos;
+use bch_bindgen::c::{bkey_update_op, bpos};
 
 use anyhow::Result;
 
@@ -25,6 +25,7 @@ pub struct Cli {
 #[derive(Debug)]
 enum DebugCommand {
     Dump(DumpCommand),
+    Update(UpdateCommand),
 }
 
 #[derive(Debug)]
@@ -33,6 +34,57 @@ struct DumpCommand {
     bpos: bpos,
 }
 
+#[derive(Debug)]
+struct UpdateCommand {
+    btree: String,
+    bpos: bpos,
+    bkey: String,
+    field: String,
+    op: bkey_update_op,
+    value: u64,
+}
+
+fn update(fs: &Fs, type_list: &bkey_types::BkeyTypes, cmd: UpdateCommand) {
+    let id: bch_bindgen::c::btree_id = match cmd.btree.parse() {
+        Ok(b) => b,
+        Err(_) => {
+            eprintln!("unknown btree '{}'", cmd.btree);
+            return;
+        }
+    };
+
+    let (bkey, inode_unpacked) = if cmd.bkey == "bch_inode_unpacked" {
+        (c::bch_bkey_type::KEY_TYPE_MAX, true)
+    } else {
+        let bkey = match cmd.bkey["bch_".len()..].parse() {
+            Ok(k) => k,
+            Err(_) => {
+                eprintln!("unknown bkey type '{}'", cmd.bkey);
+                return;
+            }
+        };
+
+        (bkey, false)
+    };
+
+    if let Some((size, offset)) = type_list.get_member_layout(&cmd.bkey, &cmd.field) {
+        let update = c::bkey_update {
+            id,
+            bkey,
+            op: cmd.op,
+            inode_unpacked,
+            offset,
+            size,
+            value: cmd.value,
+        };
+        unsafe {
+            c::cmd_update_bkey(fs.raw, update, cmd.bpos);
+        }
+    } else {
+        println!("unknown field '{}'", cmd.field);
+    }
+}
+
 fn dump(fs: &Fs, cmd: DumpCommand) {
     let id: bch_bindgen::c::btree_id = match cmd.btree.parse() {
         Ok(b) => b,
@@ -50,13 +102,15 @@ fn dump(fs: &Fs, cmd: DumpCommand) {
 fn usage() {
     println!("Usage:");
     println!("    dump <btree_type> <bpos>");
+    println!("    update <btree_type> <bpos> <bkey_type>.<field>=<value>");
 }
 
-fn do_command(fs: &Fs, cmd: &str) -> i32 {
+fn do_command(fs: &Fs, type_list: &bkey_types::BkeyTypes, cmd: &str) -> i32 {
     match parser::parse_command(cmd) {
         Ok(cmd) => {
             match cmd {
                 DebugCommand::Dump(cmd) => dump(fs, cmd),
+                DebugCommand::Update(cmd) => update(fs, type_list, cmd),
             };
 
             0
@@ -78,6 +132,7 @@ pub fn debug(argv: Vec<String>) -> Result<()> {
 
     let opt = Cli::parse_from(argv);
     let fs_opts: bcachefs::bch_opts = Default::default();
+    let type_list = bkey_types::get_bkey_type_info()?;
 
     if let Some(cmd) = opt.command {
         return match parser::parse_command(&cmd) {
@@ -85,6 +140,7 @@ pub fn debug(argv: Vec<String>) -> Result<()> {
                 let fs = Fs::open(&opt.devices, fs_opts)?;
                 match cmd {
                     DebugCommand::Dump(cmd) => dump(&fs, cmd),
+                    DebugCommand::Update(cmd) => update(&fs, &type_list, cmd),
                 }
 
                 Ok(())
@@ -103,7 +159,7 @@ pub fn debug(argv: Vec<String>) -> Result<()> {
     prompt();
     let stdin = std::io::stdin();
     for line in stdin.lock().lines() {
-        do_command(&fs, &line.unwrap());
+        do_command(&fs, &type_list, &line.unwrap());
         prompt();
     }
 
diff --git a/src/commands/debug/parser.rs b/src/commands/debug/parser.rs
index fa036447..19adeba7 100644
--- a/src/commands/debug/parser.rs
+++ b/src/commands/debug/parser.rs
@@ -1,13 +1,13 @@
 use nom::branch::alt;
-use nom::bytes::complete::tag;
+use nom::bytes::complete::{tag, take_while};
 use nom::character::complete::{alpha1, char, space1, u32, u64};
 use nom::combinator::{all_consuming, value};
 use nom::sequence::tuple;
 use nom::IResult;
 
-use bch_bindgen::c::bpos;
+use bch_bindgen::c::{bkey_update_op, bpos};
 
-use crate::commands::debug::{DebugCommand, DumpCommand};
+use crate::commands::debug::{DebugCommand, DumpCommand, UpdateCommand};
 
 fn parse_bpos(input: &str) -> IResult<&str, bpos> {
     let (input, (inode, _, offset, _, snapshot)) = tuple((
@@ -41,10 +41,58 @@ fn parse_dump_cmd(input: &str) -> IResult<&str, DebugCommand> {
     ))
 }
 
+fn bkey_name(input: &str) -> IResult<&str, &str> {
+    take_while(|c: char| c.is_alphanumeric() || c == '_')(input)
+}
+
+fn field_name(input: &str) -> IResult<&str, &str> {
+    take_while(|c: char| c.is_alphanumeric() || c == '_' || c == '.')(input)
+}
+
+fn bkey_op(input: &str) -> IResult<&str, bkey_update_op> {
+    let (input, op) = alt((tag("="), tag("+=")))(input)?;
+    match op {
+        "=" => Ok((input, bkey_update_op::BKEY_CMD_SET)),
+        "+=" => Ok((input, bkey_update_op::BKEY_CMD_ADD)),
+        _ => unreachable!(),
+    }
+}
+
+fn parse_update_cmd(input: &str) -> IResult<&str, DebugCommand> {
+    let (input, (_, btree, _, bpos, _, bkey, _, field, op, value)) = all_consuming(tuple((
+        space1,
+        alpha1,
+        space1,
+        parse_bpos,
+        space1,
+        bkey_name,
+        char('.'),
+        field_name,
+        bkey_op,
+        u64,
+    )))(input)?;
+
+    Ok((
+        input,
+        DebugCommand::Update(UpdateCommand {
+            btree: btree.to_string(),
+            bpos,
+            bkey: bkey.to_string(),
+            field: field.to_string(),
+            op,
+            value,
+        }),
+    ))
+}
+
 fn parse_command_inner(input: &str) -> IResult<&str, DebugCommand> {
-    let (input, _) = tag("dump")(input)?;
+    let (input, cmd) = alt((tag("dump"), tag("update")))(input)?;
 
-    parse_dump_cmd(input)
+    match cmd {
+        "dump" => parse_dump_cmd(input),
+        "update" => parse_update_cmd(input),
+        _ => unreachable!(),
+    }
 }
 
 /// Given an input string, tries to parse it into a valid
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH TOOLS v2 4/5] introduce "debug" command and "dump" subcommand
  2024-07-14 20:02 ` [PATCH TOOLS v2 4/5] introduce "debug" command and "dump" subcommand Thomas Bertschinger
@ 2024-07-14 20:19   ` Kent Overstreet
  0 siblings, 0 replies; 9+ messages in thread
From: Kent Overstreet @ 2024-07-14 20:19 UTC (permalink / raw)
  To: Thomas Bertschinger; +Cc: linux-bcachefs, bfoster

On Sun, Jul 14, 2024 at 02:02:25PM GMT, Thomas Bertschinger wrote:
> This introduces a new command, "debug", that is used for directly
> manipulating bkeys in the underlying btrees.
> 
> It has a subcommand, "dump", which takes a btree and bpos and
> prints the data from that bkey.

But we already have that functionality - the 'list' subcommand...

Did you just want an easy way to print a single key?

> 
> For example:
> 
> $ bcachefs debug ~/test-img -c "dump inodes 0:4096:U32_MAX"
> u64s 17 type inode_v3 0:4096:U32_MAX len 0 ver 0:   mode=40755
>   flags= (16300000)
>   journal_seq=9
>   ...
> 
> Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
> ---
>  c_src/bcachefs.c             |   4 +-
>  c_src/cmd_debug.c            |  38 ++++++++++++
>  c_src/cmds.h                 |   2 +
>  src/bcachefs.rs              |   1 +
>  src/commands/debug/mod.rs    | 108 +++++++++++++++++++++++++++++++++++
>  src/commands/debug/parser.rs |  57 ++++++++++++++++++
>  src/commands/mod.rs          |   1 +
>  7 files changed, 210 insertions(+), 1 deletion(-)
>  create mode 100644 c_src/cmd_debug.c
>  create mode 100644 src/commands/debug/parser.rs
> 
> diff --git a/c_src/bcachefs.c b/c_src/bcachefs.c
> index c5b61097..311de278 100644
> --- a/c_src/bcachefs.c
> +++ b/c_src/bcachefs.c
> @@ -86,6 +86,7 @@ void bcachefs_usage(void)
>  	     "\n"
>  	     "Debug:\n"
>  	     "These commands work on offline, unmounted filesystems\n"
> +	     "  debug                    Operate directly on the underlying btrees of a filesystem\n"
>  	     "  dump                     Dump filesystem metadata to a qcow2 image\n"
>  	     "  list                     List filesystem metadata in textual form\n"
>  	     "  list_journal             List contents of journal\n"
> @@ -94,7 +95,8 @@ void bcachefs_usage(void)
>  	     "  fusemount                Mount a filesystem via FUSE\n"
>  	     "\n"
>  	     "Miscellaneous:\n"
> -         "  completions              Generate shell completions\n"
> +	     "  completions              Generate shell completions\n"
> +	     "  list_bkeys               List all bkey types known to the current bcachefs version\n"
>  	     "  version                  Display the version of the invoked bcachefs tool\n");
>  }
>  
> diff --git a/c_src/cmd_debug.c b/c_src/cmd_debug.c
> new file mode 100644
> index 00000000..73ba3995
> --- /dev/null
> +++ b/c_src/cmd_debug.c
> @@ -0,0 +1,38 @@
> +#include <stdio.h>
> +
> +#include "libbcachefs/bkey_types.h"
> +#include "libbcachefs/btree_update.h"
> +#include "libbcachefs/printbuf.h"
> +
> +#include "cmds.h"
> +
> +int cmd_dump_bkey(struct bch_fs *c, enum btree_id id, struct bpos pos)
> +{
> +	struct btree_trans *trans = bch2_trans_get(c);
> +	struct btree_iter iter = { NULL };
> +	struct printbuf buf = PRINTBUF;
> +	int ret = 0;
> +
> +	bch2_trans_iter_init(trans, &iter, id, pos, BTREE_ITER_all_snapshots);
> +
> +	struct bkey_s_c k = bch2_btree_iter_peek(&iter);
> +	if ((ret = bkey_err(k))) {
> +		fprintf(stderr, "bch2_btree_iter_peek() failed: %s\n", bch2_err_str(ret));
> +		goto out;
> +	}
> +	if (!k.k || !bpos_eq(pos, k.k->p)) {
> +		bch2_bpos_to_text(&buf, pos);
> +		printf("no key at pos %s\n", buf.buf);
> +		ret = 1;
> +		goto out;
> +	}
> +
> +	bch2_bkey_val_to_text(&buf, c, k);
> +	printf("%s\n", buf.buf);
> +
> +out:
> +	bch2_trans_iter_exit(trans, &iter);
> +	bch2_trans_put(trans);
> +
> +	return ret;
> +}
> diff --git a/c_src/cmds.h b/c_src/cmds.h
> index 64267dc4..d55a1440 100644
> --- a/c_src/cmds.h
> +++ b/c_src/cmds.h
> @@ -54,6 +54,8 @@ int cmd_subvolume_snapshot(int argc, char *argv[]);
>  
>  int cmd_fusemount(int argc, char *argv[]);
>  
> +int cmd_dump_bkey(struct bch_fs *, enum btree_id, struct bpos);
> +
>  void bcachefs_usage(void);
>  int device_cmds(int argc, char *argv[]);
>  int fs_cmds(int argc, char *argv[]);
> diff --git a/src/bcachefs.rs b/src/bcachefs.rs
> index 4b8cef49..0087334d 100644
> --- a/src/bcachefs.rs
> +++ b/src/bcachefs.rs
> @@ -102,6 +102,7 @@ fn main() -> ExitCode {
>      };
>  
>      match cmd {
> +        "debug" => commands::debug(args[1..].to_vec()).report(),
>          "completions" => {
>              commands::completions(args[1..].to_vec());
>              ExitCode::SUCCESS
> diff --git a/src/commands/debug/mod.rs b/src/commands/debug/mod.rs
> index 30ffd16b..31b23c7e 100644
> --- a/src/commands/debug/mod.rs
> +++ b/src/commands/debug/mod.rs
> @@ -1,7 +1,115 @@
> +use clap::Parser;
> +use std::io::{BufRead, Write};
> +
> +use bch_bindgen::bcachefs;
> +use bch_bindgen::c;
> +use bch_bindgen::fs::Fs;
> +
>  mod bkey_types;
> +mod parser;
> +
> +use bch_bindgen::c::bpos;
>  
>  use anyhow::Result;
>  
> +/// Debug a bcachefs filesystem.
> +#[derive(Parser, Debug)]
> +pub struct Cli {
> +    #[arg(required(true))]
> +    devices: Vec<std::path::PathBuf>,
> +
> +    #[arg(short, long)]
> +    command: Option<String>,
> +}
> +
> +#[derive(Debug)]
> +enum DebugCommand {
> +    Dump(DumpCommand),
> +}
> +
> +#[derive(Debug)]
> +struct DumpCommand {
> +    btree: String,
> +    bpos: bpos,
> +}
> +
> +fn dump(fs: &Fs, cmd: DumpCommand) {
> +    let id: bch_bindgen::c::btree_id = match cmd.btree.parse() {
> +        Ok(b) => b,
> +        Err(_) => {
> +            eprintln!("unknown btree '{}'", cmd.btree);
> +            return;
> +        }
> +    };
> +
> +    unsafe {
> +        c::cmd_dump_bkey(fs.raw, id, cmd.bpos);
> +    }
> +}
> +
> +fn usage() {
> +    println!("Usage:");
> +    println!("    dump <btree_type> <bpos>");
> +}
> +
> +fn do_command(fs: &Fs, cmd: &str) -> i32 {
> +    match parser::parse_command(cmd) {
> +        Ok(cmd) => {
> +            match cmd {
> +                DebugCommand::Dump(cmd) => dump(fs, cmd),
> +            };
> +
> +            0
> +        }
> +        Err(e) => {
> +            println!("{e}");
> +            usage();
> +
> +            1
> +        }
> +    }
> +}
> +
> +pub fn debug(argv: Vec<String>) -> Result<()> {
> +    fn prompt() {
> +        print!("bcachefs> ");
> +        std::io::stdout().flush().unwrap();
> +    }
> +
> +    let opt = Cli::parse_from(argv);
> +    let fs_opts: bcachefs::bch_opts = Default::default();
> +
> +    if let Some(cmd) = opt.command {
> +        return match parser::parse_command(&cmd) {
> +            Ok(cmd) => {
> +                let fs = Fs::open(&opt.devices, fs_opts)?;
> +                match cmd {
> +                    DebugCommand::Dump(cmd) => dump(&fs, cmd),
> +                }
> +
> +                Ok(())
> +            }
> +            Err(e) => {
> +                println!("{e}");
> +                usage();
> +
> +                Ok(())
> +            }
> +        };
> +    }
> +
> +    let fs = Fs::open(&opt.devices, fs_opts)?;
> +
> +    prompt();
> +    let stdin = std::io::stdin();
> +    for line in stdin.lock().lines() {
> +        do_command(&fs, &line.unwrap());
> +        prompt();
> +    }
> +
> +    Ok(())
> +}
> +
>  pub fn list_bkeys() -> Result<()> {
>      print!("{}", bkey_types::get_bkey_type_info()?);
>  
> diff --git a/src/commands/debug/parser.rs b/src/commands/debug/parser.rs
> new file mode 100644
> index 00000000..fa036447
> --- /dev/null
> +++ b/src/commands/debug/parser.rs
> @@ -0,0 +1,57 @@
> +use nom::branch::alt;
> +use nom::bytes::complete::tag;
> +use nom::character::complete::{alpha1, char, space1, u32, u64};
> +use nom::combinator::{all_consuming, value};
> +use nom::sequence::tuple;
> +use nom::IResult;
> +
> +use bch_bindgen::c::bpos;
> +
> +use crate::commands::debug::{DebugCommand, DumpCommand};
> +
> +fn parse_bpos(input: &str) -> IResult<&str, bpos> {
> +    let (input, (inode, _, offset, _, snapshot)) = tuple((
> +        u64,
> +        char(':'),
> +        u64,
> +        char(':'),
> +        alt((u32, value(u32::MAX, tag("U32_MAX")))),
> +    ))(input)?;
> +
> +    Ok((
> +        input,
> +        bpos {
> +            inode,
> +            offset,
> +            snapshot,
> +        },
> +    ))
> +}
> +
> +fn parse_dump_cmd(input: &str) -> IResult<&str, DebugCommand> {
> +    let (input, (_, btree, _, bpos)) =
> +        all_consuming(tuple((space1, alpha1, space1, parse_bpos)))(input)?;
> +
> +    Ok((
> +        input,
> +        DebugCommand::Dump(DumpCommand {
> +            btree: btree.to_string(),
> +            bpos,
> +        }),
> +    ))
> +}
> +
> +fn parse_command_inner(input: &str) -> IResult<&str, DebugCommand> {
> +    let (input, _) = tag("dump")(input)?;
> +
> +    parse_dump_cmd(input)
> +}
> +
> +/// Given an input string, tries to parse it into a valid
> +/// command to the debug tool.
> +pub fn parse_command(input: &str) -> anyhow::Result<DebugCommand> {
> +    match parse_command_inner(input) {
> +        Ok((_, c)) => Ok(c),
> +        Err(e) => Err(anyhow::anyhow!("{e}")),
> +    }
> +}
> diff --git a/src/commands/mod.rs b/src/commands/mod.rs
> index 9365f981..425e0849 100644
> --- a/src/commands/mod.rs
> +++ b/src/commands/mod.rs
> @@ -7,6 +7,7 @@ pub mod mount;
>  pub mod subvolume;
>  
>  pub use completions::completions;
> +pub use debug::debug;
>  pub use debug::list_bkeys;
>  pub use list::list;
>  pub use mount::mount;
> -- 
> 2.45.2
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH TOOLS v2 1/5] include debuginfo in bcachefs binary by default
  2024-07-14 20:02 ` [PATCH TOOLS v2 1/5] include debuginfo in bcachefs binary by default Thomas Bertschinger
@ 2024-07-14 20:20   ` Kent Overstreet
  0 siblings, 0 replies; 9+ messages in thread
From: Kent Overstreet @ 2024-07-14 20:20 UTC (permalink / raw)
  To: Thomas Bertschinger; +Cc: linux-bcachefs, bfoster

On Sun, Jul 14, 2024 at 02:02:22PM GMT, Thomas Bertschinger wrote:
> The debuginfo is used by the "bcachefs debug" and "bcachefs list_bkeys"
> commands.
> 
> Rust 1.77 [1] changed Cargo's release profile to strip debuginfo by default,
> but we always want it included.

Yes please, people who strip debug info should be tarred and feathered
:)

> [1] https://github.com/rust-lang/cargo/pull/13257
> 
> Signed-off-by: Thomas Bertschinger <tahbertschinger@gmail.com>
> ---
>  Cargo.toml | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/Cargo.toml b/Cargo.toml
> index 9d1756fd..d56d6272 100644
> --- a/Cargo.toml
> +++ b/Cargo.toml
> @@ -30,3 +30,6 @@ zeroize = { version = "1", features = ["std", "zeroize_derive"] }
>  version = "0.10"
>  default-features = false
>  features = ["auto-color"]
> +
> +[profile.release]
> +strip = "none"
> -- 
> 2.45.2
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH TOOLS v2 0/5] new debug command
  2024-07-14 20:02 [PATCH TOOLS v2 0/5] new debug command Thomas Bertschinger
                   ` (4 preceding siblings ...)
  2024-07-14 20:02 ` [PATCH TOOLS v2 5/5] introduce new "debug update" command Thomas Bertschinger
@ 2024-07-14 20:21 ` Kent Overstreet
  5 siblings, 0 replies; 9+ messages in thread
From: Kent Overstreet @ 2024-07-14 20:21 UTC (permalink / raw)
  To: Thomas Bertschinger; +Cc: linux-bcachefs, bfoster

On Sun, Jul 14, 2024 at 02:02:21PM GMT, Thomas Bertschinger wrote:
> This introduces a new command, "debug", to the bcachefs tool.

Background: this is what will let us do comprehensive error injection on
our on disk images and rigorously test our repair paths.

Thanks Thomas!

> 
> Changes in v2:
> - minor fixups
> - added "field+=value" to increment a field's value, in addition to
>   "field=value"
> 
> Thomas Bertschinger (5):
>   include debuginfo in bcachefs binary by default
>   update minimum Rust version to 1.74.0
>   introduce "list_bkeys" command
>   introduce "debug" command and "dump" subcommand
>   introduce new "debug update" command
> 
>  Cargo.lock                       | 374 ++++++++++++++++++++++---------
>  Cargo.toml                       |   9 +-
>  c_src/bcachefs.c                 |   4 +-
>  c_src/cmd_debug.c                | 145 ++++++++++++
>  c_src/cmds.h                     |  18 ++
>  src/bcachefs.rs                  |   5 +-
>  src/commands/debug/bkey_types.rs | 340 ++++++++++++++++++++++++++++
>  src/commands/debug/mod.rs        | 173 ++++++++++++++
>  src/commands/debug/parser.rs     | 105 +++++++++
>  src/commands/mod.rs              |   3 +
>  10 files changed, 1061 insertions(+), 115 deletions(-)
>  create mode 100644 c_src/cmd_debug.c
>  create mode 100644 src/commands/debug/bkey_types.rs
>  create mode 100644 src/commands/debug/mod.rs
>  create mode 100644 src/commands/debug/parser.rs
> 
> --
> 2.45.2
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2024-07-14 20:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-14 20:02 [PATCH TOOLS v2 0/5] new debug command Thomas Bertschinger
2024-07-14 20:02 ` [PATCH TOOLS v2 1/5] include debuginfo in bcachefs binary by default Thomas Bertschinger
2024-07-14 20:20   ` Kent Overstreet
2024-07-14 20:02 ` [PATCH TOOLS v2 2/5] update minimum Rust version to 1.74.0 Thomas Bertschinger
2024-07-14 20:02 ` [PATCH TOOLS v2 3/5] introduce "list_bkeys" command Thomas Bertschinger
2024-07-14 20:02 ` [PATCH TOOLS v2 4/5] introduce "debug" command and "dump" subcommand Thomas Bertschinger
2024-07-14 20:19   ` Kent Overstreet
2024-07-14 20:02 ` [PATCH TOOLS v2 5/5] introduce new "debug update" command Thomas Bertschinger
2024-07-14 20:21 ` [PATCH TOOLS v2 0/5] new debug command Kent Overstreet

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox