From 70004549fbfa2e1c7ac43e79ffe89f8d0cb416fd Mon Sep 17 00:00:00 2001 From: Jan Scheffler Date: Thu, 11 Dec 2025 13:53:13 +0000 Subject: [PATCH] layer: Fix orphan creation in registerWithDescriptor Start the metadata transaction before creating the overlay2 directory. This ensures that if driver.Create() fails, we can properly cancel the transaction. Previously, if StartTransaction() failed after driver.Create() succeeded, the defer cleanup would not run (not registered yet), leaving an orphaned overlay2 directory. The fix reorders operations so that: 1. Transaction is started first (no filesystem changes yet) 2. Overlay2 directory is created second (transaction ready for cleanup) 3. Defer is registered after both succeed (tx is guaranteed non-nil) If driver.Create() fails, the transaction is explicitly cancelled before returning. The nil check for tx in the defer is no longer needed since tx is guaranteed to exist when the defer runs. Related to moby/moby#45939 Signed-off-by: Jan Scheffler --- daemon/internal/layer/layer_store.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/daemon/internal/layer/layer_store.go b/daemon/internal/layer/layer_store.go index 69d58540bb..5366f85085 100644 --- a/daemon/internal/layer/layer_store.go +++ b/daemon/internal/layer/layer_store.go @@ -294,12 +294,15 @@ func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, descr descriptor: descriptor, } - if cErr = ls.driver.Create(layer.cacheID, pid, nil); cErr != nil { + tx, cErr := ls.store.StartTransaction() + if cErr != nil { return nil, cErr } - tx, cErr := ls.store.StartTransaction() - if cErr != nil { + if cErr = ls.driver.Create(layer.cacheID, pid, nil); cErr != nil { + if err := tx.Cancel(); err != nil { + log.G(context.TODO()).WithFields(log.Fields{"cache-id": layer.cacheID, "error": err}).Error("Error canceling metadata transaction") + } return nil, cErr }