Skip to content

Fix 1) Safe GC RU handling (ru->ruh based ptr) 2) Cost-benefit correc…#187

Merged
inhoinno merged 1 commit into
MoatLab:masterfrom
inhoinno:master
May 20, 2026
Merged

Fix 1) Safe GC RU handling (ru->ruh based ptr) 2) Cost-benefit correc…#187
inhoinno merged 1 commit into
MoatLab:masterfrom
inhoinno:master

Conversation

@inhoinno
Copy link
Copy Markdown
Contributor

@inhoinno inhoinno commented May 19, 2026

Fix unsafe GC RU access (ruh-based lookup) and correct Cost-Benefit GC scoring/queueing

Description

Summary

Two independent bugs in hw/femu/bbssd/ftl.c affecting garbage collection
correctness on the FDP SSD FTL. This PR makes RU lookup safe by routing through
the owning RUH, and corrects the Cost-Benefit (CB) policy's victim selection
and queueing logic. Verified with fio random/sequential write workloads under
both Greedy and Cost-Benefit GC.

(1 file changed, +201 / -189)


Problem

Unsafe Reclaim Unit (RU) handling during GC
The previous GC path dereferenced RU pointers without going through the
owning Reclaim Unit Handle (RUH). This was fragile because "RU pointer could be stale
during GC process, clean_one_block_fdp_style(.., new_ru<-this), leading to GC operating on the wrong RU" / "a NULL


Solution

  1. Safe RU handling via ru->ruh
  • Reach RUs through their owning RUH rather than via the previously cached
    pointer.
  1. Correct Cost-Benefit logic and queueing

Testing

Tested Greedy and Cost-Benefit GC together with fio random-write and
sequential-write workloads across multiple runs. No crashes or invalid RU
accesses observed; Cost-Benefit now produces the expected victim
distribution and lower WAF than Greedy on the random-write workload.


Files

  • hw/femu/bbssd/ftl.c (+201 / -189)

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Code refactoring

Testing

  • I have tested my changes locally
  • I have added tests that prove my fix is effective or that my feature works
  • All existing tests pass
  • I have tested across multiple FEMU modes (if applicable)

FEMU Modes Tested

  • BlackBox SSD (BBSSD)
  • WhiteBox SSD (OCSSD)
  • Zoned Namespace SSD (ZNSSD)
  • NoSSD
  • Not applicable

Platform Testing

  • Ubuntu 20.04/22.04
  • Other distributions (specify): ___________
  • Build verification completed

Checklist

  • My code follows QEMU coding standards
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new compiler warnings
  • I have updated documentation if necessary
  • No trailing whitespace or C++ style comments in C files

Related Issues

Fixes #186

Additional Notes

  • Seqwrite Result : Pass without crasing
    fio
[global]
ioengine=io_uring_cmd
cmd_type=nvme
filename=/dev/ng0n1
;direct=1
iodepth=128
size=100%
loops=2
group_reporting=1

[seqwrite]
rw=write
bs=128k
numjobs=1
seqwrite: (g=0): rw=write, bs=(R) 128KiB-128KiB, (W) 128KiB-128KiB, (T) 128KiB-128KiB, ioengine=io_uring_cmd, iodepth=128
fio-3.36
Starting 1 process
Jobs: 1 (f=1): [W(1)][100.0%][w=530MiB/s][w=4240 IOPS][eta 00m:00s]
seqwrite: (groupid=0, jobs=1): err= 0: pid=1227: Tue May 19 06:03:13 2026
  write: IOPS=5661, BW=708MiB/s (742MB/s)(24.0GiB/34730msec); 0 zone resets
    slat (usec): min=3, max=48792, avg=60.16, stdev=650.91
    clat (nsec): min=270, max=148747k, avg=22548647.10, stdev=23298988.80
     lat (usec): min=783, max=148792, avg=22608.81, stdev=23295.36
    clat percentiles (usec):
     |  1.00th=[  1713],  5.00th=[  5473], 10.00th=[  7635], 20.00th=[  9896],
     | 30.00th=[ 11338], 40.00th=[ 12387], 50.00th=[ 13173], 60.00th=[ 14484],
     | 70.00th=[ 16712], 80.00th=[ 24249], 90.00th=[ 76022], 95.00th=[ 79168],
     | 99.00th=[ 89654], 99.50th=[ 95945], 99.90th=[113771], 99.95th=[135267],
     | 99.99th=[135267]
   bw (  KiB/s): min=405760, max=1271808, per=100.00%, avg=725849.04, stdev=275992.65, samples=69
   iops        : min= 3170, max= 9936, avg=5670.70, stdev=2156.19, samples=69
  lat (nsec)   : 500=0.02%, 750=0.01%
  lat (usec)   : 20=0.01%, 50=0.01%, 250=0.01%, 500=0.01%, 750=0.01%
  lat (usec)   : 1000=0.28%
  lat (msec)   : 2=0.88%, 4=1.54%, 10=18.11%, 20=55.09%, 50=10.56%
  lat (msec)   : 100=13.16%, 250=0.34%
  cpu          : usr=4.40%, sys=31.12%, ctx=69047, majf=0, minf=13
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
     issued rwts: total=0,196608,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=128

Run status group 0 (all jobs):
  WRITE: bw=708MiB/s (742MB/s), 708MiB/s-708MiB/s (742MB/s-742MB/s), io=24.0GiB (25.8GB), run=34730-34730msec
  • Randwrite Results : Pass without crasing
[global]
ioengine=io_uring_cmd
cmd_type=nvme
filename=/dev/ng0n1
;direct=1
iodepth=128
size=100%
loops=2
group_reporting=1

[seqwrite]
rw=randwrite
bs=128k
numjobs=1
femu@fvm:~$ sudo fio randwrite.fio
[sudo] password for femu: 
seqwrite: (g=0): rw=randwrite, bs=(R) 128KiB-128KiB, (W) 128KiB-128KiB, (T) 128KiB-128KiB, ioengine=io_uring_cmd, iodepth=128
fio-3.36
Starting 1 process
Jobs: 1 (f=1): [w(1)][100.0%][w=545MiB/s][w=4356 IOPS][eta 00m:00s] 
seqwrite: (groupid=0, jobs=1): err= 0: pid=1201: Tue May 19 05:22:39 2026
  write: IOPS=6099, BW=762MiB/s (799MB/s)(32.0GiB/42977msec); 0 zone resets
    slat (usec): min=6, max=429, avg=25.52, stdev=11.53
    clat (usec): min=1509, max=88425, avg=20957.79, stdev=21571.40
     lat (usec): min=1516, max=88442, avg=20983.31, stdev=21571.01
    clat percentiles (usec):
     |  1.00th=[ 3326],  5.00th=[ 5866], 10.00th=[ 8717], 20.00th=[12780],
     | 30.00th=[12780], 40.00th=[12780], 50.00th=[12780], 60.00th=[12780],
     | 70.00th=[13435], 80.00th=[19268], 90.00th=[70779], 95.00th=[79168],
     | 99.00th=[85459], 99.50th=[86508], 99.90th=[87557], 99.95th=[87557],
     | 99.99th=[88605]
   bw (  KiB/s): min=524288, max=1281280, per=100.00%, avg=783296.75, stdev=333034.67, samples=85
   iops        : min= 4096, max=10010, avg=6119.51, stdev=2601.83, samples=85
  lat (msec)   : 2=0.01%, 4=2.04%, 10=10.70%, 20=68.71%, 50=6.04%
  lat (msec)   : 100=12.50%
  cpu          : usr=6.23%, sys=12.90%, ctx=248719, majf=0, minf=10
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=100.0%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.1%
     issued rwts: total=0,262144,0,0 short=0,0,0,0 dropped=0,0,0,0
     latency   : target=0, window=0, percentile=100.00%, depth=128

Run status group 0 (all jobs):
  WRITE: bw=762MiB/s (799MB/s), 762MiB/s-762MiB/s (799MB/s-799MB/s), io=32.0GiB (34.4GB), run=42977-42977msec
  • Seq+Rand (mutliple fio runs to test ) also passed test (Omit result due to long fio run)

@inhoinno inhoinno merged commit aa5c41e into MoatLab:master May 20, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FDP GC crash in select_victim_ru() when removing RU from full_ru_list

1 participant