{
  "schemaVersion": 1,
  "slug": "fsync-retry-model",
  "evidenceType": "illustrative-model",
  "version": "1.0.0",
  "updated": "2026-10-10",
  "author": "Hesela",
  "license": "CC0-1.0",
  "sourceCode": "https://hesela.com/research/fsync-retry-model.mjs",
  "article": "https://hesela.com/analyses/fsync-failure-retry-durability/",
  "assumptions": [
    "One file value, one writer, one transient failed writeback, then no further failures.",
    "The first sync reports and consumes the pending error.",
    "A retry writes only dirty cached data; no background writeback occurs.",
    "A simulated restart or eviction discards cached state without repairing disk.",
    "Rewrite uses an independent known-good new value, not an untrusted cache read."
  ],
  "limitations": "Not empirical data, not a Linux emulator, and not a reproduction of CuttleFS. No metadata, directories, torn writes, concurrency, device caches or real system calls.",
  "cases": [
    {
      "id": "clean-retained-retry",
      "keepDirty": false,
      "evict": false,
      "rewrite": false,
      "firstSync": "EIO",
      "retry": "success",
      "cachedRead": "new",
      "afterCacheLoss": "old",
      "durableNewValue": false,
      "events": [
        {
          "event": "write",
          "cache": "new",
          "disk": "old",
          "dirty": true
        },
        {
          "event": "sync-error",
          "result": "EIO",
          "cache": "new",
          "disk": "old",
          "dirty": false
        },
        {
          "event": "retry-sync",
          "result": "success",
          "cache": "new",
          "disk": "old",
          "dirty": false
        }
      ]
    },
    {
      "id": "clean-evicted-retry",
      "keepDirty": false,
      "evict": true,
      "rewrite": false,
      "firstSync": "EIO",
      "retry": "success",
      "cachedRead": "old",
      "afterCacheLoss": "old",
      "durableNewValue": false,
      "events": [
        {
          "event": "write",
          "cache": "new",
          "disk": "old",
          "dirty": true
        },
        {
          "event": "sync-error",
          "result": "EIO",
          "cache": "new",
          "disk": "old",
          "dirty": false
        },
        {
          "event": "evict-and-read",
          "cache": "old",
          "disk": "old",
          "dirty": false
        },
        {
          "event": "retry-sync",
          "result": "success",
          "cache": "old",
          "disk": "old",
          "dirty": false
        }
      ]
    },
    {
      "id": "dirty-retained-retry",
      "keepDirty": true,
      "evict": false,
      "rewrite": false,
      "firstSync": "EIO",
      "retry": "success",
      "cachedRead": "new",
      "afterCacheLoss": "new",
      "durableNewValue": true,
      "events": [
        {
          "event": "write",
          "cache": "new",
          "disk": "old",
          "dirty": true
        },
        {
          "event": "sync-error",
          "result": "EIO",
          "cache": "new",
          "disk": "old",
          "dirty": true
        },
        {
          "event": "retry-sync",
          "result": "success",
          "cache": "new",
          "disk": "new",
          "dirty": false
        }
      ]
    },
    {
      "id": "clean-retained-rewrite",
      "keepDirty": false,
      "evict": false,
      "rewrite": true,
      "firstSync": "EIO",
      "retry": "success",
      "cachedRead": "new",
      "afterCacheLoss": "new",
      "durableNewValue": true,
      "events": [
        {
          "event": "write",
          "cache": "new",
          "disk": "old",
          "dirty": true
        },
        {
          "event": "sync-error",
          "result": "EIO",
          "cache": "new",
          "disk": "old",
          "dirty": false
        },
        {
          "event": "rewrite-from-independent-copy",
          "cache": "new",
          "disk": "old",
          "dirty": true
        },
        {
          "event": "retry-sync",
          "result": "success",
          "cache": "new",
          "disk": "new",
          "dirty": false
        }
      ]
    }
  ]
}
