From d0e396aa60dd20d96a5bc35d7c24f8b24227d231 Mon Sep 17 00:00:00 2001 From: Stephen J Day Date: Mon, 24 Jul 2017 12:13:37 -0700 Subject: [PATCH] metadata: defer ingest lock to backend Because the lock on an ingest ref being held regardless of whether a writer was in use, resuming an existing ingest proved impossible. We now defer writer locking to the content store backend, where the lock will be released automatically on closing the writer or on restarting containerd. There are still cases where a writer can be abandoned but not closed, leaving an active ingest, but this is extremely rare and can be resolved with a daemon restart. Signed-off-by: Stephen J Day --- content/local/store.go | 2 +- metadata/content.go | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/content/local/store.go b/content/local/store.go index dd415c78d..170a84f98 100644 --- a/content/local/store.go +++ b/content/local/store.go @@ -271,7 +271,7 @@ func (s *store) Writer(ctx context.Context, ref string, total int64, expected di path, refp, data := s.ingestPaths(ref) if err := tryLock(ref); err != nil { - return nil, errors.Wrapf(err, "locking %v failed", ref) + return nil, errors.Wrapf(err, "locking ref %v failed", ref) } var ( diff --git a/metadata/content.go b/metadata/content.go index 47e841243..811a91912 100644 --- a/metadata/content.go +++ b/metadata/content.go @@ -303,18 +303,23 @@ func (cs *contentStore) Writer(ctx context.Context, ref string, size int64, expe return err } - if len(bkt.Get([]byte(ref))) > 0 { - return errors.Wrapf(errdefs.ErrUnavailable, "ref %v is currently in use", ref) - } + var ( + bref string + brefb = bkt.Get([]byte(ref)) + ) - sid, err := bkt.NextSequence() - if err != nil { - return err - } + if brefb == nil { + sid, err := bkt.NextSequence() + if err != nil { + return err + } - bref := createKey(sid, ns, ref) - if err := bkt.Put([]byte(ref), []byte(bref)); err != nil { - return err + bref = createKey(sid, ns, ref) + if err := bkt.Put([]byte(ref), []byte(bref)); err != nil { + return err + } + } else { + bref = string(brefb) } // Do not use the passed in expected value here since it was