docs: create comprehensive syscall migration plan

SYSCALL-MIGRATION-PLAN.md:
  - Detailed analysis of upstream 0.9.0 BREAKING changes (FD reservation refactor,
    removed syscalls, new *_into variants)
  - Complete consumer impact catalog: 2 bootstrap call sites, 7 kernel/relibc
    constant references, 26 recipes (no impact)
  - 5-phase migration plan: bootstrap→kernel→relibc→syscall sync→full build
  - Risk assessment with rollback procedure
  - Clear migration table: old API → new API for each deprecated function/constant
  - Execution order with time estimates (~1-2 days total)
This commit is contained in:
2026-07-08 00:33:17 +03:00
parent c71dd84188
commit 7e34c4c251
+242
View File
@@ -0,0 +1,242 @@
# Syscall Migration — Upstream 0.9.0 BREAKING Changes
**Date**: 2026-07-07
**Status**: Assessment complete, migration plan ready
**Reference**: `local/sources/syscall/` — our fork `7e9cffd` vs upstream `1db4871`
---
## 1. What Changed Upstream
Redox OS upstream (`gitlab.redox-os.org/redox-os/syscall.git`) introduced two
breaking changes in version 0.9.0:
### 1.1 FD Reservation Refactor (`4bb9233`)
The old auto-allocation FD API was replaced with reservation-based allocation:
| Old (deprecated) | New (upstream 0.9.0) |
|---|---|
| `syscall::open(path, flags)` → returns auto-allocated fd | `syscall::open_into(path, flags, reserved_fd)` |
| `syscall::dup(fd, buf)` → returns auto-allocated fd | `syscall::dup_into(fd, reserved_fd, buf)` |
| Implicit fd allocation | Explicit reservation via `syscall::reserve_fd(n)` |
The reservation model requires callers to:
1. Call `reserve_fd(n)` to reserve N consecutive fd numbers
2. Pass the reserved fd to `*_into` variants
3. Release unused reservations via `release_fd(n)`
### 1.2 Removed Syscalls (`1db4871`)
These syscall numbers were removed from `src/number.rs` and `src/call.rs`:
| Removed Constant | Reason |
|---|---|
| `SYS_OPENAT_WITH_FILTER` (985) | Replaced by `SYS_OPENAT_INTO` (987) — reservation-based |
| `SYS_UNLINKAT_WITH_FILTER` (986) | Replaced by `SYS_UNLINKAT` (263) — no filter needed |
| `SYS_SENDFD` (34) | Absorbed into `SYS_CLOSE` / scheme dispatch |
| `SYS_OPENAT` (7) | Replaced by `SYS_OPENAT_INTO` (987) |
| `SYS_DUP` (41) | Replaced by `SYS_DUP_INTO` (988) |
The corresponding call wrappers were also removed:
- `openat_with_filter()` — removed
- `unlinkat_with_filter()` — removed
### 1.3 New Upstream Features (unrelated, useful)
| Commit | Change |
|---|---|
| `79cb6d9` | `AcpiVerb` — new proc scheme ACPI verb |
| `a358928` | Additional proc scheme & addrsp verbs |
| `fcce297` | `Error::new` as `const fn` |
---
## 2. Our Fork State
Our fork `7e9cffd` is based on upstream at the pre-breaking-change point
(before `4bb9233`). Five commits were added to preserve backward compatibility:
| Our Commit | What It Preserves |
|---|---|
| `812d74e` | `SYS_OPENAT` and `SYS_DUP` aliases |
| `bf54ba8` | `SYS_SENDFD` constant |
| `488ed0c` | `SYS_OPENAT_WITH_FILTER` and `SYS_UNLINKAT_WITH_FILTER` constants |
| `2c06be3` | Legacy `openat`/`dup`/`sendfd`/`close` call wrappers |
| `7e9cffd` | `openat_with_filter` / `unlinkat_with_filter` call wrappers |
**Current divergence**: 5 commits behind upstream HEAD (2 actual changes + 3 cosmetic).
---
## 3. Consumer Impact Analysis
### 3.1 `openat_with_filter` / `unlinkat_with_filter` Usage
Only 1 file uses these deprecated APIs:
| File | Usages | Migration Difficulty |
|---|---|---|
| `local/sources/base/bootstrap/src/initnsmgr.rs` | 2 (openat + unlinkat) | **Low** — straightforward replacement |
### 3.2 Legacy Constant References
| File | Constants Used | Action |
|---|---|---|
| `local/sources/kernel/src/syscall/mod.rs` | `SYS_OPENAT_WITH_FILTER`, `SYS_UNLINKAT_WITH_FILTER`, `SYS_SENDFD` | Update dispatch table |
| `local/sources/kernel/src/scheme/proc.rs` | `SYS_SENDFD` | Update proc scheme handler |
| `local/sources/kernel/src/syscall/debug.rs` | `SYS_OPENAT`, `SYS_DUP` | Update debug logging |
| `local/sources/syscall/src/flag.rs` | `SYS_SENDFD` | Internal — will be updated by sync |
| `local/sources/relibc/redox-rt/src/sys.rs` | `SYS_OPENAT`, `SYS_DUP`, `SYS_SENDFD` | Update redox-rt wrappers |
### 3.3 Recipe Consumers (26 recipes)
All 26 recipes reference `redox_syscall` via `Cargo.toml` but do NOT use the
deprecated APIs directly — they use stable APIs (`open`, `read`, `write`, etc.).
**No recipe changes needed.**
---
## 4. Migration Plan
### Phase 1: Bootstrap Migration (Low Risk, 2 call sites)
**File**: `local/sources/base/bootstrap/src/initnsmgr.rs`
Replace `openat_with_filter` with the upstream `openat_into` + reservation pattern:
```rust
// OLD:
let scheme_fd = syscall::openat_with_filter(
cap_fd, reference, flags, ctx.uid, ctx.gid
)?;
// NEW (reservation-based):
let reserved = syscall::reserve_fd(1)?;
let scheme_fd = syscall::openat_into(
cap_fd, reference, flags, reserved, ctx.uid, ctx.gid
)?;
```
Replace `unlinkat_with_filter` with `unlinkat`:
```rust
// OLD:
syscall::unlinkat_with_filter(cap_fd, reference, flags, ctx.uid, ctx.gid)?;
// NEW:
syscall::unlinkat(cap_fd, reference, flags)?;
```
**Verification**: `cargo check -p bootstrap` passes.
### Phase 2: Kernel Dispatch Update (Medium Risk, 3 files)
Update `local/sources/kernel/src/syscall/mod.rs` — replace deprecated constants in
the syscall dispatch match:
| Old | New |
|---|---|
| `SYS_OPENAT_WITH_FILTER` | `SYS_OPENAT_INTO` |
| `SYS_UNLINKAT_WITH_FILTER` | Remove (no longer dispatched) |
| `SYS_SENDFD` | Remove (absorbed into scheme dispatch) |
| `SYS_OPENAT` | `SYS_OPENAT_INTO` |
| `SYS_DUP` | `SYS_DUP_INTO` |
Update `local/sources/kernel/src/scheme/proc.rs` — remove `SYS_SENDFD` handling.
Update `local/sources/kernel/src/syscall/debug.rs` — update constant names in log messages.
**Verification**: `cargo check -p kernel` passes. Boot test in QEMU.
### Phase 3: relibc redox-rt Update (Medium Risk, 1 file)
Update `local/sources/relibc/redox-rt/src/sys.rs` — replace deprecated constant
references with the new names. The redox-rt module wraps kernel syscalls for
relibc's POSIX layer.
**Verification**: `cargo check` in relibc passes. `sys_socket` tests pass.
### Phase 4: Syscall Fork Sync (High Risk, entire fork)
Squash-merge the upstream changes into our fork:
```bash
cd local/sources/syscall
git fetch upstream
git checkout -b sync-0.9.0 upstream/master
git merge --squash master # re-apply our preservation commits on top of upstream
# Resolve conflicts in:
# src/call.rs — keep upstream's reservation API, drop our legacy wrappers
# src/number.rs — keep upstream's constants, drop our legacy constants
# src/flag.rs — merge minimally
```
**After sync, our fork drops all 5 preservation commits** since:
1. `openat_with_filter` / `unlinkat_with_filter` are no longer needed (bootstrap migrated)
2. `SYS_OPENAT_WITH_FILTER` etc. are no longer needed (kernel migrated)
3. The reservation API is the canonical path
**Verification**:
- `cargo check` in syscall passes
- All 26 recipes compile against new syscall
- Kernel compiles against new syscall
- relibc compiles against new syscall
- Full `redbear-mini` ISO builds
### Phase 5: Full Image Build + Validation
```bash
touch syscall && make prefix
./local/scripts/build-redbear.sh --upstream redbear-mini
# QEMU boot test
# DHCP + curl test
```
---
## 5. Risk Assessment
| Risk | Severity | Mitigation |
|---|---|---|
| Kernel panic from missing syscall dispatch | **HIGH** | Test each syscall removal individually in QEMU |
| FD leak from reservation API misuse | **MEDIUM** | Audit all `reserve_fd` / `release_fd` call pairs |
| relibc ABI break | **MEDIUM** | Run full `sys_socket` test suite |
| Recipe compile failure | **LOW** | All 26 recipes use stable APIs — no changes needed |
| Bootstrap fails to init | **LOW** | Only 2 call sites, simple replacement |
---
## 6. Execution Order
```
Phase 1 (bootstrap) → Phase 2 (kernel) → Phase 3 (relibc) → Phase 4 (syscall sync) → Phase 5 (full build)
30 min 2-4 hours 1 hour 1-2 hours 2-4 hours
```
**Total estimated duration**: 1-2 days.
**Prerequisite**: None — all phases are independent except Phase 4 depends on 1-3 completing
first (consumers must be migrated before syscall drops legacy support).
---
## 7. Rollback Plan
If the migration fails, revert each component:
```bash
# Revert syscall fork to pre-sync state
cd local/sources/syscall && git checkout master
# Revert kernel (git stash or checkout)
cd local/sources/kernel && git checkout -- .
# Revert bootstrap
cd local/sources/base && git checkout -- bootstrap/
# Revert relibc
cd local/sources/relibc && git checkout -- redox-rt/
```
The legacy constants and wrappers are preserved in our fork's git history at `7e9cffd`.