@@ -1378,6 +1378,19 @@ func (r *layerStore) pickStoreLocation(volatile, writeable bool) layerLocations
13781378 }
13791379}
13801380
1381+ func checkIdAndNameConflict (r * layerStore , id string , names []string ) error {
1382+ if _ , idInUse := r .byid [id ]; idInUse {
1383+ return ErrDuplicateID
1384+ }
1385+ names = dedupeStrings (names )
1386+ for _ , name := range names {
1387+ if _ , nameInUse := r .byname [name ]; nameInUse {
1388+ return ErrDuplicateName
1389+ }
1390+ }
1391+ return nil
1392+ }
1393+
13811394// Requires startWriting.
13821395func (r * layerStore ) create (id string , parentLayer * Layer , names []string , mountLabel string , options map [string ]string , moreOptions * LayerOptions , writeable bool , diff io.Reader , slo * stagedLayerOptions ) (layer * Layer , size int64 , err error ) {
13831396 if moreOptions == nil {
@@ -1400,14 +1413,9 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
14001413 _ , idInUse = r .byid [id ]
14011414 }
14021415 }
1403- if duplicateLayer , idInUse := r .byid [id ]; idInUse {
1404- return duplicateLayer , - 1 , ErrDuplicateID
1405- }
14061416 names = dedupeStrings (names )
1407- for _ , name := range names {
1408- if _ , nameInUse := r .byname [name ]; nameInUse {
1409- return nil , - 1 , ErrDuplicateName
1410- }
1417+ if err := checkIdAndNameConflict (r , id , names ); err != nil {
1418+ return nil , - 1 , err
14111419 }
14121420 parent := ""
14131421 if parentLayer != nil {
@@ -1448,9 +1456,6 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
14481456 selinux .ReserveLabel (mountLabel )
14491457 }
14501458
1451- // Before actually creating the layer, make a persistent record of it
1452- // with the incomplete flag set, so that future processes have a chance
1453- // to clean up after it.
14541459 layer = & Layer {
14551460 ID : id ,
14561461 Parent : parent ,
@@ -1474,6 +1479,41 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
14741479 }
14751480 layer .Flags [incompleteFlag ] = true
14761481
1482+ var (
1483+ cleanupFunctions []tempdir.CleanupTempDirFunc
1484+ applyDiffFunc func () error
1485+ applyDiffSize int64
1486+ )
1487+
1488+ applyDiffTemporaryDriver , ok := r .driver .(drivers.ApplyDiffStaging )
1489+ if ok && diff != nil {
1490+ // CRITICAL, this releases the lock so we can extract this unlocked
1491+ r .stopWriting ()
1492+
1493+ var applyDiffError error
1494+ cleanupFunctions , applyDiffFunc , applyDiffSize , applyDiffError = r .applyDiffUnlocked (applyDiffTemporaryDriver , layer , moreOptions , diff )
1495+ // We must try to cleanup reagrdless of if an error was returned or not.
1496+ defer tempdir .CleanupTemporaryDirectories (cleanupFunctions ... )
1497+ // Acquire the lock again, this releases the lock so we can extract this unlocked.
1498+ // This must be done before checking for the error from applyDiffUnlocked() so the caller doesn't try to unlock again.
1499+ // FIXME: if startWriting() fails we return unlocked and then the parent unlocks again causing a panic. We should try to avoid that case somehow.
1500+ if err := r .startWriting (); err != nil {
1501+ return nil , - 1 , fmt .Errorf ("re-acquire lock after applying layer diff: %w" , err )
1502+ }
1503+ if applyDiffError != nil {
1504+ return nil , - 1 , applyDiffError
1505+ }
1506+
1507+ if err := checkIdAndNameConflict (r , id , names ); err != nil {
1508+ logrus .Debugf ("Layer id %s or name from %v was created while staging the layer content unlocked, aborting layer creation" , id , names )
1509+ return nil , - 1 , err
1510+ }
1511+ }
1512+
1513+ // Before actually creating the layer, make a persistent record of it
1514+ // with the incomplete flag set, so that future processes have a chance
1515+ // to clean up after it.
1516+
14771517 r .layers = append (r .layers , layer )
14781518 // This can only fail if the ID is already missing, which shouldn’t
14791519 // happen — and in that case the index is already in the desired state
@@ -1568,7 +1608,13 @@ func (r *layerStore) create(id string, parentLayer *Layer, names []string, mount
15681608 }
15691609
15701610 size = - 1
1571- if diff != nil {
1611+ if applyDiffFunc != nil {
1612+ size = applyDiffSize
1613+ if err := applyDiffFunc (); err != nil {
1614+ cleanupFailureContext = "applying staged diff"
1615+ return nil , - 1 , err
1616+ }
1617+ } else if diff != nil {
15721618 if size , err = r .applyDiffWithOptions (layer , moreOptions , diff ); err != nil {
15731619 cleanupFailureContext = "applying layer diff"
15741620 return nil , - 1 , err
@@ -2404,6 +2450,66 @@ func (r *layerStore) ApplyDiff(to string, diff io.Reader) (size int64, err error
24042450
24052451type diffApplyFunc func (id string , parent string , options drivers.ApplyDiffOpts , tsBytes * bytes.Buffer ) error
24062452
2453+ func (r * layerStore ) applyDiffUnlocked (dd drivers.ApplyDiffStaging , layer * Layer , layerOptions * LayerOptions , diff io.Reader ) ([]tempdir.CleanupTempDirFunc , func () error , int64 , error ) {
2454+ var (
2455+ size int64
2456+ cleanFunctions []tempdir.CleanupTempDirFunc
2457+ applyDiff func () error
2458+ )
2459+
2460+ f := func (id string , parent string , options drivers.ApplyDiffOpts , tsBytes * bytes.Buffer ) error {
2461+ var (
2462+ err error
2463+ cleanup tempdir.CleanupTempDirFunc
2464+ commit tempdir.CommitFunc
2465+ )
2466+ cleanup , commit , size , err = dd .StartStagingDiffToApply (layer .ID , layer .Parent , options )
2467+ cleanFunctions = append (cleanFunctions , cleanup )
2468+ if err != nil {
2469+ return err
2470+ }
2471+
2472+ td , err := tempdir .NewTempDir (filepath .Join (r .layerdir , tempDirPath ))
2473+ cleanFunctions = append (cleanFunctions , td .Cleanup )
2474+ if err != nil {
2475+ return err
2476+ }
2477+
2478+ sa , err := td .StageFileAddition (func (path string ) error {
2479+ return os .WriteFile (path , tsBytes .Bytes (), 0o600 )
2480+ })
2481+ cleanFunctions = append (cleanFunctions , td .Cleanup )
2482+ if err != nil {
2483+ return err
2484+ }
2485+
2486+ applyDiff = func () error {
2487+ err := dd .CommitStagedLayer (layer .ID , commit )
2488+ if err != nil {
2489+ return fmt .Errorf ("commit temporary layer: %w" , err )
2490+ }
2491+
2492+ if err := os .MkdirAll (filepath .Dir (r .tspath (layer .ID )), 0o700 ); err != nil {
2493+ return err
2494+ }
2495+
2496+ err = sa .Commit (r .tspath (layer .ID ))
2497+ if err != nil {
2498+ return fmt .Errorf ("commit tar split file: %w" , err )
2499+ }
2500+ return nil
2501+ }
2502+ return nil
2503+ }
2504+
2505+ err := r .applyDiffWithOptionsInner (layer , layerOptions , diff , f )
2506+ if err != nil {
2507+ return cleanFunctions , nil , 0 , err
2508+ }
2509+
2510+ return cleanFunctions , applyDiff , size , nil
2511+ }
2512+
24072513// Requires startWriting.
24082514func (r * layerStore ) applyDiffWithOptions (layer * Layer , layerOptions * LayerOptions , diff io.Reader ) (int64 , error ) {
24092515 var size int64
@@ -2422,7 +2528,12 @@ func (r *layerStore) applyDiffWithOptions(layer *Layer, layerOptions *LayerOptio
24222528 return nil
24232529 }
24242530
2425- return size , r .applyDiffWithOptionsInner (layer , layerOptions , diff , f )
2531+ err := r .applyDiffWithOptionsInner (layer , layerOptions , diff , f )
2532+ if err != nil {
2533+ return 0 , err
2534+ }
2535+
2536+ return size , r .saveFor (layer )
24262537}
24272538
24282539func (r * layerStore ) applyDiffWithOptionsInner (layer * Layer , layerOptions * LayerOptions , diff io.Reader , applyFunc diffApplyFunc ) (err error ) {
@@ -2545,9 +2656,7 @@ func (r *layerStore) applyDiffWithOptionsInner(layer *Layer, layerOptions *Layer
25452656 }
25462657 slices .Sort (layer .GIDs )
25472658
2548- err = r .saveFor (layer )
2549-
2550- return err
2659+ return nil
25512660}
25522661
25532662// Requires (startReading or?) startWriting.
0 commit comments