Skip to content

Commit 95659d3

Browse files
committed
refactor(uffd): swap pageTracker for block.StateTracker, add removed state
Replace the map-based pageTracker with block.StateTracker[pageState], a roaring-bitmap-backed tracker with O(1) range ops. pageState gains a third value, removed, which is wired at the type level but not yet written anywhere -- #2520 adds the REMOVE-event handler that produces it. Page indices are computed at the call site via header.BlockIdx. pageStateEntries is updated to iterate the exported bitmaps so the cross-process test harness keeps working.
1 parent 949a4ec commit 95659d3

3 files changed

Lines changed: 20 additions & 40 deletions

File tree

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,9 @@
11
package userfaultfd
22

3-
import "sync"
4-
53
type pageState uint8
64

75
const (
86
missing pageState = iota
97
faulted
8+
removed
109
)
11-
12-
type pageTracker struct {
13-
pageSize uintptr
14-
15-
m map[uintptr]pageState
16-
mu sync.RWMutex
17-
}
18-
19-
func newPageTracker(pageSize uintptr) *pageTracker {
20-
return &pageTracker{
21-
pageSize: pageSize,
22-
m: make(map[uintptr]pageState),
23-
}
24-
}
25-
26-
func (pt *pageTracker) setState(start, end uintptr, state pageState) {
27-
pt.mu.Lock()
28-
defer pt.mu.Unlock()
29-
30-
for addr := start; addr < end; addr += pt.pageSize {
31-
pt.m[addr] = state
32-
}
33-
}

packages/orchestrator/pkg/sandbox/uffd/userfaultfd/rpc_services_test.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"os"
1111
"sync"
1212

13+
"github.com/RoaringBitmap/roaring/v2"
14+
1315
"github.com/e2b-dev/infra/packages/orchestrator/pkg/sandbox/uffd/fdexit"
1416
"github.com/e2b-dev/infra/packages/orchestrator/pkg/sandbox/uffd/memory"
1517
"github.com/e2b-dev/infra/packages/orchestrator/pkg/sandbox/uffd/testutils/testharness"
@@ -186,24 +188,24 @@ func (p *Paging) Resume(_ *testharness.Empty, _ *testharness.Empty) error {
186188
}
187189

188190
// pageStateEntries returns a wire-format snapshot of pageTracker.
189-
// settleRequests.Lock drains fault workers (mirrors PrefetchData);
190-
// pageTracker.mu.RLock is defensive against a future REMOVE writer
191-
// that mutates pageTracker.m outside settleRequests.
191+
// settleRequests.Lock drains fault workers (mirrors PrefetchData) so
192+
// the snapshot is consistent w.r.t. concurrent installs.
192193
func (u *Userfaultfd) pageStateEntries() ([]testharness.PageStateEntry, error) {
193194
u.settleRequests.Lock()
194195
defer u.settleRequests.Unlock()
195196

196-
u.pageTracker.mu.RLock()
197-
defer u.pageTracker.mu.RUnlock()
198-
199-
entries := make([]testharness.PageStateEntry, 0, len(u.pageTracker.m))
200-
for addr, state := range u.pageTracker.m {
201-
offset, err := u.ma.GetOffset(addr)
202-
if err != nil {
203-
return nil, fmt.Errorf("address %#x not in mapping: %w", addr, err)
197+
bmFaulted, bmRemoved := u.pageTracker.Export()
198+
entries := make([]testharness.PageStateEntry, 0, bmFaulted.GetCardinality()+bmRemoved.GetCardinality())
199+
emit := func(bm *roaring.Bitmap, state pageState) {
200+
for _, idx := range bm.ToArray() {
201+
entries = append(entries, testharness.PageStateEntry{
202+
State: uint8(state),
203+
Offset: uint64(idx) * uint64(u.pageSize),
204+
})
204205
}
205-
entries = append(entries, testharness.PageStateEntry{State: uint8(state), Offset: uint64(offset)})
206206
}
207+
emit(bmFaulted, faulted)
208+
emit(bmRemoved, removed)
207209

208210
return entries, nil
209211
}

packages/orchestrator/pkg/sandbox/uffd/userfaultfd/userfaultfd.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/e2b-dev/infra/packages/orchestrator/pkg/sandbox/uffd/fdexit"
2323
"github.com/e2b-dev/infra/packages/orchestrator/pkg/sandbox/uffd/memory"
2424
"github.com/e2b-dev/infra/packages/shared/pkg/logger"
25+
"github.com/e2b-dev/infra/packages/shared/pkg/storage/header"
2526
)
2627

2728
var tracer = otel.Tracer("github.com/e2b-dev/infra/packages/orchestrator/pkg/sandbox/uffd/userfaultfd")
@@ -52,7 +53,7 @@ type Userfaultfd struct {
5253
src block.Slicer
5354
ma *memory.Mapping
5455
pageSize uintptr
55-
pageTracker *pageTracker
56+
pageTracker *block.StateTracker[pageState]
5657

5758
// We use the settleRequests to guard the pageTracker so we can access a consistent state of the pageTracker after the requests are finished.
5859
settleRequests sync.RWMutex
@@ -92,7 +93,7 @@ func NewUserfaultfdFromFd(fd uintptr, src block.Slicer, m *memory.Mapping, logge
9293
fd: Fd(fd),
9394
src: src,
9495
pageSize: uintptr(blockSize),
95-
pageTracker: newPageTracker(uintptr(blockSize)),
96+
pageTracker: block.NewStateTracker(missing, faulted, removed),
9697
prefetchTracker: block.NewPrefetchTracker(blockSize),
9798
ma: m,
9899
logger: logger,
@@ -418,7 +419,8 @@ retryLoop:
418419
return fmt.Errorf("failed uffdio copy: %w", joinedErr)
419420
}
420421

421-
u.pageTracker.setState(addr, addr+u.pageSize, faulted)
422+
idx := uint64(header.BlockIdx(offset, int64(u.pageSize)))
423+
u.pageTracker.SetRange(idx, idx+1, faulted)
422424
u.prefetchTracker.Add(offset, accessType)
423425

424426
return nil

0 commit comments

Comments
 (0)