<<

Using Concurrent Relational Logic with Helpers for Verifying the AtomFS System

Mo Zou1, Haoran Ding1, Dong Du1, Ming Fu2, Ronghui Gu3, Haibo Chen12 1 IPADS, Shanghai Jiao Tong University 2 Huawei Technologies Co. Ltd 3 Columbia University File systems are buggy and underspecified

• 40% of FS patches fix bugs [Lu et al., FAST’13] – 20% of the bugs are concurrency bugs • Hard to eliminate due to many possible interleavings

• POSIX is vague about concurrent behavior – E.g., unclear whether an operation should be atomic – Hard to reason about higher-level applications

2 Approach: formal verification

• Concurrent implementation meets specification – Under arbitrary interleavings – Proof checked by proof assistant (Coq) • Avoid large classes of bugs • Specification serves as a precise interface

3 Verification efforts

• File system verification – FSCQ project [SOSP’15,SOSP’17,Tej M.S. thesis] No fine-grained – Yggdrasil [OSDI’16] concurrency – Cogent [ASPOLOS’16] • Concurrent system verification – CertiKOS [OSDI’16] Not applicable – CSPEC [OSDI’18] to FS Goal: verify a fine-grained, concurrent file system 4 Contributions

• CRL-H: Concurrent Relation Logic with Helpers for concurrent file systems – Helper mechanism – Proofs mechanically checked by Coq • AtomFS: the first verified concurrent FS with fine-grained locking – Fine-grained: per-inode lock (no crash-safety) – Atomic interfaces – Verified directly in C language

5 How to specify “correct”?

(/a), succss (/b), failure Sequential Sequential file system

For a sequential file system, correct if sequential history is legal

unlink(/b), failure Concurrent Concurrent file system execution mkdir(/a), succss

How to describe concurrent via sequential?

6 This work: “correct” means linearizability

Linearizability: describe concurrent via sequential unlink(/b), failure Concurrent execution mkdir(/a), succss map to Sequential history

linearization point (LP)---effect happens atomically Correct if equivalent “sequential” history is legal

7 Prove linearizability via forward simulation

multi steps LP multi steps mkdir C0 Ci Ci+1 Cn Concrete state

Equivalent effect

Abstract MKDIR A0 A1 Abstract state MKDIR(/a/b) / / Define abstract a state and abstract a b operation Abstract file system

as a 8 Prove linearizability via forward simulation

multi steps LP multi steps mkdir C0 Ci Ci+1 Cn Concrete state effect

Abstract MKDIR A0 A1 Abstract state effect Decide linearization point Define abstraction relation mkdir MKDIR 9 Prove linearizability via forward simulation

Simulation proof unlink(/b), failure LP C0 Ci Ci+1 Cn Concurrent effect execution mkdir(/a), success Abstraction relation A0 A1 effect

Linearization Proven by Liang et al, PLDI’13 MKDIR(/a), success UNLINK(/b), failure Filipovic, ESOP’09

Construct linearization of abstract operation Linearizability following temporal order of LPs

10 Strawman: fixed LP in critical section

/* error and corner cases Pattern of path-based operations mkdir(path) handling omitted*/ def mkdir(path) (path, dir, name); 1. Invocation begins

// traverse path from root look(root); 2. Pathname resolution fat = (root, dir);

// fat’s lock is held node = init(); 3. Lock-protected critical insert(fat, name, node); section (where updates LP of mkdir happen) unlock(fat); 4. Invocation returns return success; 11 Strawman: fixed LP in critical section

begin lookup LP return mkdir(path)

begin lookup LP return rename(src, dst)

If fixed LP is correct and We can construct linearization implementation is linearizable for any concurrent execution

12 Challenge: fixed LP could fail in linearization Two threads begin lookup LP success mkdir(/a/b/c)

rename(/a,/d) begin lookup LP success

/ a b Initially

13 Challenge: fixed LP could fail in linearization Two threads begin lookup LP success mkdir(/a/b/c)

rename(/a,/d) begin lookup LP success

/ / a a b b Initially mkdir traverses to b 14 Challenge: fixed LP could fail in linearization Two threads begin lookup LP success mkdir(/a/b/c)

rename(/a,/d) begin lookup LP success

/ / / d a a b b b Initially mkdir traverses rename finishes to b 15 Challenge: fixed LP could fail in linearization Two threads begin lookup LP success mkdir(/a/b/c)

rename(/a,/d) begin lookup LP success / / / / d d a a b b b b c Initially mkdir traverses rename finishes mkdir succeeds to b Legal interleaving 16 Challenge: fixed LP could fail in linearization begin lookup LP success mkdir(/a/b/c)

rename(/a,/d) begin lookup LP success Map to abstract operation

Not legal RENAME(/a, /d) MKDIR(/a/b/c) success success (Should be failure) 17 Challenge: fixed LP could fail in linearization begin lookup LP success mkdir(/a/b/c)

rename(/a,/d) begin lookup LP success ? Legal Cannot obtain legal linearization using fixed LPs MKDIR(/a/b/c) RENAME(/a, /d) success success Check other cases All failed cases involve rename 18 Observation: rename modifies other Op’s traversed path

• We call this phenomenon path inter-dependency – Rename, only operation that can modify an internal inode

mkdir(/a/b/c) LP /

rename(/a,/d) LP d

b Path inter- dependency Allowed by fine-grained implementation 19 Should consider path inter-dependency in linearization

/ RENAME(/a,/d) Linearization strategy break MKDIR(/a/b/c)’s (linearize LPs) is insufficient d path integrity b

linearize before Fix linearization strategy to consider path inter-dependency RENAME(/a, /d) MKDIR(/a/b/c)

Approach: also linearize when path inter-dependency happens 20 Approach: linearize when path inter-dependency happens

/ mkdir(/a/b/c)⤻ success fixed LP Concurrent a rename(/a, /d) success fixed LP execution b ⤻ rename helps external LP commit mkdir Sequential history MKDIR(/a/b/c) RENAME(/a, /d) success success

• The LP of Op1 (e.g., mkdir) resides in another Op2 (e.g., rename) – This kind of LP is called external linearization point • For path-based Op, LP could be internal (“fixed LP”) or external (triggered by rename) 21 Helping: linearize abstract operations of other threads

• Helping: linearize abstract operations of other threads [Liang et al, PLDI’13]

Shared thread pool E.g., (mkdir, args) or Exist logically in (mkdir end, ret) abstract model Thread ID AopState … …

Current thread t-2: rename Linearized t-1 (mkdir, args) t-1 (mkdir end, ret) Helping

22 File system-specific challenges

threads to (for a rename)? • Helping order? • Handle recursive path inter-dependency root rename

mkdir create stat Help many Decide helping set and order

23 File system-specific challenges

• Which threads to help (for a rename)? • Helping order? rename-1 • Handle recursive path inter-dependency

rename-2 Path inter- dependency … rename-3 Recursive path inter-dependency

24 Helpers: extend helping with file system-specific notions

• Helper metadata provides global information – E.g., add “lock path” in Descriptor to record traversed path

• Decide whether Op1 should be linearized before Op2 – E.g., rename can use “lock path” to decide which threads to help

root Helper metadata Linearize before rename Shared thread pool Thread ID AopState Descriptor … mkdir create stat Helper extensions Should be helped 25 Read paper Specifying and proving with CRL-H for details CRL-H framework: Concurrent Relation Logic with Helpers Rely; Guarantee; Invariant ⊢ {Pre ∗ (aop, args)} Code {Post ∗ (aop end, ret)}

Specification Implementation Abstraction Concurrent file Local rely guarantee Invariants /G conditions and Aops system code for fine-grained concurrency Import to Coq Inference rule Proof modelled C

Simulation Compile with with helpers C compiler

Linearizability Fuse/Kernel FS 26 Read paper Specifying and proving with CRL-H for details CRL-H framework: Concurrent Relation Logic with Helpers Rely; Guarantee; Invariant ⊢ {Pre ∗ (aop, args)} Code {Post ∗ (aop end, ret)} RENAME rename(args) Specification Implementation Abstraction Concurrent file Local rely guarantee Invariants R/G conditions and Aops system code for fine-grained concurrency Import to Coq Inference rule Proof modelled C Relational reasoning

Simulation Compile with with helpers C compiler

Linearizability Fuse/Kernel FS 27 Read paper Specifying and proving with CRL-H for details CRL-H framework: Concurrent Relation Logic with Helpers Rely; Guarantee; Invariant ⊢ {Pre ∗ (aop, args)} Code {Post ∗ (aop end, ret)} RENAME rename(args) Specification Implementation Abstraction Concurrent file Local rely guarantee Invariants R/G conditions and Aops system code for fine-grained concurrency Import to Coq Inference rule Proof modelled C Relational reasoning Inference rule Simulation Compile with with helpers C compiler

Linearizability Fuse/Kernel FS 28 Read paper Specifying and proving with CRL-H for details CRL-H framework: Concurrent Relation Logic with Helpers Rely; Guarantee; Invariant ⊢ {Pre ∗ (aop, args)} Code {Post ∗ (aop end, ret)} RENAME rename(args) Specification Implementation Abstraction Concurrent file Local rely guarantee Invariants R/G conditions and Aops system code for fine-grained concurrency Import to Coq Inference rule Proof modelled C Relational reasoning Inference rule Simulation Compile with with helpers C compiler Correctness theorem

Linearizability Fuse/Kernel FS 29 Read paper Specifying and proving with CRL-H for details CRL-H framework: Concurrent Relation Logic with Helpers Rely; Guarantee; Invariant ⊢ {Pre ∗ (aop, args)} Code {Post ∗ (aop end, ret)} RENAME rename(args) Specification Implementation Abstraction Concurrent file Local rely guarantee Invariants R/G conditions and Aops system code for fine-grained concurrency Import to Coq Inference rule Proof modelled C Relational reasoning Inference rule Simulation Compile with with helpers C compiler Correctness theorem C language modeling Linearizability Fuse/Kernel FS 30 Invariants in proving AtomFS

Abstract-concrete relation Finding all and precise specification Non-bypassable invariant is difficult! Invariants Good-FS-Tree Helper-metadata-consistency Always … hold on Necessary for simulation proof Shared states Abstract & concrete tree Helper metadata

31 Operation bypassing leads to non-linearizability

/ Op-2 holds no Op-1 a lock

b

c Op-1 bypasses Op-2

32 Operation bypassing leads to non-linearizability

Read paper for a concrete case Path inter- Op-1 bypasses op-2 dependency and modifies the state op-2 will use

Concurrent rename op-1 execution op-2 op-2 ⤻ return Illegal Sequential Op-2 return RENAME Op-1 history ⤻

Construct a non-linearizable interleaving 33 Lock coupling forbids operation bypassing

2. Release current • Non-bypassable invariant to capture the / property Op-2 Op-1 a • Cons: reduce parallelism • Pros: ensure linearizability b 1. Acquire next – Easier to reason about for users

c Tradeoff between Forbid bypassing by always holding a lock performance and reasoning!

34 Implementing CRL-H and AtomFS in Coq

• 1.5 years of effort, including building the framework and proving AtomFS

• CRL-H, ~100k LOC Basic libraries 34,820 – can be reused AtomFS 63,099 • AtomFS Machine & – 673 lines of C code logic 38,904 – 2k lines of specification Proof automation – 60k lines of proof 24,387

35 Evaluation: AtomFS achieves reasonable performance

• Single core performance • Faster than DFSCQ (1.38x-2.52x) – Avoid Haskell overhead 20 dfscq 17.5 atomfs tmpfs • Slower than ext4 and tmpfs 15 ext4 12.5 – FUSE overhead 10 – 7.5 Simplified data strucutre 5 Running (seconds) 2.5 0 largefile smallfile git-clone -xv6 -qemu ripgrep 36 Evaluation: AtomFS achieves reasonable performance

• Multicore scalability 8 AtomFS ext4 7

• Better scalability than ext4 6 – Not bypass VFS-level path lookup 5 – Bottleneck: lock coupling traverse Speedup 4 3 • Worse performance than ext4 2 1 2 4 6 8 10 12 14 16 – 6.39x lower throughput with 16cores Thread Number – Not implement optimizations Speedup on Fileserver (compared to single core)

37 Conclusion

• CRL-H: specify and prove concurrent file systems – Path inter-dependency and external LP challenge – Helper mechanism • AtomFS: first verified concurrent FS with fine-grained locking – Atomic interfaces – Reasonable performance

https://ipads.se.sjtu.edu.cn/projects/atomfs Thanks!

38