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 <stephen.day@docker.com>
This commit is contained in:
Stephen J Day 2017-07-24 12:13:37 -07:00
parent ba577f7115
commit d0e396aa60
No known key found for this signature in database
GPG Key ID: 67B3DED84EDC823F
2 changed files with 16 additions and 11 deletions

View File

@ -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 (

View File

@ -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