| ⟨awbuf_write_buf#(n, buf, adr, m, nx, lpt, ns, buffered(m1); avol, isbuf; err)⟩ (avol = avol1 ∧ (isbuf ↔ isbuf0) ∧ err = err0), # lpt = # avol, avol[m1] = mapped(buf0), bleb = buffered(m1), m0 = m, n0 = n, m1 < # avol, awbuf-inv(avol, buffered(m1)), avol0 ↓ avol1, # avol[bleb.leb].data + n0 ≤ LEB_SIZE, n0 ≤ # buf, n ≤ # buf, # buf0 + n ≤ LEB_SIZE, bleb ≠ nobuffer → avol[bleb.leb].mapped? ∧ bleb.leb < # avol ∧ bleb.isbuf? ⊦ ⟨if isbuf then err := EROFS else {fail_or_success#(; ; err); let m = bleb.leb in if err = ESUCCESS then avol[m] := mapped(avol[m].data + subarray(buf, 0, n0)) else { choose n with n ≠ 0 ∧ n < n0 ∧ is-aligned(# avol[m].data + n, EB_PAGE_SIZE) in avol[m] := mapped(avol[m].data + subarray(buf, 0, n)) ifnone skip or skip; isbuf := true}}⟩ (synced(avol) ∧ avol0 ↓ avol), bleb = nobuffer, avol0 ↓ avol |
⟨awbuf_write_buf#(n, buf, adr, m, nx, lpt, ns, buffered(m1); avol, isbuf; err)⟩ (avol = avol1 ∧ (isbuf ↔ isbuf0) ∧ err = err0), # lpt = # avol, avol[m1] = mapped(buf0), m1 < # avol, awbuf-inv(avol, buffered(m1)), avol0 ↓ avol1, n ≤ # buf, # buf0 + n ≤ LEB_SIZE, ¬ avol0 ↓ avol ⊦ ⟨if isbuf then err := EROFS else {fail_or_success#(; ; err); let m = buffered(m1).leb in if err = ESUCCESS then avol[m] := mapped(avol[m].data + subarray(buf, 0, n)) else { choose n1 with n1 ≠ 0 ∧ n1 < n ∧ is-aligned(# avol[m].data + n1, EB_PAGE_SIZE) in avol[m] := mapped(avol[m].data + subarray(buf, 0, n1)) ifnone skip or skip; isbuf := true}}⟩ (synced(avol) ∧ avol0 ↓ avol)
Used simplifier rules: fwd-buffered-mapped: ⊦ awbuf-inv(avol, buffered(n)) → n < # avol ∧ avol[n].mapped?;% ⊦ mapped(buf).data = buf; (s)% ⊦ mapped(buf) = mapped(buf0) ↔ buf = buf0; (s)%inv-buf-in-vol: ⊦ awbuf-inv(avol, buffered(n)) → n < # avol; (forward) from specification awbuf-inv%lf-01: ⊦ m < n ∧ n = n0 → m < n0; (forward) from specification nat-basic% ⊦ aleb.mapped? ↔ (∃ buf. aleb = mapped(buf)); (as)% ⊦ buffered(m).isbuf?; (s)% ⊦ buffered(m).leb = m; (s)% ⊦ nobuffer ≠ buffered(m); (s)