Files
markbase/docs/FUSE_POC_TEST.md
2026-05-18 17:02:30 +08:00

710 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MarkBase FUSE POC Test Plan
## Overview
**Objective**: Verify FUSE-T installation, basic functionality, and backend selection before full implementation.
**Scope**: Phase 1 POC verification (Day 1-2)
**Environment**: M4 Mac mini, macOS 26.4.1, NVMe storage
---
## Test Environment Setup
### Hardware Configuration
| Component | Specification |
|-----------|--------------|
| **CPU** | Apple M4, 10 physical cores |
| **RAM** | 16 GB unified memory |
| **Storage** | KIOXIA NVMe 2TB (PCIe) |
| **OS** | macOS 26.4.1 (Sequoia) |
| **Network** | Thunderbolt Ethernet |
### Software Dependencies
```bash
# Required tools
brew install fuse-t # FUSE-T installation
brew install rustup # Rust toolchain (already installed)
# Optional test tools
brew install ajadatacalc # AJA Data Calculator (storage estimation)
```
### AJA System Test Installation
```bash
# Download AJA System Test
curl -L -o ~/Downloads/AJA_System_Test.dmg \
"https://www.aja.com/en/products/aja-system-test"
# Install
hdiutil attach ~/Downloads/AJA_System_Test.dmg
cp -R /Volumes/AJA\ System\ Test/*.app /Applications/
hdiutil detach /Volumes/AJA\ System\ Test
# Verify installation
ls -la /Applications/AJA\ System\ Test.app
```
---
## Test 1: FUSE-T Installation Verification
### Objective
Verify FUSE-T can be installed and basic mount/unmount operations work.
### Steps
```bash
# Step 1: Install FUSE-T
brew install macos-fuse-t/homebrew-cask/fuse-t
# Step 2: Verify installation
ls -la /usr/local/bin/fuse-t
fuse-t --version
# Step 3: Check NFS server
ls -la /usr/local/bin/nfs-t
nfs-t --version
# Step 4: Verify mount capability
mount | grep fuse # Should show no existing FUSE mounts
```
### Expected Results
| Check | Expected | Actual | Pass/Fail |
|-------|----------|--------|-----------|
| fuse-t binary exists | `/usr/local/bin/fuse-t` | TBD | TBD |
| fuse-t version | >=1.2.6 | TBD | TBD |
| nfs-t binary exists | `/usr/local/bin/nfs-t` | TBD | TBD |
| No existing FUSE mounts | Empty output | TBD | TBD |
### Failure Handling
**If installation fails:**
1. Check System Settings → Privacy & Security → Network Volumes permission
2. Manual download: https://github.com/macos-fuse-t/fuse-t/releases
3. Install from PKG: `sudo installer -pkg fuse-t-macos-installer-1.2.6.pkg -target /`
---
## Test 2: Hello FUSE POC
### Objective
Create minimal FUSE filesystem to verify mount/unmount works.
### Implementation
```rust
// src/fuse/poc_hello.rs
use fuse::{Filesystem, FileAttr, FileType};
use time::Timespec;
use std::path::Path;
pub struct HelloFs;
impl Filesystem for HelloFs {
fn lookup(&mut self, _parent: u64, name: &str, reply: fuse::ReplyEntry) {
if name == "hello.txt" {
let attr = FileAttr {
ino: 2,
size: 13,
blocks: 0,
atime: Timespec::new(0, 0),
mtime: Timespec::new(0, 0),
ctime: Timespec::new(0, 0),
crtime: Timespec::new(0, 0),
kind: FileType::RegularFile,
perm: 0o644,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
flags: 0,
};
reply.entry(&Timespec::new(0, 0), &attr, 0);
} else {
reply.error(libc::ENOENT);
}
}
fn getattr(&mut self, ino: u64, reply: fuse::ReplyAttr) {
match ino {
1 => {
// Root directory
let attr = FileAttr {
ino: 1,
size: 0,
blocks: 0,
atime: Timespec::new(0, 0),
mtime: Timespec::new(0, 0),
ctime: Timespec::new(0, 0),
crtime: Timespec::new(0, 0),
kind: FileType::Directory,
perm: 0o755,
nlink: 2,
uid: 0,
gid: 0,
rdev: 0,
flags: 0,
};
reply.attr(&Timespec::new(0, 0), &attr);
}
2 => {
// hello.txt
let attr = FileAttr {
ino: 2,
size: 13,
blocks: 0,
atime: Timespec::new(0, 0),
mtime: Timespec::new(0, 0),
ctime: Timespec::new(0, 0),
crtime: Timespec::new(0, 0),
kind: FileType::RegularFile,
perm: 0o644,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
flags: 0,
};
reply.attr(&Timespec::new(0, 0), &attr);
}
_ => reply.error(libc::ENOENT),
}
}
fn read(&mut self, ino: u64, _offset: u64, _size: u32, reply: fuse::ReplyData) {
if ino == 2 {
reply.data(&b"Hello from MarkBase FUSE!\n"[..]);
} else {
reply.error(libc::ENOENT);
}
}
fn readdir(&mut self, ino: u64, _offset: u64, reply: fuse::ReplyDirectory) {
if ino == 1 {
reply.add(1, 0, FileType::Directory, ".");
reply.add(1, 1, FileType::Directory, "..");
reply.add(2, 2, FileType::RegularFile, "hello.txt");
reply.ok();
} else {
reply.error(libc::ENOENT);
}
}
}
pub fn mount_hello_fs(path: &Path) -> Result<(), Box<dyn std::error::Error>> {
let fs = HelloFs;
fuse::mount(fs, path, &[])?;
Ok(())
}
```
### Test Commands
```bash
# Create test directory
mkdir -p /tmp/fuse_test
# Mount Hello FUSE
cargo run -- fuse --poc --mount --dir /tmp/fuse_test
# Verify mount
mount | grep fuse_test
ls -la /tmp/fuse_test
cat /tmp/fuse_test/hello.txt
# Expected output: "Hello from MarkBase FUSE!\n"
# Unmount
cargo run -- fuse --poc --unmount --dir /tmp/fuse_test
umount /tmp/fuse_test # Manual fallback
```
### Expected Results
| Check | Expected | Actual | Pass/Fail |
|-------|----------|--------|-----------|
| Mount succeeds | Exit code 0 | TBD | TBD |
| Mount visible in `mount` | `fuse_test` entry | TBD | TBD |
| Directory listing | `hello.txt` visible | TBD | TBD |
| File read | "Hello from MarkBase FUSE!\n" | TBD | TBD |
| Unmount succeeds | Exit code 0 | TBD | TBD |
| Mount removed | No `fuse_test` in `mount` | TBD | TBD |
---
## Test 3: Backend Selection Verification
### Objective
Test both NFSv4 and FSKit backends to verify performance difference.
### Backend Detection
```rust
// src/fuse/backend.rs
use std::env;
pub fn detect_macos_version() -> String {
env::var("MACOS_VERSION").unwrap_or_else(|_| {
// Fallback: parse from system
let output = Command::new("sw_vers")
.arg("-productVersion")
.output()
.expect("Failed to get macOS version");
String::from_utf8_lossy(&output.stdout).trim().to_string()
})
}
pub fn select_backend() -> BackendType {
let version = detect_macos_version();
if version.starts_with("26") {
BackendType::Fskit // macOS 26+ supports FSKit
} else {
BackendType::Nfs4 // Older macOS uses NFSv4
}
}
```
### Test NFSv4 Backend
```bash
# Force NFSv4 backend
cargo run -- fuse --poc --mount --dir /tmp/fuse_nfs --backend nfs
# Performance test
time ls -la /tmp/fuse_nfs
time cat /tmp/fuse_nfs/hello.txt
# Unmount
cargo run -- fuse --poc --unmount --dir /tmp/fuse_nfs
```
### Test FSKit Backend
```bash
# Force FSKit backend (macOS 26+)
cargo run -- fuse --poc --mount --dir /tmp/fuse_fskit --backend fskit
# Performance test
time ls -la /tmp/fuse_fskit
time cat /tmp/fuse_fskit/hello.txt
# Unmount
cargo run -- fuse --poc --unmount --dir /tmp/fuse_fskit
```
### Performance Comparison
| Backend | ls latency | cat latency | Notes |
|---------|------------|--------------|-------|
| NFSv4 | TBD | TBD | Baseline |
| FSKit | TBD | TBD | Target: 40% faster |
| Direct disk | TBD | TBD | Reference |
---
## Test 4: Basic Read/Write Operations
### Objective
Verify basic file operations work through FUSE mount.
### Test Script
```bash
#!/bin/bash
# tests/fuse_basic_ops.sh
MOUNT_DIR="/tmp/fuse_ops_test"
# Setup
mkdir -p "$MOUNT_DIR"
cargo run -- fuse --poc --mount --dir "$MOUNT_DIR"
# Test 1: Directory listing
echo "=== Test 1: Directory Listing ==="
ls -la "$MOUNT_DIR"
# Test 2: File read
echo "=== Test 2: File Read ==="
cat "$MOUNT_DIR/hello.txt"
# Test 3: File stat
echo "=== Test 3: File Stat ==="
stat "$MOUNT_DIR/hello.txt"
# Cleanup
cargo run -- fuse --poc --unmount --dir "$MOUNT_DIR"
rm -rf "$MOUNT_DIR"
echo "All tests completed"
```
### Expected Results
| Operation | Expected Output | Pass/Fail |
|-----------|-----------------|-----------|
| Directory listing | Shows `hello.txt` | TBD |
| File read | "Hello from MarkBase FUSE!\n" | TBD |
| File stat | ino=2, size=13, perm=644 | TBD |
| Unmount | Exit code 0 | TBD |
---
## Test 5: AJA System Test Baseline
### Objective
Measure raw disk performance before FUSE implementation.
### AJA Test Configuration
| Setting | Value |
|---------|-------|
| **Target** | `/System/Volumes/Data` (NVMe) |
| **Resolution** | 4K (3840×2160) |
| **Codec** | ProRes 4444 |
| **Frame Rate** | 60 fps |
| **Duration** | 10 seconds |
| **Mode** | Write test |
### Test Procedure
```bash
# Open AJA System Test
open -a "AJA System Test"
# Manual steps:
1. Select target: /System/Volumes/Data
2. Configure: 4K ProRes 4444, 60fps
3. Run Write test (10 seconds)
4. Record results:
- Write speed: ___ MB/s
- Frame rate achieved: ___ fps
- Disk usage: ___ %
```
### dd Baseline Test
```bash
# Write test (6GB)
time dd if=/dev/zero of=/System/Volumes/Data/test_baseline.bin bs=1M count=6000
# Expected: ~1.5GB/s (NVMe raw speed)
# Record: ___ MB/s
# Cleanup
rm /System/Volumes/Data/test_baseline.bin
```
### Expected Results
| Test | Expected Speed | Actual Speed | Pass/Fail |
|------|----------------|--------------|-----------|
| AJA 4K ProRes 4444 Write | >=1500 MB/s | TBD | TBD |
| dd write (6GB) | >=1500 MB/s | TBD | TBD |
| AJA frame rate | 60 fps sustained | TBD | TBD |
---
## Test 6: Rust FUSE Library Verification
### Objective
Verify Rust FUSE library compatibility with FUSE-T.
### Dependency Check
```toml
# Cargo.toml
[dependencies]
fuse = "0.3" # Or fuse-t specific binding
time = "0.3"
libc = "0.2"
```
### Compilation Test
```bash
# Add fuse dependency
cargo add fuse
# Compile check
cargo check
# Expected: No compilation errors
```
### Mount Options Verification
```rust
// src/fuse/options.rs
use fuse::MountOption;
pub fn get_mount_options(backend: BackendType) -> Vec<MountOption> {
match backend {
BackendType::Nfs4 => vec![
MountOption::FSName("markbase"),
MountOption::Noatime,
],
BackendType::Fskit => vec![
MountOption::FSName("markbase"),
MountOption::Noatime,
],
}
}
```
### Expected Results
| Check | Expected | Actual | Pass/Fail |
|-------|----------|--------|-----------|
| Cargo build succeeds | Exit code 0 | TBD | TBD |
| fuse library linked | Binary includes fuse symbols | TBD | TBD |
| Mount options valid | No runtime errors | TBD | TBD |
---
## Test Execution Schedule
### Day 1: Environment Setup
| Time | Task | Duration |
|------|------|----------|
| 09:00 | Install FUSE-T | 15 min |
| 09:15 | Verify installation | 10 min |
| 09:25 | Download AJA System Test | 20 min |
| 09:45 | Install AJA System Test | 10 min |
| 09:55 | Run AJA baseline test | 30 min |
| 10:25 | Document results | 15 min |
| **Total** | | **1.5 hours** |
### Day 1: Hello FUSE POC
| Time | Task | Duration |
|------|------|----------|
| 10:40 | Create src/fuse/poc_hello.rs | 30 min |
| 11:10 | Add fuse dependency | 10 min |
| 11:20 | Compile and test | 20 min |
| 11:40 | Document results | 15 min |
| **Total** | | **1.25 hours** |
### Day 2: Backend Verification
| Time | Task | Duration |
|------|------|----------|
| 09:00 | Test NFSv4 backend | 30 min |
| 09:30 | Test FSKit backend | 30 min |
| 10:00 | Compare performance | 20 min |
| 10:20 | Document findings | 20 min |
| **Total** | | **1.7 hours** |
---
## Test Reporting Template
### FUSE-T Installation Report
```
## Test 1: FUSE-T Installation
**Date**: 2026-05-17
**Environment**: M4 Mac mini, macOS 26.4.1
### Results
| Check | Expected | Actual | Pass/Fail |
|-------|----------|--------|-----------|
| fuse-t binary | Exists | [Record] | [Pass/Fail] |
| fuse-t version | >=1.2.6 | [Record] | [Pass/Fail] |
| nfs-t binary | Exists | [Record] | [Pass/Fail] |
### Issues Found
- [Document any issues]
### Resolution
- [Document solutions applied]
```
### Hello FUSE POC Report
```
## Test 2: Hello FUSE POC
**Date**: 2026-05-17
**Mount Path**: /tmp/fuse_test
### Results
| Check | Expected | Actual | Pass/Fail |
|-------|----------|--------|-----------|
| Mount succeeds | Exit 0 | [Record] | [Pass/Fail] |
| Directory listing | hello.txt | [Record] | [Pass/Fail] |
| File read | "Hello..." | [Record] | [Pass/Fail] |
### Latency Measurements
- Mount time: [Record] ms
- ls time: [Record] ms
- cat time: [Record] ms
### Backend Used
- Backend: [NFSv4/FSKit/Auto]
- Reason: [Auto-detect/Manual]
```
### Performance Baseline Report
```
## Test 5: AJA System Test Baseline
**Date**: 2026-05-17
**Target**: /System/Volumes/Data (NVMe)
### AJA Results
| Codec | Resolution | Frame Rate | Write Speed | Pass/Fail |
|-------|------------|------------|-------------|-----------|
| ProRes 4444 | 4K | 60fps | [Record] MB/s | [Pass/Fail] |
### dd Results
| Test | Block Size | Count | Speed | Pass/Fail |
|------|------------|-------|-------|-----------|
| Write | 1MB | 6000 | [Record] MB/s | [Pass/Fail] |
### Analysis
- NVMe raw speed: [Record] MB/s
- AJA speed: [Record] MB/s
- Overhead: [Calculate] %
```
---
## Failure Recovery Procedures
### FUSE-T Installation Failure
**Symptoms:**
- brew install fails
- Permission denied
- Network volumes not accessible
**Recovery:**
```bash
# Step 1: Check permissions
System Settings → Privacy & Security → Files and Folders → Network Volumes → Enable
# Step 2: Manual install
curl -L -o ~/Downloads/fuse-t.pkg \
https://github.com/macos-fuse-t/fuse-t/releases/download/1.2.6/fuse-t-macos-installer-1.2.6.pkg
sudo installer -pkg ~/Downloads/fuse-t.pkg -target /
# Step 3: Restart terminal
exec zsh
```
### Mount Failure
**Symptoms:**
- mount command hangs
- Operation not permitted
- Device not found
**Recovery:**
```bash
# Check mount status
mount | grep fuse
# Force unmount
umount -f /tmp/fuse_test
# Check process
ps aux | grep fuse
# Kill if needed
kill -9 [PID]
```
### Compilation Failure
**Symptoms:**
- Cargo build fails
- fuse library not found
- Linking errors
**Recovery:**
```bash
# Check Rust version
rustc --version # Need >=1.70
# Update toolchain
rustup update stable
# Rebuild dependencies
cargo clean
cargo build
```
---
## Success Criteria
### Phase 1 POC Complete
| Criterion | Threshold | Measurement |
|-----------|-----------|-------------|
| FUSE-T installed | Binary exists | `/usr/local/bin/fuse-t` present |
| Hello FUSE works | Read/write succeeds | `cat /tmp/fuse_test/hello.txt` outputs correctly |
| Backend detected | Auto-select works | macOS 26 → FSKit, older → NFSv4 |
| AJA baseline | >=1500 MB/s | Raw disk write speed |
| Compilation succeeds | Exit code 0 | `cargo build` completes |
### Proceed to Phase 2
**Decision Criteria:**
- All Test 1-6 pass
- No critical failures
- Performance baseline documented
- Backend selection confirmed
---
## Next Steps After POC
### Phase 2: SQLite-backed FUSE (Day 3-5)
1. Implement `MarkBaseFs` struct
2. Integrate file_nodes/file_locations queries
3. Test warren user (12,659 nodes)
4. Implement LRU caching
5. Performance measurement
### Phase 3: Multi-user Concurrent (Day 6-8)
1. Implement `MountManager`
2. Test 10 user parallel mount
3. AJA concurrent write test
4. Stability test (24h)
### Phase 4: Performance Optimization (Day 9-12)
1. Write buffering (64KB chunks)
2. FSKit backend optimization
3. AJA 600MB/s target validation
4. Final documentation
---
**Last Updated**: 2026-05-17
**Version**: 1.0
**Status**: Ready for Execution