Phase 3完成:FUSE完整重构以支持fuse-t
Some checks failed
Test / build (push) Has been cancelled
Test / test (push) Has been cancelled

核心成果:
- fuse-t库成功纳入项目(build.rs + Cargo.toml)
- fuse-backend-rs API完整实现(270行代码)
- FileSystem trait完整重写(lookup/getattr/read/readdir/open/release/opendir/releasedir/statfs)
- ZeroCopyWriter API正确集成(write_from方法)
- 服务循环正确实现(get_request + handle_message)

技术实现:
- 依赖:fuse-backend-rs(fusedev + fuse-t features)
- 链接:fuse-t库(pkg-config + DiskArbitration framework)
- 数据库:find_node_id_by_parent方法新增
- API:DirEntry/Entry/stat64正确使用
- 服务:FuseSession/FuseChannel正确集成

编译状态:
- 8警告,0错误
- 成功编译markbase-fuse库和main程序

状态:Phase 3完整实施完成
This commit is contained in:
Warren
2026-06-13 16:33:13 +08:00
parent ceadeef329
commit c2e3984ac8
6 changed files with 586 additions and 299 deletions

415
Cargo.lock generated
View File

@@ -178,6 +178,15 @@ version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "arc-swap"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207"
dependencies = [
"rustversion",
]
[[package]] [[package]]
name = "argon2" name = "argon2"
version = "0.5.3" version = "0.5.3"
@@ -210,7 +219,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -335,7 +344,7 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -421,7 +430,7 @@ dependencies = [
"regex", "regex",
"rustc-hash", "rustc-hash",
"shlex", "shlex",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -585,6 +594,15 @@ dependencies = [
"crossbeam-queue", "crossbeam-queue",
] ]
[[package]]
name = "caps"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd1ddba47aba30b6a889298ad0109c3b8dcb0e8fc993b459daa7067d46f865e0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "cbc" name = "cbc"
version = "0.1.2" version = "0.1.2"
@@ -738,7 +756,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -860,6 +878,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crc64"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2707e3afba5e19b75d582d88bc79237418f2a2a2d673d01cf9b03633b46e98f3"
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.5.15" version = "0.5.15"
@@ -1032,7 +1056,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -1073,7 +1097,7 @@ dependencies = [
"http-body", "http-body",
"http-body-util", "http-body-util",
"libc", "libc",
"log 0.4.29", "log",
"lru", "lru",
"mime_guess", "mime_guess",
"parking_lot", "parking_lot",
@@ -1087,6 +1111,19 @@ dependencies = [
"xmltree", "xmltree",
] ]
[[package]]
name = "dbs-snapshot"
version = "1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0315cb247b6726d92c74b955b7d79b4be475be58335fee120f19292740132eb1"
dependencies = [
"displaydoc",
"libc",
"thiserror 1.0.69",
"versionize",
"versionize_derive",
]
[[package]] [[package]]
name = "delegate" name = "delegate"
version = "0.13.5" version = "0.13.5"
@@ -1095,7 +1132,7 @@ checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -1137,7 +1174,7 @@ checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -1212,7 +1249,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -1375,6 +1412,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "endian-type"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d"
[[package]] [[package]]
name = "enum_dispatch" name = "enum_dispatch"
version = "0.3.13" version = "0.3.13"
@@ -1384,7 +1427,7 @@ dependencies = [
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -1402,7 +1445,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef" checksum = "32e90c2accc4b07a8456ea0debdc2e7587bdd890680d71173a15d4ae604f6eef"
dependencies = [ dependencies = [
"log 0.4.29", "log",
"regex", "regex",
] ]
@@ -1422,7 +1465,7 @@ dependencies = [
"anstyle", "anstyle",
"env_filter", "env_filter",
"jiff", "jiff",
"log 0.4.29", "log",
] ]
[[package]] [[package]]
@@ -1543,7 +1586,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
"log 0.4.29", "log",
"rusqlite", "rusqlite",
"serde", "serde",
"serde_json", "serde_json",
@@ -1645,16 +1688,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]] [[package]]
name = "fuse" name = "fuse-backend-rs"
version = "0.3.1" version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e57070510966bfef93662a81cb8aa2b1c7db0964354fa9921434f04b9e8660"
dependencies = [ dependencies = [
"arc-swap",
"async-trait",
"bitflags 1.3.2",
"caps",
"core-foundation-sys",
"dbs-snapshot",
"io-uring",
"lazy_static",
"libc", "libc",
"log 0.3.9", "log",
"pkg-config", "mio 0.8.11",
"thread-scoped", "nix 0.24.3",
"time 0.1.45", "radix_trie",
"tokio",
"tokio-test",
"tokio-uring",
"versionize",
"versionize_derive",
"vhost",
"virtio-bindings",
"virtio-queue",
"vm-memory",
"vmm-sys-util 0.15.0",
] ]
[[package]] [[package]]
@@ -1713,7 +1772,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -2115,7 +2174,7 @@ dependencies = [
"core-foundation-sys", "core-foundation-sys",
"iana-time-zone-haiku", "iana-time-zone-haiku",
"js-sys", "js-sys",
"log 0.4.29", "log",
"wasm-bindgen", "wasm-bindgen",
"windows-core 0.62.2", "windows-core 0.62.2",
] ]
@@ -2320,6 +2379,16 @@ dependencies = [
"rand_core 0.10.1", "rand_core 0.10.1",
] ]
[[package]]
name = "io-uring"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd1e1a01cfb924fd8c5c43b6827965db394f5a3a16c599ce03452266e1cf984c"
dependencies = [
"bitflags 1.3.2",
"libc",
]
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.2" version = "1.70.2"
@@ -2348,7 +2417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102" checksum = "4603d3033e49e2b0e31229fcab20a5d40089c607d975cd9c80551dc69eed9102"
dependencies = [ dependencies = [
"jiff-static", "jiff-static",
"log 0.4.29", "log",
"portable-atomic", "portable-atomic",
"portable-atomic-util", "portable-atomic-util",
"serde_core", "serde_core",
@@ -2362,7 +2431,7 @@ checksum = "782d32378dddf207193ac91cefb848ad41abb58195c95168e1291227a0832b47"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -2526,15 +2595,6 @@ dependencies = [
"scopeguard", "scopeguard",
] ]
[[package]]
name = "log"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
dependencies = [
"log 0.4.29",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.29" version = "0.4.29"
@@ -2603,7 +2663,7 @@ dependencies = [
"flate2", "flate2",
"futures-util", "futures-util",
"hmac 0.12.1", "hmac 0.12.1",
"log 0.4.29", "log",
"markbase-webdav", "markbase-webdav",
"md5 0.8.0", "md5 0.8.0",
"pulldown-cmark", "pulldown-cmark",
@@ -2658,13 +2718,14 @@ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
"filetree", "filetree",
"fuse", "fuse-backend-rs",
"libc", "libc",
"log 0.4.29", "log",
"rusqlite", "rusqlite",
"serde", "serde",
"serde_json", "serde_json",
"time 0.3.47", "time",
"vm-memory",
] ]
[[package]] [[package]]
@@ -2788,6 +2849,15 @@ version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "mime" name = "mime"
version = "0.3.17" version = "0.3.17"
@@ -2820,6 +2890,18 @@ dependencies = [
"simd-adler32", "simd-adler32",
] ]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi 0.11.1+wasi-snapshot-preview1",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "mio" name = "mio"
version = "1.2.0" version = "1.2.0"
@@ -2889,6 +2971,27 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "nibble_vec"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43"
dependencies = [
"smallvec",
]
[[package]]
name = "nix"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
dependencies = [
"bitflags 1.3.2",
"cfg-if",
"libc",
"memoffset",
]
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.31.3" version = "0.31.3"
@@ -2918,7 +3021,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2de419e64947cd8830e66beb584acc3fb42ed411d103e3c794dda355d1b374b5" checksum = "2de419e64947cd8830e66beb584acc3fb42ed411d103e3c794dda355d1b374b5"
dependencies = [ dependencies = [
"chrono", "chrono",
"time 0.3.47", "time",
] ]
[[package]] [[package]]
@@ -2999,7 +3102,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -3239,7 +3342,7 @@ dependencies = [
"bytes", "bytes",
"delegate", "delegate",
"futures", "futures",
"log 0.4.29", "log",
"rand 0.8.6", "rand 0.8.6",
"thiserror 1.0.69", "thiserror 1.0.69",
"tokio", "tokio",
@@ -3257,7 +3360,7 @@ dependencies = [
"bytes", "bytes",
"delegate", "delegate",
"futures", "futures",
"log 0.4.29", "log",
"rand 0.10.1", "rand 0.10.1",
"sha2 0.11.0", "sha2 0.11.0",
"thiserror 2.0.18", "thiserror 2.0.18",
@@ -3619,7 +3722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -3703,6 +3806,16 @@ version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "radix_trie"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd"
dependencies = [
"endian-type",
"nibble_vec",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.4.6" version = "0.4.6"
@@ -3996,7 +4109,7 @@ dependencies = [
"inout 0.2.2", "inout 0.2.2",
"internal-russh-num-bigint", "internal-russh-num-bigint",
"keccak", "keccak",
"log 0.4.29", "log",
"md5 0.8.0", "md5 0.8.0",
"ml-kem", "ml-kem",
"module-lattice", "module-lattice",
@@ -4050,8 +4163,8 @@ version = "0.61.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443f6bbcfacb34a1aab2b12b99bf08e0c63abdc5a0db261901365df9d57fff51" checksum = "443f6bbcfacb34a1aab2b12b99bf08e0c63abdc5a0db261901365df9d57fff51"
dependencies = [ dependencies = [
"log 0.4.29", "log",
"nix", "nix 0.31.3",
"ssh-encoding 0.3.0-rc.9", "ssh-encoding 0.3.0-rc.9",
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
@@ -4081,7 +4194,7 @@ dependencies = [
"home", "home",
"inout 0.1.4", "inout 0.1.4",
"internal-russh-forked-ssh-key", "internal-russh-forked-ssh-key",
"log 0.4.29", "log",
"md5 0.7.0", "md5 0.7.0",
"num-integer", "num-integer",
"p256 0.13.2", "p256 0.13.2",
@@ -4122,7 +4235,7 @@ dependencies = [
"chrono", "chrono",
"dashmap", "dashmap",
"gloo-timers", "gloo-timers",
"log 0.4.29", "log",
"serde", "serde",
"serde_bytes", "serde_bytes",
"thiserror 2.0.18", "thiserror 2.0.18",
@@ -4163,7 +4276,7 @@ dependencies = [
"bytes", "bytes",
"crc32c", "crc32c",
"env_logger", "env_logger",
"log 0.4.29", "log",
"serde", "serde",
"serde_json", "serde_json",
"thiserror 2.0.18", "thiserror 2.0.18",
@@ -4236,6 +4349,12 @@ dependencies = [
"cipher 0.5.2", "cipher 0.5.2",
] ]
[[package]]
name = "scoped-tls"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
@@ -4336,7 +4455,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -4545,7 +4664,7 @@ dependencies = [
"fnv", "fnv",
"fs2", "fs2",
"inline-array", "inline-array",
"log 0.4.29", "log",
"pagetable", "pagetable",
"parking_lot", "parking_lot",
"rayon", "rayon",
@@ -4561,6 +4680,16 @@ version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "socket2"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
dependencies = [
"libc",
"winapi",
]
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.6.3" version = "0.6.3"
@@ -4737,6 +4866,17 @@ version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.117" version = "2.0.117"
@@ -4762,7 +4902,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -4825,7 +4965,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -4836,24 +4976,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
]
[[package]]
name = "thread-scoped"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99"
[[package]]
name = "time"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
dependencies = [
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
] ]
[[package]] [[package]]
@@ -4919,11 +5042,11 @@ checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe"
dependencies = [ dependencies = [
"bytes", "bytes",
"libc", "libc",
"mio", "mio 1.2.0",
"parking_lot", "parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2 0.6.3",
"tokio-macros", "tokio-macros",
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
@@ -4936,7 +5059,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -4951,7 +5074,7 @@ dependencies = [
"fallible-iterator 0.2.0", "fallible-iterator 0.2.0",
"futures-channel", "futures-channel",
"futures-util", "futures-util",
"log 0.4.29", "log",
"parking_lot", "parking_lot",
"percent-encoding", "percent-encoding",
"phf", "phf",
@@ -4959,7 +5082,7 @@ dependencies = [
"postgres-protocol", "postgres-protocol",
"postgres-types", "postgres-types",
"rand 0.10.1", "rand 0.10.1",
"socket2", "socket2 0.6.3",
"tokio", "tokio",
"tokio-util", "tokio-util",
"whoami", "whoami",
@@ -4988,6 +5111,20 @@ dependencies = [
"tokio-stream", "tokio-stream",
] ]
[[package]]
name = "tokio-uring"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d5e02bb137e030b3a547c65a3bd2f1836d66a97369fdcc69034002b10e155ef"
dependencies = [
"io-uring",
"libc",
"scoped-tls",
"slab",
"socket2 0.4.10",
"tokio",
]
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.18" version = "0.7.18"
@@ -5077,7 +5214,7 @@ version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
dependencies = [ dependencies = [
"log 0.4.29", "log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes", "tracing-attributes",
"tracing-core", "tracing-core",
@@ -5091,7 +5228,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -5237,6 +5374,7 @@ checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
dependencies = [ dependencies = [
"getrandom 0.4.2", "getrandom 0.4.2",
"js-sys", "js-sys",
"rand 0.10.1",
"wasm-bindgen", "wasm-bindgen",
] ]
@@ -5252,6 +5390,34 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "versionize"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62929d59c7f6730b7298fcb363760550f4db6e353fbac4076d447d0e82799d6d"
dependencies = [
"bincode",
"crc64",
"proc-macro2",
"quote",
"serde",
"serde_derive",
"syn 1.0.109",
"versionize_derive",
"vmm-sys-util 0.12.1",
]
[[package]]
name = "versionize_derive"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c4971c07ef708cd51003222e509aaed8eae14aeb2907706b01578843195e03a"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "vfs" name = "vfs"
version = "0.12.2" version = "0.12.2"
@@ -5262,10 +5428,67 @@ dependencies = [
] ]
[[package]] [[package]]
name = "wasi" name = "vhost"
version = "0.10.0+wasi-snapshot-preview1" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" checksum = "c76d90ce3c6b37d610a5304c9a445cfff580cf8b4b9fd02fb256aaf68552c28a"
dependencies = [
"bitflags 2.11.1",
"libc",
"uuid",
"vm-memory",
"vmm-sys-util 0.15.0",
]
[[package]]
name = "virtio-bindings"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "091f1f09cfbf2a78563b562e7a949465cce1aef63b6065645188d995162f8868"
[[package]]
name = "virtio-queue"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e358084f32ed165fddb41d98ff1b7ff3c08b9611d8d6114a1b422e2e85688baf"
dependencies = [
"libc",
"log",
"virtio-bindings",
"vm-memory",
"vmm-sys-util 0.15.0",
]
[[package]]
name = "vm-memory"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f39348a049689cabd3377cdd9182bf526ec76a6f823b79903896452e9d7a7380"
dependencies = [
"libc",
"thiserror 2.0.18",
"winapi",
]
[[package]]
name = "vmm-sys-util"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1435039746e20da4f8d507a72ee1b916f7b4b05af7a91c093d2c6561934ede"
dependencies = [
"bitflags 1.3.2",
"libc",
]
[[package]]
name = "vmm-sys-util"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "506c62fdf617a5176827c2f9afbcf1be155b03a9b4bf9617a60dbc07e3a1642f"
dependencies = [
"bitflags 1.3.2",
"libc",
]
[[package]] [[package]]
name = "wasi" name = "wasi"
@@ -5351,7 +5574,7 @@ dependencies = [
"bumpalo", "bumpalo",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
@@ -5531,7 +5754,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -5542,7 +5765,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -5553,7 +5776,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -5564,7 +5787,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -5828,7 +6051,7 @@ dependencies = [
"heck", "heck",
"indexmap", "indexmap",
"prettyplease", "prettyplease",
"syn", "syn 2.0.117",
"wasm-metadata", "wasm-metadata",
"wit-bindgen-core", "wit-bindgen-core",
"wit-component", "wit-component",
@@ -5844,7 +6067,7 @@ dependencies = [
"prettyplease", "prettyplease",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
"wit-bindgen-core", "wit-bindgen-core",
"wit-bindgen-rust", "wit-bindgen-rust",
] ]
@@ -5858,7 +6081,7 @@ dependencies = [
"anyhow", "anyhow",
"bitflags 2.11.1", "bitflags 2.11.1",
"indexmap", "indexmap",
"log 0.4.29", "log",
"serde", "serde",
"serde_derive", "serde_derive",
"serde_json", "serde_json",
@@ -5877,7 +6100,7 @@ dependencies = [
"anyhow", "anyhow",
"id-arena", "id-arena",
"indexmap", "indexmap",
"log 0.4.29", "log",
"semver", "semver",
"serde", "serde",
"serde_derive", "serde_derive",
@@ -5966,7 +6189,7 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
"synstructure", "synstructure",
] ]
@@ -5987,7 +6210,7 @@ checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -6007,7 +6230,7 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
"synstructure", "synstructure",
] ]
@@ -6028,7 +6251,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -6061,7 +6284,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.117",
] ]
[[package]] [[package]]
@@ -6080,7 +6303,7 @@ dependencies = [
"hmac 0.12.1", "hmac 0.12.1",
"pbkdf2 0.11.0", "pbkdf2 0.11.0",
"sha1 0.10.6", "sha1 0.10.6",
"time 0.3.47", "time",
"zstd 0.11.2+zstd.1.5.2", "zstd 0.11.2+zstd.1.5.2",
] ]

View File

@@ -18,10 +18,11 @@ path = "src/lib.rs"
anyhow = "1" anyhow = "1"
clap = { version = "4", features = ["derive"] } clap = { version = "4", features = ["derive"] }
filetree = { path = "../filetree" } filetree = { path = "../filetree" }
fuse = "0.3.1" fuse-backend-rs = { path = "../fuse-backend-rs-fork", features = ["fusedev", "fuse-t"] }
libc = "0.2" libc = "0.2"
log = "0.4" log = "0.4"
rusqlite = { version = "0.32", features = ["bundled"] } rusqlite = { version = "0.32", features = ["bundled"] }
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
time = "0.3" time = "0.3"
vm-memory = "0.17"

View File

@@ -1,13 +1,16 @@
fn main() { fn main() {
// Manual linking for FUSE-T on macOS (no pkg-config dependency) if cfg!(target_os = "macos") {
println!("cargo:rustc-link-search=native=/usr/local/lib"); // Link fuse-t library
println!("cargo:rustc-link-lib=fuse-t");
// Link to both fuse3 and fuse-t (FUSE-T provides both) // Link macOS frameworks
println!("cargo:rustc-link-lib=dylib=fuse3"); println!("cargo:rustc-link-lib=framework=DiskArbitration");
println!("cargo:rustc-link-lib=dylib=fuse-t"); println!("cargo:rustc-link-lib=framework=CoreFoundation");
// Set rpath for runtime loading // Add fuse-t include path
println!("cargo:rustc-link-arg=-Wl,-rpath,/usr/local/lib"); println!("cargo:rustc-link-search=native=/usr/local/lib");
println!("cargo:rerun-if-changed=build.rs"); // Rerun if fuse-t changes
println!("cargo:rerun-if-changed=/usr/local/lib/libfuse-t.dylib");
}
} }

View File

@@ -106,6 +106,21 @@ impl DbManager {
Ok(labels) Ok(labels)
} }
pub fn find_node_id_by_parent(&self, parent_id: &str, name: &str) -> Result<Option<String>> {
let conn = self.conn.lock().unwrap();
let sql = "SELECT node_id FROM file_nodes WHERE parent_id = ?1 AND label = ?2 AND tree_type = ?3 LIMIT 1";
let mut stmt = conn.prepare(sql)?;
let result = stmt.query_row(params![parent_id, name, &self.tree_type], |row| row.get::<_, String>(0));
match result {
Ok(node_id) => Ok(Some(node_id)),
Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
Err(e) => Err(e.into()),
}
}
pub fn preload_files( pub fn preload_files(
&self, &self,
cache: &super::cache::ThreadSafeCache, cache: &super::cache::ThreadSafeCache,

View File

@@ -1,28 +1,25 @@
use anyhow::Result; use anyhow::Result;
use fuse::{ use fuse_backend_rs::api::filesystem::{Context, DirEntry, Entry, FileSystem, ZeroCopyWriter};
FileAttr, FileType, Filesystem, ReplyAttr, ReplyData, ReplyDirectory, ReplyEntry, Request, use fuse_backend_rs::abi::fuse_abi::{stat64, statvfs64, FsOptions, OpenOptions};
};
use libc::{EIO, ENOENT};
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::CStr;
use std::fs::File; use std::fs::File;
use std::io::{Read, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
use std::path::Path; use std::os::unix::io::{AsRawFd, FromRawFd};
use std::sync::Arc; use std::sync::{Arc, RwLock};
use std::time::SystemTime; use std::time::{Duration, SystemTime};
use std::ffi::CString; use super::cache::ThreadSafeCache;
use super::db::DbManager;
const TTL: std::time::Duration = std::time::Duration::from_secs(1); const TTL: Duration = Duration::from_secs(1);
const READ_CHUNK_SIZE: usize = 524288; // 512KB for maximum throughput const READ_CHUNK_SIZE: usize = 524288; // 512KB
const CACHE_SIZE: usize = 1000;
pub struct MarkBaseFs { pub struct MarkBaseFs {
db: Arc<DbManager>, db: Arc<DbManager>,
cache: Arc<ThreadSafeCache>, cache: Arc<ThreadSafeCache>,
inode_map: HashMap<u64, String>, inode_map: RwLock<HashMap<u64, String>>,
path_cache: HashMap<String, u64>, next_inode: RwLock<u64>,
next_inode: u64,
} }
impl MarkBaseFs { impl MarkBaseFs {
@@ -30,213 +27,253 @@ impl MarkBaseFs {
let db = DbManager::open(db_path, tree_type)?; let db = DbManager::open(db_path, tree_type)?;
let cache = ThreadSafeCache::new(); let cache = ThreadSafeCache::new();
let count = db.preload_files(&cache, CACHE_SIZE)?;
println!("Pre-cached {} files for tree_type: {}", count, tree_type);
Ok(Self { Ok(Self {
db: Arc::new(db), db: Arc::new(db),
cache: Arc::new(cache), cache: Arc::new(cache),
inode_map: HashMap::new(), inode_map: RwLock::new(HashMap::new()),
path_cache: HashMap::new(), next_inode: RwLock::new(2),
next_inode: 2,
}) })
} }
fn find_node_id_by_inode(&self, ino: u64) -> Option<String> { fn find_node_id_by_inode(&self, ino: u64) -> Option<String> {
self.inode_map.get(&ino).cloned() self.inode_map.read().unwrap().get(&ino).cloned()
} }
fn get_or_create_inode(&mut self, node_id: &str) -> u64 { fn get_or_create_inode(&self, node_id: &str) -> u64 {
// Find existing inode let map = self.inode_map.read().unwrap();
for (ino, id) in &self.inode_map { for (ino, id) in &*map {
if id == node_id { if id == node_id {
return *ino; return *ino;
} }
} }
drop(map);
// Create new inode let mut next = self.next_inode.write().unwrap();
let ino = self.next_inode; let ino = *next;
self.next_inode += 1; *next += 1;
self.inode_map.insert(ino, node_id.to_string());
let mut map = self.inode_map.write().unwrap();
map.insert(ino, node_id.to_string());
ino ino
} }
fn find_node_id_by_path(&self, path: &str) -> Option<String> { fn make_stat64(node_type: &str, file_size: u64) -> stat64 {
// Check path cache first let mut st = unsafe { std::mem::zeroed::<stat64>() };
if let Some(node_id) = self.cache.lookup_path(path) { st.st_ino = 0;
return Some(node_id); st.st_mode = if node_type == "folder" { 0o755 } else { 0o644 };
} st.st_nlink = if node_type == "folder" { 2 } else { 1 };
st.st_uid = 501;
st.st_gid = 20;
st.st_size = file_size as i64;
st.st_blocks = ((file_size + 511) / 512) as i64;
st.st_blksize = 4096;
// Query from database let now = SystemTime::now();
match self.db.find_node_id(path) { st.st_atime = now.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs() as i64;
Ok(Some(node_id)) => { st.st_mtime = st.st_atime;
self.cache.insert_path(path, &node_id); st.st_ctime = st.st_atime;
Some(node_id)
}
_ => None,
}
}
fn get_file_path(&self, node_id: &str) -> Option<String> { st
// Check cache first
if let Some((path, _)) = self.cache.lookup_file(node_id) {
return Some(path);
}
// Query from database
match self.db.get_file_path(node_id) {
Ok(Some(path)) => {
self.cache.insert_file(node_id, &path, 0);
Some(path)
}
_ => None,
}
}
fn make_file_attr(ino: u64, node_type: &str, file_size: u64) -> FileAttr {
FileAttr {
ino,
size: file_size,
blocks: (file_size + 511) / 512,
atime: SystemTime::now(),
mtime: SystemTime::now(),
ctime: SystemTime::now(),
crtime: SystemTime::now(),
kind: if node_type == "folder" {
FileType::Directory
} else {
FileType::RegularFile
},
perm: if node_type == "folder" { 0o755 } else { 0o644 },
nlink: if node_type == "folder" { 2 } else { 1 },
uid: 501, // default user
gid: 20, // default group
rdev: 0,
flags: 0,
}
} }
} }
impl Filesystem for MarkBaseFs { impl FileSystem for MarkBaseFs {
fn lookup(&mut self, _req: &Request, parent: u64, name: &Path, reply: ReplyEntry) { type Inode = u64;
let parent_path = if parent == 1 { "/" } else { "" }; type Handle = u64;
let full_path = format!("{}/{}", parent_path, name.to_string_lossy());
let node_id = self.find_node_id_by_path(&full_path); fn init(&self, capable: FsOptions) -> std::io::Result<FsOptions> {
Ok(capable)
}
fn lookup(
&self,
ctx: &Context,
parent: Self::Inode,
name: &CStr,
) -> std::io::Result<Entry> {
let name_str = name.to_string_lossy();
let node_id = if parent == 1 {
self.db.find_node_id(&format!("/{}", name_str)).ok().flatten()
} else {
let parent_id = self.find_node_id_by_inode(parent);
match parent_id {
Some(pid) => self.db.find_node_id_by_parent(&pid, &name_str).ok().flatten(),
None => None,
}
};
match node_id { match node_id {
Some(id) => { Some(id) => {
let info = self.db.get_node_info(&id).ok(); let info = self.db.get_node_info(&id);
match info { match info {
Some((node_type, file_size)) => { Ok(Some((node_type, file_size))) => {
let ino = self.get_or_create_inode(&id); let ino = self.get_or_create_inode(&id);
let attr = self.make_file_attr(ino, &node_type, file_size); let attr = MarkBaseFs::make_stat64(&node_type, file_size);
reply.entry(&TTL, &attr, 0); Ok(Entry {
inode: ino,
generation: 0,
attr,
attr_flags: 0,
attr_timeout: TTL,
entry_timeout: TTL,
})
} }
_ => reply.error(ENOENT), _ => Err(std::io::Error::from_raw_os_error(libc::ENOENT)),
} }
} }
None => reply.error(ENOENT), None => Err(std::io::Error::from_raw_os_error(libc::ENOENT)),
} }
} }
fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) { fn forget(&self, ctx: &Context, inode: Self::Inode, count: u64) {
if ino == 1 { let mut map = self.inode_map.write().unwrap();
let attr = self.make_file_attr(1, "folder", 0); map.remove(&inode);
reply.attr(&TTL, &attr); }
return;
fn getattr(
&self,
ctx: &Context,
inode: Self::Inode,
handle: Option<Self::Handle>,
) -> std::io::Result<(stat64, Duration)> {
if inode == 1 {
let attr = MarkBaseFs::make_stat64("folder", 0);
return Ok((attr, TTL));
} }
let node_id = self.find_node_id_by_inode(ino); let node_id = self.find_node_id_by_inode(inode);
match node_id { match node_id {
Some(id) => { Some(id) => {
let info = self.db.get_node_info(&id).ok(); let info = self.db.get_node_info(&id);
match info { match info {
Some((node_type, file_size)) => { Ok(Some((node_type, file_size))) => {
let attr = self.make_file_attr(ino, &node_type, file_size); let attr = MarkBaseFs::make_stat64(&node_type, file_size);
reply.attr(&TTL, &attr); Ok((attr, TTL))
} }
_ => reply.error(ENOENT), _ => Err(std::io::Error::from_raw_os_error(libc::ENOENT)),
} }
} }
None => reply.error(ENOENT), None => Err(std::io::Error::from_raw_os_error(libc::ENOENT)),
} }
} }
fn open(
&self,
ctx: &Context,
inode: Self::Inode,
flags: u32,
fuse_flags: u32,
) -> std::io::Result<(Option<Self::Handle>, OpenOptions, Option<u32>)> {
Ok((Some(inode), OpenOptions::empty(), None))
}
fn read( fn read(
&mut self, &self,
_req: &Request, ctx: &Context,
ino: u64, inode: Self::Inode,
fh: u64, handle: Self::Handle,
offset: i64, w: &mut dyn ZeroCopyWriter,
size: u32, size: u32,
reply: ReplyData, offset: u64,
) { lock_owner: Option<u64>,
let node_id = self.find_node_id_by_inode(ino); flags: u32,
) -> std::io::Result<usize> {
let node_id = self.find_node_id_by_inode(inode);
match node_id { match node_id {
Some(id) => { Some(id) => {
let file_path = self.get_file_path(&id); let file_path = self.db.get_file_path(&id);
match file_path { match file_path {
Some(fp) => { Ok(Some(fp)) => {
let mut file = File::open(&fp)?; let file = File::open(&fp)?;
file.seek(SeekFrom::Start(offset as u64)).ok(); let fd = file.as_raw_fd();
let f = unsafe { File::from_raw_fd(fd) };
let mut f = std::mem::ManuallyDrop::new(f);
let mut buffer = vec![0u8; size as usize]; w.write_from(&mut *f, size as usize, offset)
let bytes_read = file.read(&mut buffer).ok();
buffer.truncate(bytes_read);
reply.data(&buffer);
} }
None => reply.error(ENOENT), _ => Err(std::io::Error::from_raw_os_error(libc::ENOENT)),
} }
} }
None => reply.error(ENOENT), None => Err(std::io::Error::from_raw_os_error(libc::ENOENT)),
} }
} }
fn release(
&self,
ctx: &Context,
inode: Self::Inode,
flags: u32,
handle: Self::Handle,
flush: bool,
flock_release: bool,
lock_owner: Option<u64>,
) -> std::io::Result<()> {
Ok(())
}
fn opendir(
&self,
ctx: &Context,
inode: Self::Inode,
flags: u32,
) -> std::io::Result<(Option<Self::Handle>, OpenOptions)> {
Ok((Some(inode), OpenOptions::empty()))
}
fn readdir( fn readdir(
&mut self, &self,
_req: &Request, ctx: &Context,
ino: u64, inode: Self::Inode,
fh: u64, handle: Self::Handle,
offset: i64, size: u32,
mut reply: ReplyDirectory, offset: u64,
) { add_entry: &mut dyn FnMut(DirEntry) -> std::io::Result<usize>,
) -> std::io::Result<()> {
if offset == 0 { if offset == 0 {
reply.add(ino, 1, FileType::Directory, "."); add_entry(DirEntry {
reply.add(ino, 2, FileType::Directory, ".."); name: b".\0",
ino: inode,
offset: 1,
type_: libc::S_IFDIR as u32,
})?;
if ino == 1 { add_entry(DirEntry {
// Root - show Home folder name: b"..\0",
reply.add(2, 3, FileType::Directory, "Home"); ino: 1,
} else { offset: 2,
let node_id = self.find_node_id_by_inode(ino); type_: libc::S_IFDIR as u32,
})?;
match node_id {
Some(id) => {
let children = self.db.list_children(&id).ok();
let mut child_offset = 3;
for child_name in children {
reply.add(
child_offset,
child_offset + 1,
FileType::RegularFile,
&child_name,
);
child_offset += 1;
}
}
None => {}
}
}
} }
reply.ok(); Ok(())
}
fn releasedir(
&self,
ctx: &Context,
inode: Self::Inode,
flags: u32,
handle: Self::Handle,
) -> std::io::Result<()> {
Ok(())
}
fn statfs(
&self,
ctx: &Context,
inode: Self::Inode,
) -> std::io::Result<statvfs64> {
let mut st = unsafe { std::mem::zeroed::<statvfs64>() };
st.f_bsize = 4096;
st.f_blocks = 1000000;
st.f_bfree = 500000;
st.f_bavail = 500000;
st.f_files = 1000;
st.f_ffree = 500;
st.f_favail = 500;
st.f_namemax = 255;
Ok(st)
} }
} }

View File

@@ -2,7 +2,6 @@ use anyhow::Result;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex;
#[derive(Parser)] #[derive(Parser)]
#[command(name = "markbase-fuse", about = "MarkBase FUSE Mount Tool")] #[command(name = "markbase-fuse", about = "MarkBase FUSE Mount Tool")]
@@ -43,7 +42,8 @@ fn main() -> Result<()> {
} }
fn mount_user(user: String, tree_type: String, dir: PathBuf) -> Result<()> { fn mount_user(user: String, tree_type: String, dir: PathBuf) -> Result<()> {
use fuse::mount; use fuse_backend_rs::api::server::Server;
use fuse_backend_rs::transport::FuseSession;
use markbase_fuse::MarkBaseFs; use markbase_fuse::MarkBaseFs;
use std::env::current_dir; use std::env::current_dir;
@@ -61,7 +61,7 @@ fn mount_user(user: String, tree_type: String, dir: PathBuf) -> Result<()> {
std::fs::create_dir_all(&dir)?; std::fs::create_dir_all(&dir)?;
} }
println!("=== MarkBase FUSE (fuse crate + FUSE-T) ==="); println!("=== MarkBase FUSE (fuse-backend-rs + fuse-t) ===");
println!("User: {}", user); println!("User: {}", user);
println!("Tree Type: {}", tree_type); println!("Tree Type: {}", tree_type);
println!("Database: {}", db_path.display()); println!("Database: {}", db_path.display());
@@ -69,34 +69,42 @@ fn mount_user(user: String, tree_type: String, dir: PathBuf) -> Result<()> {
println!(""); println!("");
let fs = MarkBaseFs::new(&db_path.to_string_lossy(), &tree_type)?; let fs = MarkBaseFs::new(&db_path.to_string_lossy(), &tree_type)?;
let fs = Arc::new(Mutex::new(fs)); let server = Arc::new(Server::new(fs));
let options = vec![ let mut session = FuseSession::new(&dir, "markbase", "markbase-fuse", false)?;
"-o", session.mount()?;
"rw",
"-o",
"allow_other",
"-o",
"noatime",
"-o",
"local",
"-o",
"big_writes",
"-o",
"max_read=524288",
"-o",
"max_write=524288",
"-o",
"kernel_cache",
];
mount(fs, &dir, &options)?;
println!("Mounted successfully!"); println!("Mounted successfully!");
println!("Press Ctrl+C to unmount..."); println!("Press Ctrl+C to unmount...");
let mut channel = session.new_channel()?;
let ebadf = std::io::Error::from_raw_os_error(libc::EBADF);
loop {
if let Some((reader, writer)) = channel.get_request()? {
if let Err(e) = server.handle_message(reader, writer.into(), None, None) {
match e {
fuse_backend_rs::Error::EncodeMessage(e) if e.kind() == std::io::ErrorKind::Other => {
break;
}
_ => {
eprintln!("Handling fuse message failed: {:?}", e);
continue;
}
}
}
} else {
println!("fuse server exits");
break;
}
}
session.umount()?;
println!("Unmounted successfully");
Ok(()) Ok(())
} }
fn unmount_user(dir: PathBuf) -> Result<()> { fn unmount_user(dir: PathBuf) -> Result<()> {
println!("Unmounting: {}", dir.display()); println!("Unmounting: {}", dir.display());