The Specification of POSIX File Systems Gian Ntzik, Pedro da Rocha Pinto and Philippa Gardner Imperial College London gian.ntzik08@imperial.ac.uk pedro.da-rocha-pinto09@imperial.ac.uk p.gardner@imperial.ac.uk INVEST 2017 1/13
Logics for Specifying Concurrent Programs Owicki-Gries (1976) Rely-Guarantee (1983) CSL (2004) Bornat-at (2005) RGSep (2007) SAGL (2007) Gotsman-al (2007) Deny-Guarantee (2009) LRG (2009) RSL (2013) CAP (2010) Jacobs-Piessens (2011) HLRG (2010) HOCAP (2013) SCSL (2013) RGSim (2012) iCAP (2014) TaDA (2014) Liang-Feng (2013) FTCSL (2015) CaReSL (2013) Iris (2015) GPS (2014) FCSL (2014) CoLoSL (2015) LiLi (2016) Iris 2.0 (2016) Total-TaDA (2016) Thanks, Ilya Sergey. 2/13
POSIX File Systems • The POSIX standard is written in English • Several formal sequential specifications have been given: - not good for client reasoning if based on first-order logic; - good for client reasoning if based on separation logic. • The English specification of the concurrent behaviour is poor. • We have the first concurrent specification of POSIX file systems. 3/13
A POSIX operation: unlink ( / usr / bin / git ) unlink ( / usr / bin / git ) takes a sequence of atomic actions 0 tmp usr 1 2 share local .X0-lock bin 3 0101111011... 8 5 4 lib git 7 0110011011... 9 4/13
unlink ( / usr / bin / git ): a Sequence of Atomic Actions unlink(/usr/bin/git) usr bin git FS 1 FS 1 FS 2 FS 2 FS 3 FS 4 Environment: mupltiple atomic updates Thread: single atomic read in path traversal Thread: single atomic update 5/13
Concurrent Specification of unlink ( path ) unlink ( path ) ⊑ let p = dirname ( path ); let a = basename ( path ); let r = resolve ( p , ι 0 ); if ¬ iserr( r ) then return link delete ( r , a ) ⊔ link delete notdir ( r , a ) else return r fi • link delete ( r , a ) atomically removes link a , even if it links a directory • link delete notdir ( r , a ) atomically removes link a , only if it does not link a directory • ⊔ : non-deterministic angelic choice 6/13
Concurrent Specification of path resolution letrec resolve ( path , ι ) � if path = null then return ι else let a = head ( path ); let p = tail ( path ); let r = link lookup ( ι, a ); if iserr( r ) then return r else return resolve ( p , r ) fi fi • link lookup ( ι, a ) atomically lookup the link named a in the directory with inode ι . 7/13
Concurrent Specification of unlink ( path ) unlink ( path ) ⊑ let p = dirname ( path ); let a = basename ( path ); let r = resolve ( p , ι 0 ); if ¬ iserr( r ) then return link delete ( r , a ) ⊔ link delete notdir ( r , a ) else return r fi 8/13
Concurrent Specification of unlink ( path ) unlink ( path ) ⊑ let p = dirname ( path ); let a = basename ( path ); let r = resolve ( p , ι 0 ); if ¬ iserr( r ) then return link delete ( r , a ) ⊔ link delete notdir ( r , a ) else return r fi link delete ( ι, a ) � � fs( FS ) ∧ isdir( FS ( ι )) , a ∈ FS ( ι ) = ⇒ fs( FS [ ι �→ FS ( ι ) \ { a } ]) ∗ ret = 0 � A FS . ⊓ return enoent ( ι, a ) ⊓ return enotdir ( ι ) enoent ( ι, a ) and enotdir ( ι ) describe error cases. ⊓ is non-deterministic demonic choice. 8/13
Concurrent specification of link ( source , target ) link ( source , target ) ⊑ let p s = dirname ( source ); let a = basename ( source ); let p t = dirname ( target ); let b = basename ( target ); let r s , r t = resolve ( p s , ι 0 ) � resolve ( p t , ι 0 ); if ¬ iserr( r s ) ∧ ¬ iserr( r t ) then return link insert ( r s , a , r t , b ) ⊔ link insert notdir ( r s , a , r t , b ) else if iserr( r s ) ∧ ¬ iserr( r t ) then return r s else if ¬ iserr( r s ) ∧ iserr( r t ) then return r t else if iserr( r s ) ∧ iserr( r t ) then return r s ⊔ return r t fi 9/13
Lock-file Client ◮ lock ( path ): atomically create a non-existing lock file at path ◮ unlock ( path ): remove the lock file identified by path ◮ Implemented similarly to spin locks ◮ open ( path , O CREAT | O EXCL ) to try to lock ◮ unlink to unlock 10/13
Lock-file Protocol Agreement We want the module and the environment to agree on a boundary 0 tmp usr LF 1 2 share .X0-lock local bin 3 8 5 4 lib git 7 0110011011... 9 11/13
Lock-file Specification � � LF( path ) ⊢ lock ( path ) ⊑ v ∈ { 0 , 1 } . Lock( path , v ) , Lock( path , 1) ∗ v = 0 A � � LF( path ) ⊢ unlock ( path ) ⊑ Lock( path , 1) , Lock( path , 0) ◮ LF( path ) is a context invariant denoting what the implementation and the environment can and cannot do to the path: ◮ The path-prefix of path is not changed (everyone can only read) ◮ Only the module create the lock file at path (locks the lock) ◮ Only the module removes the lock file at path (unlocks the lock) 12/13
Conclusions • Concurrent specification of the POSIX file system (fragment) • Combination of the refinement calculus and a modern concurrent separation logic called TaDA • Client reasoning: lock files, named pipes, email server • Future: executable specification which we can test against implementations • Future: now what about distribution.... 13/13
Recommend
More recommend