Browse code

LCOW: Refactor to multiple layer-stores based on feedback

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2017/09/20 04:14:46
Showing 54 changed files
... ...
@@ -102,6 +102,6 @@ type Image interface {
102 102
 type ReleaseableLayer interface {
103 103
 	Release() error
104 104
 	Mount() (containerfs.ContainerFS, error)
105
-	Commit(platform string) (ReleaseableLayer, error)
105
+	Commit() (ReleaseableLayer, error)
106 106
 	DiffID() layer.DiffID
107 107
 }
... ...
@@ -357,7 +357,7 @@ func addNodesForLabelOption(dockerfile *parser.Node, labels map[string]string) {
357 357
 // coming from the query parameter of the same name.
358 358
 //
359 359
 // TODO: Remove?
360
-func BuildFromConfig(config *container.Config, changes []string) (*container.Config, error) {
360
+func BuildFromConfig(config *container.Config, changes []string, os string) (*container.Config, error) {
361 361
 	if len(changes) == 0 {
362 362
 		return config, nil
363 363
 	}
... ...
@@ -395,6 +395,7 @@ func BuildFromConfig(config *container.Config, changes []string) (*container.Con
395 395
 	// We make mutations to the configuration, ensure we have a copy
396 396
 	dispatchRequest.state.runConfig = copyRunConfig(config)
397 397
 	dispatchRequest.state.imageID = config.Image
398
+	dispatchRequest.state.operatingSystem = os
398 399
 	for _, cmd := range commands {
399 400
 		err := dispatch(dispatchRequest, cmd)
400 401
 		if err != nil {
... ...
@@ -28,7 +28,7 @@ func newContainerManager(docker builder.ExecBackend) *containerManager {
28 28
 }
29 29
 
30 30
 // Create a container
31
-func (c *containerManager) Create(runConfig *container.Config, hostConfig *container.HostConfig, platform string) (container.ContainerCreateCreatedBody, error) {
31
+func (c *containerManager) Create(runConfig *container.Config, hostConfig *container.HostConfig) (container.ContainerCreateCreatedBody, error) {
32 32
 	container, err := c.backend.ContainerCreate(types.ContainerCreateConfig{
33 33
 		Config:     runConfig,
34 34
 		HostConfig: hostConfig,
... ...
@@ -261,8 +261,8 @@ func dispatchOnbuild(d dispatchRequest, c *instructions.OnbuildCommand) error {
261 261
 func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
262 262
 	runConfig := d.state.runConfig
263 263
 	var err error
264
-	optionsOS := system.ParsePlatform(d.builder.options.Platform).OS
265
-	runConfig.WorkingDir, err = normalizeWorkdir(optionsOS, runConfig.WorkingDir, c.Path)
264
+	baseImageOS := system.ParsePlatform(d.state.operatingSystem).OS
265
+	runConfig.WorkingDir, err = normalizeWorkdir(baseImageOS, runConfig.WorkingDir, c.Path)
266 266
 	if err != nil {
267 267
 		return err
268 268
 	}
... ...
@@ -278,7 +278,7 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
278 278
 	}
279 279
 
280 280
 	comment := "WORKDIR " + runConfig.WorkingDir
281
-	runConfigWithCommentCmd := copyRunConfig(runConfig, withCmdCommentString(comment, optionsOS))
281
+	runConfigWithCommentCmd := copyRunConfig(runConfig, withCmdCommentString(comment, baseImageOS))
282 282
 	containerID, err := d.builder.probeAndCreate(d.state, runConfigWithCommentCmd)
283 283
 	if err != nil || containerID == "" {
284 284
 		return err
... ...
@@ -290,10 +290,10 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
290 290
 	return d.builder.commitContainer(d.state, containerID, runConfigWithCommentCmd)
291 291
 }
292 292
 
293
-func resolveCmdLine(cmd instructions.ShellDependantCmdLine, runConfig *container.Config, platform string) []string {
293
+func resolveCmdLine(cmd instructions.ShellDependantCmdLine, runConfig *container.Config, os string) []string {
294 294
 	result := cmd.CmdLine
295 295
 	if cmd.PrependShell && result != nil {
296
-		result = append(getShell(runConfig, platform), result...)
296
+		result = append(getShell(runConfig, os), result...)
297 297
 	}
298 298
 	return result
299 299
 }
... ...
@@ -311,8 +311,7 @@ func resolveCmdLine(cmd instructions.ShellDependantCmdLine, runConfig *container
311 311
 func dispatchRun(d dispatchRequest, c *instructions.RunCommand) error {
312 312
 
313 313
 	stateRunConfig := d.state.runConfig
314
-	optionsOS := system.ParsePlatform(d.builder.options.Platform).OS
315
-	cmdFromArgs := resolveCmdLine(c.ShellDependantCmdLine, stateRunConfig, optionsOS)
314
+	cmdFromArgs := resolveCmdLine(c.ShellDependantCmdLine, stateRunConfig, d.state.operatingSystem)
316 315
 	buildArgs := d.state.buildArgs.FilterAllowed(stateRunConfig.Env)
317 316
 
318 317
 	saveCmd := cmdFromArgs
... ...
@@ -104,13 +104,14 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) {
104 104
 
105 105
 // dispatchState is a data object which is modified by dispatchers
106 106
 type dispatchState struct {
107
-	runConfig  *container.Config
108
-	maintainer string
109
-	cmdSet     bool
110
-	imageID    string
111
-	baseImage  builder.Image
112
-	stageName  string
113
-	buildArgs  *buildArgs
107
+	runConfig       *container.Config
108
+	maintainer      string
109
+	cmdSet          bool
110
+	imageID         string
111
+	baseImage       builder.Image
112
+	stageName       string
113
+	buildArgs       *buildArgs
114
+	operatingSystem string
114 115
 }
115 116
 
116 117
 func newDispatchState(baseArgs *buildArgs) *dispatchState {
... ...
@@ -213,6 +214,7 @@ func (s *dispatchState) hasFromImage() bool {
213 213
 func (s *dispatchState) beginStage(stageName string, image builder.Image) {
214 214
 	s.stageName = stageName
215 215
 	s.imageID = image.ImageID()
216
+	s.operatingSystem = image.OperatingSystem()
216 217
 
217 218
 	if image.RunConfig() != nil {
218 219
 		// copy avoids referencing the same instance when 2 stages have the same base
... ...
@@ -229,7 +231,7 @@ func (s *dispatchState) beginStage(stageName string, image builder.Image) {
229 229
 // Add the default PATH to runConfig.ENV if one exists for the operating system and there
230 230
 // is no PATH set. Note that Windows containers on Windows won't have one as it's set by HCS
231 231
 func (s *dispatchState) setDefaultPath() {
232
-	defaultPath := system.DefaultPathEnv(s.baseImage.OperatingSystem())
232
+	defaultPath := system.DefaultPathEnv(s.operatingSystem)
233 233
 	if defaultPath == "" {
234 234
 		return
235 235
 	}
... ...
@@ -125,8 +125,7 @@ func (b *Builder) commitContainer(dispatchState *dispatchState, id string, conta
125 125
 }
126 126
 
127 127
 func (b *Builder) exportImage(state *dispatchState, imageMount *imageMount, runConfig *container.Config) error {
128
-	optionsPlatform := system.ParsePlatform(b.options.Platform)
129
-	newLayer, err := imageMount.Layer().Commit(optionsPlatform.OS)
128
+	newLayer, err := imageMount.Layer().Commit()
130 129
 	if err != nil {
131 130
 		return err
132 131
 	}
... ...
@@ -502,15 +501,13 @@ func (b *Builder) probeAndCreate(dispatchState *dispatchState, runConfig *contai
502 502
 	}
503 503
 	// Set a log config to override any default value set on the daemon
504 504
 	hostConfig := &container.HostConfig{LogConfig: defaultLogConfig}
505
-	optionsPlatform := system.ParsePlatform(b.options.Platform)
506
-	container, err := b.containerManager.Create(runConfig, hostConfig, optionsPlatform.OS)
505
+	container, err := b.containerManager.Create(runConfig, hostConfig)
507 506
 	return container.ID, err
508 507
 }
509 508
 
510 509
 func (b *Builder) create(runConfig *container.Config) (string, error) {
511 510
 	hostConfig := hostConfigFromOptions(b.options)
512
-	optionsPlatform := system.ParsePlatform(b.options.Platform)
513
-	container, err := b.containerManager.Create(runConfig, hostConfig, optionsPlatform.OS)
511
+	container, err := b.containerManager.Create(runConfig, hostConfig)
514 512
 	if err != nil {
515 513
 		return "", err
516 514
 	}
... ...
@@ -127,7 +127,7 @@ func (l *mockLayer) Mount() (containerfs.ContainerFS, error) {
127 127
 	return containerfs.NewLocalContainerFS("mountPath"), nil
128 128
 }
129 129
 
130
-func (l *mockLayer) Commit(string) (builder.ReleaseableLayer, error) {
130
+func (l *mockLayer) Commit() (builder.ReleaseableLayer, error) {
131 131
 	return nil, nil
132 132
 }
133 133
 
... ...
@@ -23,7 +23,6 @@ type releaseableLayer struct {
23 23
 	layerStore layer.Store
24 24
 	roLayer    layer.Layer
25 25
 	rwLayer    layer.RWLayer
26
-	os         string
27 26
 }
28 27
 
29 28
 func (rl *releaseableLayer) Mount() (containerfs.ContainerFS, error) {
... ...
@@ -35,7 +34,7 @@ func (rl *releaseableLayer) Mount() (containerfs.ContainerFS, error) {
35 35
 	}
36 36
 
37 37
 	mountID := stringid.GenerateRandomID()
38
-	rl.rwLayer, err = rl.layerStore.CreateRWLayer(mountID, chainID, rl.os, nil)
38
+	rl.rwLayer, err = rl.layerStore.CreateRWLayer(mountID, chainID, nil)
39 39
 	if err != nil {
40 40
 		return nil, errors.Wrap(err, "failed to create rwlayer")
41 41
 	}
... ...
@@ -55,7 +54,7 @@ func (rl *releaseableLayer) Mount() (containerfs.ContainerFS, error) {
55 55
 	return mountPath, nil
56 56
 }
57 57
 
58
-func (rl *releaseableLayer) Commit(os string) (builder.ReleaseableLayer, error) {
58
+func (rl *releaseableLayer) Commit() (builder.ReleaseableLayer, error) {
59 59
 	var chainID layer.ChainID
60 60
 	if rl.roLayer != nil {
61 61
 		chainID = rl.roLayer.ChainID()
... ...
@@ -67,12 +66,12 @@ func (rl *releaseableLayer) Commit(os string) (builder.ReleaseableLayer, error)
67 67
 	}
68 68
 	defer stream.Close()
69 69
 
70
-	newLayer, err := rl.layerStore.Register(stream, chainID, os)
70
+	newLayer, err := rl.layerStore.Register(stream, chainID)
71 71
 	if err != nil {
72 72
 		return nil, err
73 73
 	}
74 74
 	// TODO: An optimization woudld be to handle empty layers before returning
75
-	return &releaseableLayer{layerStore: rl.layerStore, roLayer: newLayer, os: os}, nil
75
+	return &releaseableLayer{layerStore: rl.layerStore, roLayer: newLayer}, nil
76 76
 }
77 77
 
78 78
 func (rl *releaseableLayer) DiffID() layer.DiffID {
... ...
@@ -128,9 +127,9 @@ func (rl *releaseableLayer) releaseROLayer() error {
128 128
 	return err
129 129
 }
130 130
 
131
-func newReleasableLayerForImage(img *image.Image, layerStore layer.Store, os string) (builder.ReleaseableLayer, error) {
131
+func newReleasableLayerForImage(img *image.Image, layerStore layer.Store) (builder.ReleaseableLayer, error) {
132 132
 	if img == nil || img.RootFS.ChainID() == "" {
133
-		return &releaseableLayer{layerStore: layerStore, os: os}, nil
133
+		return &releaseableLayer{layerStore: layerStore}, nil
134 134
 	}
135 135
 	// Hold a reference to the image layer so that it can't be removed before
136 136
 	// it is released
... ...
@@ -138,7 +137,7 @@ func newReleasableLayerForImage(img *image.Image, layerStore layer.Store, os str
138 138
 	if err != nil {
139 139
 		return nil, errors.Wrapf(err, "failed to get layer for image %s", img.ImageID())
140 140
 	}
141
-	return &releaseableLayer{layerStore: layerStore, roLayer: roLayer, os: os}, nil
141
+	return &releaseableLayer{layerStore: layerStore, roLayer: roLayer}, nil
142 142
 }
143 143
 
144 144
 // TODO: could this use the regular daemon PullImage ?
... ...
@@ -172,7 +171,7 @@ func (daemon *Daemon) pullForBuilder(ctx context.Context, name string, authConfi
172 172
 // leaking of layers.
173 173
 func (daemon *Daemon) GetImageAndReleasableLayer(ctx context.Context, refOrID string, opts backend.GetImageAndLayerOptions) (builder.Image, builder.ReleaseableLayer, error) {
174 174
 	if refOrID == "" {
175
-		layer, err := newReleasableLayerForImage(nil, daemon.layerStore, opts.OS)
175
+		layer, err := newReleasableLayerForImage(nil, daemon.layerStores[opts.OS])
176 176
 		return nil, layer, err
177 177
 	}
178 178
 
... ...
@@ -183,7 +182,7 @@ func (daemon *Daemon) GetImageAndReleasableLayer(ctx context.Context, refOrID st
183 183
 		}
184 184
 		// TODO: shouldn't we error out if error is different from "not found" ?
185 185
 		if image != nil {
186
-			layer, err := newReleasableLayerForImage(image, daemon.layerStore, image.OperatingSystem())
186
+			layer, err := newReleasableLayerForImage(image, daemon.layerStores[image.OperatingSystem()])
187 187
 			return image, layer, err
188 188
 		}
189 189
 	}
... ...
@@ -192,7 +191,7 @@ func (daemon *Daemon) GetImageAndReleasableLayer(ctx context.Context, refOrID st
192 192
 	if err != nil {
193 193
 		return nil, nil, err
194 194
 	}
195
-	layer, err := newReleasableLayerForImage(image, daemon.layerStore, image.OperatingSystem())
195
+	layer, err := newReleasableLayerForImage(image, daemon.layerStores[image.OperatingSystem()])
196 196
 	return image, layer, err
197 197
 }
198 198
 
... ...
@@ -154,7 +154,7 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
154 154
 		c.Config = container.Config
155 155
 	}
156 156
 
157
-	newConfig, err := dockerfile.BuildFromConfig(c.Config, c.Changes)
157
+	newConfig, err := dockerfile.BuildFromConfig(c.Config, c.Changes, container.OS)
158 158
 	if err != nil {
159 159
 		return "", err
160 160
 	}
... ...
@@ -186,11 +186,11 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
186 186
 		}
187 187
 	}
188 188
 
189
-	l, err := daemon.layerStore.Register(rwTar, parent.RootFS.ChainID(), container.OS)
189
+	l, err := daemon.layerStores[container.OS].Register(rwTar, parent.RootFS.ChainID())
190 190
 	if err != nil {
191 191
 		return "", err
192 192
 	}
193
-	defer layer.ReleaseAndLog(daemon.layerStore, l)
193
+	defer layer.ReleaseAndLog(daemon.layerStores[container.OS], l)
194 194
 
195 195
 	containerConfig := c.ContainerConfig
196 196
 	if containerConfig == nil {
... ...
@@ -251,13 +251,13 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
251 251
 }
252 252
 
253 253
 func (daemon *Daemon) exportContainerRw(container *container.Container) (arch io.ReadCloser, err error) {
254
-	rwlayer, err := daemon.stores[container.OS].layerStore.GetRWLayer(container.ID)
254
+	rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID)
255 255
 	if err != nil {
256 256
 		return nil, err
257 257
 	}
258 258
 	defer func() {
259 259
 		if err != nil {
260
-			daemon.stores[container.OS].layerStore.ReleaseRWLayer(rwlayer)
260
+			daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer)
261 261
 		}
262 262
 	}()
263 263
 
... ...
@@ -278,7 +278,7 @@ func (daemon *Daemon) exportContainerRw(container *container.Container) (arch io
278 278
 	return ioutils.NewReadCloserWrapper(archive, func() error {
279 279
 			archive.Close()
280 280
 			err = rwlayer.Unmount()
281
-			daemon.stores[container.OS].layerStore.ReleaseRWLayer(rwlayer)
281
+			daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer)
282 282
 			return err
283 283
 		}),
284 284
 		nil
... ...
@@ -270,7 +270,7 @@ func (daemon *Daemon) setRWLayer(container *container.Container) error {
270 270
 		StorageOpt: container.HostConfig.StorageOpt,
271 271
 	}
272 272
 
273
-	rwLayer, err := daemon.layerStore.CreateRWLayer(container.ID, layerID, container.OS, rwLayerOpts)
273
+	rwLayer, err := daemon.layerStores[container.OS].CreateRWLayer(container.ID, layerID, rwLayerOpts)
274 274
 	if err != nil {
275 275
 		return err
276 276
 	}
... ...
@@ -97,7 +97,7 @@ type Daemon struct {
97 97
 	referenceStore            refstore.Store
98 98
 	imageStore                image.Store
99 99
 	imageRoot                 string
100
-	layerStore                layer.Store
100
+	layerStores               map[string]layer.Store // By operating system
101 101
 	distributionMetadataStore dmetadata.Store
102 102
 	PluginStore               *plugin.Store // todo: remove
103 103
 	pluginManager             *plugin.Manager
... ...
@@ -159,7 +159,7 @@ func (daemon *Daemon) restore() error {
159 159
 		// Ignore the container if it does not support the current driver being used by the graph
160 160
 		currentDriverForContainerOS := daemon.graphDrivers[container.OS]
161 161
 		if (container.Driver == "" && currentDriverForContainerOS == "aufs") || container.Driver == currentDriverForContainerOS {
162
-			rwlayer, err := daemon.layerStore.GetRWLayer(container.ID)
162
+			rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID)
163 163
 			if err != nil {
164 164
 				logrus.Errorf("Failed to load container mount %v: %v", id, err)
165 165
 				continue
... ...
@@ -703,6 +703,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
703 703
 	// be set through an environment variable, a daemon start parameter, or chosen through
704 704
 	// initialization of the layerstore through driver priority order for example.
705 705
 	d.graphDrivers = make(map[string]string)
706
+	d.layerStores = make(map[string]layer.Store)
706 707
 	if runtime.GOOS == "windows" {
707 708
 		d.graphDrivers[runtime.GOOS] = "windowsfilter"
708 709
 		if system.LCOWSupported() {
... ...
@@ -746,22 +747,25 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
746 746
 		return nil, errors.Wrap(err, "couldn't create plugin manager")
747 747
 	}
748 748
 
749
-	d.layerStore, err = layer.NewStoreFromOptions(layer.StoreOptions{
750
-		Root: config.Root,
751
-		MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
752
-		GraphDrivers:              d.graphDrivers,
753
-		GraphDriverOptions:        config.GraphOptions,
754
-		IDMappings:                idMappings,
755
-		PluginGetter:              d.PluginStore,
756
-		ExperimentalEnabled:       config.Experimental,
757
-	})
758
-	if err != nil {
759
-		return nil, err
749
+	for operatingSystem, gd := range d.graphDrivers {
750
+		d.layerStores[operatingSystem], err = layer.NewStoreFromOptions(layer.StoreOptions{
751
+			Root: config.Root,
752
+			MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
753
+			GraphDriver:               gd,
754
+			GraphDriverOptions:        config.GraphOptions,
755
+			IDMappings:                idMappings,
756
+			PluginGetter:              d.PluginStore,
757
+			ExperimentalEnabled:       config.Experimental,
758
+			OS:                        operatingSystem,
759
+		})
760
+		if err != nil {
761
+			return nil, err
762
+		}
760 763
 	}
761 764
 
762
-	// As layerstore may set the driver
765
+	// As layerstore initialization may set the driver
763 766
 	for os := range d.graphDrivers {
764
-		d.graphDrivers[os] = d.layerStore.DriverName(os)
767
+		d.graphDrivers[os] = d.layerStores[os].DriverName()
765 768
 	}
766 769
 
767 770
 	// Configure and validate the kernels security support. Note this is a Linux/FreeBSD
... ...
@@ -771,7 +775,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
771 771
 	}
772 772
 
773 773
 	logrus.Debugf("Max Concurrent Downloads: %d", *config.MaxConcurrentDownloads)
774
-	d.downloadManager = xfer.NewLayerDownloadManager(d.layerStore, *config.MaxConcurrentDownloads)
774
+	d.downloadManager = xfer.NewLayerDownloadManager(d.layerStores, *config.MaxConcurrentDownloads)
775 775
 	logrus.Debugf("Max Concurrent Uploads: %d", *config.MaxConcurrentUploads)
776 776
 	d.uploadManager = xfer.NewLayerUploadManager(*config.MaxConcurrentUploads)
777 777
 
... ...
@@ -780,7 +784,12 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
780 780
 	if err != nil {
781 781
 		return nil, err
782 782
 	}
783
-	d.imageStore, err = image.NewImageStore(ifs, d.layerStore)
783
+
784
+	lgrMap := make(map[string]image.LayerGetReleaser)
785
+	for os, ls := range d.layerStores {
786
+		lgrMap[os] = ls
787
+	}
788
+	d.imageStore, err = image.NewImageStore(ifs, lgrMap)
784 789
 	if err != nil {
785 790
 		return nil, err
786 791
 	}
... ...
@@ -829,7 +838,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
829 829
 	// No content-addressability migration on Windows as it never supported pre-CA
830 830
 	if runtime.GOOS != "windows" {
831 831
 		migrationStart := time.Now()
832
-		if err := v1.Migrate(config.Root, d.graphDrivers[runtime.GOOS], d.layerStore, d.imageStore, rs, d.distributionMetadataStore); err != nil {
832
+		if err := v1.Migrate(config.Root, d.graphDrivers[runtime.GOOS], d.layerStores[runtime.GOOS], d.imageStore, rs, d.distributionMetadataStore); err != nil {
833 833
 			logrus.Errorf("Graph migration failed: %q. Your old graph data was found to be too inconsistent for upgrading to content-addressable storage. Some of the old data was probably not upgraded. We recommend starting over with a clean storage directory if possible.", err)
834 834
 		}
835 835
 		logrus.Infof("Graph migration to content-addressability took %.2f seconds", time.Since(migrationStart).Seconds())
... ...
@@ -988,7 +997,7 @@ func (daemon *Daemon) Shutdown() error {
988 988
 				logrus.Errorf("Stop container error: %v", err)
989 989
 				return
990 990
 			}
991
-			if mountid, err := daemon.layerStore.GetMountID(c.ID); err == nil {
991
+			if mountid, err := daemon.layerStores[c.OS].GetMountID(c.ID); err == nil {
992 992
 				daemon.cleanupMountsByID(mountid)
993 993
 			}
994 994
 			logrus.Debugf("container stopped %s", c.ID)
... ...
@@ -1001,8 +1010,12 @@ func (daemon *Daemon) Shutdown() error {
1001 1001
 		}
1002 1002
 	}
1003 1003
 
1004
-	if err := daemon.layerStore.Cleanup(); err != nil {
1005
-		logrus.Errorf("Error during layer Store.Cleanup(): %v", err)
1004
+	for os, ls := range daemon.layerStores {
1005
+		if ls != nil {
1006
+			if err := ls.Cleanup(); err != nil {
1007
+				logrus.Errorf("Error during layer Store.Cleanup(): %v %s", err, os)
1008
+			}
1009
+		}
1006 1010
 	}
1007 1011
 
1008 1012
 	// If we are part of a cluster, clean up cluster's stuff
... ...
@@ -1083,7 +1096,7 @@ func (daemon *Daemon) Subnets() ([]net.IPNet, []net.IPNet) {
1083 1083
 
1084 1084
 // GraphDriverName returns the name of the graph driver used by the layer.Store
1085 1085
 func (daemon *Daemon) GraphDriverName(os string) string {
1086
-	return daemon.layerStore.DriverName(os)
1086
+	return daemon.layerStores[os].DriverName()
1087 1087
 }
1088 1088
 
1089 1089
 // prepareTempDir prepares and returns the default directory to use
... ...
@@ -118,7 +118,7 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
118 118
 	// When container creation fails and `RWLayer` has not been created yet, we
119 119
 	// do not call `ReleaseRWLayer`
120 120
 	if container.RWLayer != nil {
121
-		metadata, err := daemon.layerStore.ReleaseRWLayer(container.RWLayer)
121
+		metadata, err := daemon.layerStores[container.OS].ReleaseRWLayer(container.RWLayer)
122 122
 		layer.LogReleaseMetadata(metadata)
123 123
 		if err != nil && err != layer.ErrMountDoesNotExist && !os.IsNotExist(errors.Cause(err)) {
124 124
 			e := errors.Wrapf(err, "driver %q failed to remove root filesystem for %s", daemon.GraphDriverName(container.OS), container.ID)
... ...
@@ -96,21 +96,23 @@ func (daemon *Daemon) SystemDiskUsage(ctx context.Context) (*types.DiskUsage, er
96 96
 	// Get total layers size on disk
97 97
 	var allLayersSize int64
98 98
 	layerRefs := daemon.getLayerRefs()
99
-	allLayers := daemon.layerStore.Map()
100
-	for _, l := range allLayers {
101
-		select {
102
-		case <-ctx.Done():
103
-			return nil, ctx.Err()
104
-		default:
105
-			size, err := l.DiffSize()
106
-			if err == nil {
107
-				if _, ok := layerRefs[l.ChainID()]; ok {
108
-					allLayersSize += size
99
+	for _, ls := range daemon.layerStores {
100
+		allLayers := ls.Map()
101
+		for _, l := range allLayers {
102
+			select {
103
+			case <-ctx.Done():
104
+				return nil, ctx.Err()
105
+			default:
106
+				size, err := l.DiffSize()
107
+				if err == nil {
108
+					if _, ok := layerRefs[l.ChainID()]; ok {
109
+						allLayersSize += size
110
+					} else {
111
+						logrus.Warnf("found leaked image layer %v", l.ChainID())
112
+					}
109 113
 				} else {
110
-					logrus.Warnf("found leaked image layer %v", l.ChainID())
114
+					logrus.Warnf("failed to get diff size for layer %v", l.ChainID())
111 115
 				}
112
-			} else {
113
-				logrus.Warnf("failed to get diff size for layer %v", l.ChainID())
114 116
 			}
115 117
 		}
116 118
 	}
... ...
@@ -47,13 +47,13 @@ func (daemon *Daemon) ContainerExport(name string, out io.Writer) error {
47 47
 }
48 48
 
49 49
 func (daemon *Daemon) containerExport(container *container.Container) (arch io.ReadCloser, err error) {
50
-	rwlayer, err := daemon.stores[container.OS].layerStore.GetRWLayer(container.ID)
50
+	rwlayer, err := daemon.layerStores[container.OS].GetRWLayer(container.ID)
51 51
 	if err != nil {
52 52
 		return nil, err
53 53
 	}
54 54
 	defer func() {
55 55
 		if err != nil {
56
-			daemon.stores[container.OS].layerStore.ReleaseRWLayer(rwlayer)
56
+			daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer)
57 57
 		}
58 58
 	}()
59 59
 
... ...
@@ -74,7 +74,7 @@ func (daemon *Daemon) containerExport(container *container.Container) (arch io.R
74 74
 	arch = ioutils.NewReadCloserWrapper(archive, func() error {
75 75
 		err := archive.Close()
76 76
 		rwlayer.Unmount()
77
-		daemon.stores[container.OS].layerStore.ReleaseRWLayer(rwlayer)
77
+		daemon.layerStores[container.OS].ReleaseRWLayer(rwlayer)
78 78
 		return err
79 79
 	})
80 80
 	daemon.LogContainerEvent(container, "export")
... ...
@@ -15,12 +15,14 @@ func (daemon *Daemon) getSize(containerID string) (int64, int64) {
15 15
 		err                error
16 16
 	)
17 17
 
18
-	rwlayer, err := daemon.layerStore.GetRWLayer(containerID)
18
+	// Safe to index by runtime.GOOS as Unix hosts don't support multiple
19
+	// container operating systems.
20
+	rwlayer, err := daemon.layerStores[runtime.GOOS].GetRWLayer(containerID)
19 21
 	if err != nil {
20 22
 		logrus.Errorf("Failed to compute size of container rootfs %v: %v", containerID, err)
21 23
 		return sizeRw, sizeRootfs
22 24
 	}
23
-	defer daemon.layerStore.ReleaseRWLayer(rwlayer)
25
+	defer daemon.layerStores[runtime.GOOS].ReleaseRWLayer(rwlayer)
24 26
 
25 27
 	sizeRw, err = rwlayer.Size()
26 28
 	if err != nil {
... ...
@@ -931,8 +931,6 @@ func parseStorageOpt(storageOpt map[string]string) (*storageOptions, error) {
931 931
 				return nil, err
932 932
 			}
933 933
 			options.size = uint64(size)
934
-		default:
935
-			return nil, fmt.Errorf("Unknown storage option: %s", key)
936 934
 		}
937 935
 	}
938 936
 	return &options, nil
... ...
@@ -2,7 +2,6 @@ package daemon
2 2
 
3 3
 import (
4 4
 	"fmt"
5
-	"runtime"
6 5
 
7 6
 	"github.com/docker/distribution/reference"
8 7
 	"github.com/docker/docker/errdefs"
... ...
@@ -58,11 +57,7 @@ func (daemon *Daemon) GetImageIDAndOS(refOrID string) (image.ID, string, error)
58 58
 		if err != nil {
59 59
 			return "", "", errImageDoesNotExist{ref}
60 60
 		}
61
-		imageOS := img.OperatingSystem()
62
-		if imageOS == "" {
63
-			imageOS = runtime.GOOS
64
-		}
65
-		return id, imageOS, nil
61
+		return id, img.OperatingSystem(), nil
66 62
 	}
67 63
 
68 64
 	return "", "", errImageDoesNotExist{ref}
... ...
@@ -12,7 +12,7 @@ import (
12 12
 // the same tag are exported. names is the set of tags to export, and
13 13
 // outStream is the writer which the images are written to.
14 14
 func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error {
15
-	imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore, daemon)
15
+	imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStores, daemon.referenceStore, daemon)
16 16
 	return imageExporter.Save(names, outStream)
17 17
 }
18 18
 
... ...
@@ -20,6 +20,6 @@ func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error {
20 20
 // complement of ImageExport.  The input stream is an uncompressed tar
21 21
 // ball containing images and metadata.
22 22
 func (daemon *Daemon) LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error {
23
-	imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStore, daemon.referenceStore, daemon)
23
+	imageExporter := tarexport.NewTarExporter(daemon.imageStore, daemon.layerStores, daemon.referenceStore, daemon)
24 24
 	return imageExporter.Load(inTar, outStream, quiet)
25 25
 }
... ...
@@ -33,12 +33,12 @@ func (daemon *Daemon) ImageHistory(name string) ([]*image.HistoryResponseItem, e
33 33
 			}
34 34
 
35 35
 			rootFS.Append(img.RootFS.DiffIDs[layerCounter])
36
-			l, err := daemon.layerStore.Get(rootFS.ChainID())
36
+			l, err := daemon.layerStores[img.OperatingSystem()].Get(rootFS.ChainID())
37 37
 			if err != nil {
38 38
 				return nil, err
39 39
 			}
40 40
 			layerSize, err = l.DiffSize()
41
-			layer.ReleaseAndLog(daemon.layerStore, l)
41
+			layer.ReleaseAndLog(daemon.layerStores[img.OperatingSystem()], l)
42 42
 			if err != nil {
43 43
 				return nil, err
44 44
 			}
... ...
@@ -1,7 +1,6 @@
1 1
 package daemon
2 2
 
3 3
 import (
4
-	"runtime"
5 4
 	"time"
6 5
 
7 6
 	"github.com/docker/distribution/reference"
... ...
@@ -18,12 +17,6 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
18 18
 		return nil, errors.Wrapf(err, "no such image: %s", name)
19 19
 	}
20 20
 
21
-	// If the image OS isn't set, assume it's the host OS
22
-	os := img.OS
23
-	if os == "" {
24
-		os = runtime.GOOS
25
-	}
26
-
27 21
 	refs := daemon.referenceStore.References(img.ID().Digest())
28 22
 	repoTags := []string{}
29 23
 	repoDigests := []string{}
... ...
@@ -40,11 +33,11 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
40 40
 	var layerMetadata map[string]string
41 41
 	layerID := img.RootFS.ChainID()
42 42
 	if layerID != "" {
43
-		l, err := daemon.layerStore.Get(layerID)
43
+		l, err := daemon.layerStores[img.OperatingSystem()].Get(layerID)
44 44
 		if err != nil {
45 45
 			return nil, err
46 46
 		}
47
-		defer layer.ReleaseAndLog(daemon.layerStore, l)
47
+		defer layer.ReleaseAndLog(daemon.layerStores[img.OperatingSystem()], l)
48 48
 		size, err = l.Size()
49 49
 		if err != nil {
50 50
 			return nil, err
... ...
@@ -79,7 +72,7 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
79 79
 		Author:          img.Author,
80 80
 		Config:          img.Config,
81 81
 		Architecture:    img.Architecture,
82
-		Os:              os,
82
+		Os:              img.OperatingSystem(),
83 83
 		OsVersion:       img.OSVersion,
84 84
 		Size:            size,
85 85
 		VirtualSize:     size, // TODO: field unused, deprecate
... ...
@@ -89,7 +82,7 @@ func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
89 89
 		},
90 90
 	}
91 91
 
92
-	imageInspect.GraphDriver.Name = daemon.GraphDriverName(os)
92
+	imageInspect.GraphDriver.Name = daemon.GraphDriverName(img.OperatingSystem())
93 93
 	imageInspect.GraphDriver.Data = layerMetadata
94 94
 
95 95
 	return imageInspect, nil
... ...
@@ -51,7 +51,7 @@ func (daemon *Daemon) PushImage(ctx context.Context, image, tag string, metaHead
51 51
 			ReferenceStore:   daemon.referenceStore,
52 52
 		},
53 53
 		ConfigMediaType: schema2.MediaTypeImageConfig,
54
-		LayerStore:      distribution.NewLayerProviderFromStore(daemon.layerStore),
54
+		LayerStores:     distribution.NewLayerProvidersFromStores(daemon.layerStores),
55 55
 		TrustKey:        daemon.trustKey,
56 56
 		UploadManager:   daemon.uploadManager,
57 57
 	}
... ...
@@ -116,7 +116,7 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs
116 116
 		layerID := img.RootFS.ChainID()
117 117
 		var size int64
118 118
 		if layerID != "" {
119
-			l, err := daemon.layerStore.Get(layerID)
119
+			l, err := daemon.layerStores[img.OperatingSystem()].Get(layerID)
120 120
 			if err != nil {
121 121
 				// The layer may have been deleted between the call to `Map()` or
122 122
 				// `Heads()` and the call to `Get()`, so we just ignore this error
... ...
@@ -127,7 +127,7 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs
127 127
 			}
128 128
 
129 129
 			size, err = l.Size()
130
-			layer.ReleaseAndLog(daemon.layerStore, l)
130
+			layer.ReleaseAndLog(daemon.layerStores[img.OperatingSystem()], l)
131 131
 			if err != nil {
132 132
 				return nil, err
133 133
 			}
... ...
@@ -179,7 +179,7 @@ func (daemon *Daemon) Images(imageFilters filters.Args, all bool, withExtraAttrs
179 179
 			// lazily init variables
180 180
 			if imagesMap == nil {
181 181
 				allContainers = daemon.List()
182
-				allLayers = daemon.layerStore.Map()
182
+				allLayers = daemon.layerStores[img.OperatingSystem()].Map()
183 183
 				imagesMap = make(map[*image.Image]*types.ImageSummary)
184 184
 				layerRefs = make(map[layer.ChainID]int)
185 185
 			}
... ...
@@ -264,11 +264,11 @@ func (daemon *Daemon) SquashImage(id, parent string) (string, error) {
264 264
 		parentImg = &image.Image{RootFS: rootFS}
265 265
 	}
266 266
 
267
-	l, err := daemon.layerStore.Get(img.RootFS.ChainID())
267
+	l, err := daemon.layerStores[img.OperatingSystem()].Get(img.RootFS.ChainID())
268 268
 	if err != nil {
269 269
 		return "", errors.Wrap(err, "error getting image layer")
270 270
 	}
271
-	defer daemon.layerStore.Release(l)
271
+	defer daemon.layerStores[img.OperatingSystem()].Release(l)
272 272
 
273 273
 	ts, err := l.TarStreamFrom(parentChainID)
274 274
 	if err != nil {
... ...
@@ -276,11 +276,11 @@ func (daemon *Daemon) SquashImage(id, parent string) (string, error) {
276 276
 	}
277 277
 	defer ts.Close()
278 278
 
279
-	newL, err := daemon.layerStore.Register(ts, parentChainID, img.OperatingSystem())
279
+	newL, err := daemon.layerStores[img.OperatingSystem()].Register(ts, parentChainID)
280 280
 	if err != nil {
281 281
 		return "", errors.Wrap(err, "error registering layer")
282 282
 	}
283
-	defer daemon.layerStore.Release(newL)
283
+	defer daemon.layerStores[img.OperatingSystem()].Release(newL)
284 284
 
285 285
 	newImage := *img
286 286
 	newImage.RootFS = nil
... ...
@@ -57,7 +57,7 @@ func (daemon *Daemon) ImportImage(src string, repository, os string, tag string,
57 57
 		}
58 58
 	}
59 59
 
60
-	config, err := dockerfile.BuildFromConfig(&container.Config{}, changes)
60
+	config, err := dockerfile.BuildFromConfig(&container.Config{}, changes, os)
61 61
 	if err != nil {
62 62
 		return err
63 63
 	}
... ...
@@ -91,11 +91,11 @@ func (daemon *Daemon) ImportImage(src string, repository, os string, tag string,
91 91
 	if err != nil {
92 92
 		return err
93 93
 	}
94
-	l, err := daemon.layerStore.Register(inflatedLayerData, "", os)
94
+	l, err := daemon.layerStores[os].Register(inflatedLayerData, "")
95 95
 	if err != nil {
96 96
 		return err
97 97
 	}
98
-	defer layer.ReleaseAndLog(daemon.layerStore, l)
98
+	defer layer.ReleaseAndLog(daemon.layerStores[os], l)
99 99
 
100 100
 	created := time.Now().UTC()
101 101
 	imgConfig, err := json.Marshal(&image.Image{
... ...
@@ -81,7 +81,7 @@ func (daemon *Daemon) SystemInfo() (*types.Info, error) {
81 81
 	var ds [][2]string
82 82
 	drivers := ""
83 83
 	for os, gd := range daemon.graphDrivers {
84
-		ds = append(ds, daemon.layerStore.DriverStatus(os)...)
84
+		ds = append(ds, daemon.layerStores[os].DriverStatus()...)
85 85
 		drivers += gd
86 86
 		if len(daemon.graphDrivers) > 1 {
87 87
 			drivers += fmt.Sprintf(" (%s) ", os)
... ...
@@ -138,9 +138,9 @@ func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
138 138
 	max := len(img.RootFS.DiffIDs)
139 139
 	for i := 1; i <= max; i++ {
140 140
 		img.RootFS.DiffIDs = img.RootFS.DiffIDs[:i]
141
-		layerPath, err := layer.GetLayerPath(daemon.layerStore, img.RootFS.ChainID())
141
+		layerPath, err := layer.GetLayerPath(daemon.layerStores[img.OperatingSystem()], img.RootFS.ChainID())
142 142
 		if err != nil {
143
-			return nil, fmt.Errorf("failed to get layer path from graphdriver %s for ImageID %s - %s", daemon.layerStore, img.RootFS.ChainID(), err)
143
+			return nil, fmt.Errorf("failed to get layer path from graphdriver %s for ImageID %s - %s", daemon.layerStores[img.OperatingSystem()], img.RootFS.ChainID(), err)
144 144
 		}
145 145
 		// Reverse order, expecting parent most first
146 146
 		s.Windows.LayerFolders = append([]string{layerPath}, s.Windows.LayerFolders...)
... ...
@@ -205,7 +205,12 @@ func (daemon *Daemon) ImagesPrune(ctx context.Context, pruneFilters filters.Args
205 205
 	}
206 206
 
207 207
 	// Filter intermediary images and get their unique size
208
-	allLayers := daemon.layerStore.Map()
208
+	allLayers := make(map[layer.ChainID]layer.Layer)
209
+	for _, ls := range daemon.layerStores {
210
+		for k, v := range ls.Map() {
211
+			allLayers[k] = v
212
+		}
213
+	}
209 214
 	topImages := map[image.ID]*image.Image{}
210 215
 	for id, img := range allImages {
211 216
 		select {
... ...
@@ -222,7 +222,7 @@ func (daemon *Daemon) Cleanup(container *container.Container) {
222 222
 	if err := daemon.conditionalUnmountOnCleanup(container); err != nil {
223 223
 		// FIXME: remove once reference counting for graphdrivers has been refactored
224 224
 		// Ensure that all the mounts are gone
225
-		if mountid, err := daemon.layerStore.GetMountID(container.ID); err == nil {
225
+		if mountid, err := daemon.layerStores[container.OS].GetMountID(container.ID); err == nil {
226 226
 			daemon.cleanupMountsByID(mountid)
227 227
 		}
228 228
 	}
... ...
@@ -71,8 +71,8 @@ type ImagePushConfig struct {
71 71
 	// ConfigMediaType is the configuration media type for
72 72
 	// schema2 manifests.
73 73
 	ConfigMediaType string
74
-	// LayerStore manages layers.
75
-	LayerStore PushLayerProvider
74
+	// LayerStores (indexed by operating system) manages layers.
75
+	LayerStores map[string]PushLayerProvider
76 76
 	// TrustKey is the private key for legacy signatures. This is typically
77 77
 	// an ephemeral key, since these signatures are no longer verified.
78 78
 	TrustKey libtrust.PrivateKey
... ...
@@ -165,13 +165,15 @@ type storeLayerProvider struct {
165 165
 	ls layer.Store
166 166
 }
167 167
 
168
-// NewLayerProviderFromStore returns a layer provider backed by
168
+// NewLayerProvidersFromStores returns layer providers backed by
169 169
 // an instance of LayerStore. Only getting layers as gzipped
170 170
 // tars is supported.
171
-func NewLayerProviderFromStore(ls layer.Store) PushLayerProvider {
172
-	return &storeLayerProvider{
173
-		ls: ls,
171
+func NewLayerProvidersFromStores(lss map[string]layer.Store) map[string]PushLayerProvider {
172
+	plps := make(map[string]PushLayerProvider)
173
+	for os, ls := range lss {
174
+		plps[os] = &storeLayerProvider{ls: ls}
174 175
 	}
176
+	return plps
175 177
 }
176 178
 
177 179
 func (p *storeLayerProvider) Get(lid layer.ChainID) (PushLayer, error) {
... ...
@@ -210,7 +210,7 @@ func (p *v1Pusher) imageListForTag(imgID image.ID, dependenciesSeen map[layer.Ch
210 210
 
211 211
 	topLayerID := img.RootFS.ChainID()
212 212
 
213
-	pl, err := p.config.LayerStore.Get(topLayerID)
213
+	pl, err := p.config.LayerStores[img.OperatingSystem()].Get(topLayerID)
214 214
 	*referencedLayers = append(*referencedLayers, pl)
215 215
 	if err != nil {
216 216
 		return nil, fmt.Errorf("failed to get top layer from image: %v", err)
... ...
@@ -118,12 +118,12 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, id
118 118
 		return fmt.Errorf("could not find image from tag %s: %v", reference.FamiliarString(ref), err)
119 119
 	}
120 120
 
121
-	rootfs, _, err := p.config.ImageStore.RootFSAndOSFromConfig(imgConfig)
121
+	rootfs, os, err := p.config.ImageStore.RootFSAndOSFromConfig(imgConfig)
122 122
 	if err != nil {
123 123
 		return fmt.Errorf("unable to get rootfs for image %s: %s", reference.FamiliarString(ref), err)
124 124
 	}
125 125
 
126
-	l, err := p.config.LayerStore.Get(rootfs.ChainID())
126
+	l, err := p.config.LayerStores[os].Get(rootfs.ChainID())
127 127
 	if err != nil {
128 128
 		return fmt.Errorf("failed to get top layer from image: %v", err)
129 129
 	}
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"errors"
5 5
 	"fmt"
6 6
 	"io"
7
+	"runtime"
7 8
 	"time"
8 9
 
9 10
 	"github.com/docker/distribution"
... ...
@@ -22,7 +23,7 @@ const maxDownloadAttempts = 5
22 22
 // registers and downloads those, taking into account dependencies between
23 23
 // layers.
24 24
 type LayerDownloadManager struct {
25
-	layerStore   layer.Store
25
+	layerStores  map[string]layer.Store
26 26
 	tm           TransferManager
27 27
 	waitDuration time.Duration
28 28
 }
... ...
@@ -33,9 +34,9 @@ func (ldm *LayerDownloadManager) SetConcurrency(concurrency int) {
33 33
 }
34 34
 
35 35
 // NewLayerDownloadManager returns a new LayerDownloadManager.
36
-func NewLayerDownloadManager(layerStore layer.Store, concurrencyLimit int, options ...func(*LayerDownloadManager)) *LayerDownloadManager {
36
+func NewLayerDownloadManager(layerStores map[string]layer.Store, concurrencyLimit int, options ...func(*LayerDownloadManager)) *LayerDownloadManager {
37 37
 	manager := LayerDownloadManager{
38
-		layerStore:   layerStore,
38
+		layerStores:  layerStores,
39 39
 		tm:           NewTransferManager(concurrencyLimit),
40 40
 		waitDuration: time.Second,
41 41
 	}
... ...
@@ -104,6 +105,11 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima
104 104
 		downloadsByKey = make(map[string]*downloadTransfer)
105 105
 	)
106 106
 
107
+	// Assume that the operating system is the host OS if blank
108
+	if os == "" {
109
+		os = runtime.GOOS
110
+	}
111
+
107 112
 	rootFS := initialRootFS
108 113
 	for _, descriptor := range layers {
109 114
 		key := descriptor.Key()
... ...
@@ -115,13 +121,13 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima
115 115
 			if err == nil {
116 116
 				getRootFS := rootFS
117 117
 				getRootFS.Append(diffID)
118
-				l, err := ldm.layerStore.Get(getRootFS.ChainID())
118
+				l, err := ldm.layerStores[os].Get(getRootFS.ChainID())
119 119
 				if err == nil {
120 120
 					// Layer already exists.
121 121
 					logrus.Debugf("Layer already exists: %s", descriptor.ID())
122 122
 					progress.Update(progressOutput, descriptor.ID(), "Already exists")
123 123
 					if topLayer != nil {
124
-						layer.ReleaseAndLog(ldm.layerStore, topLayer)
124
+						layer.ReleaseAndLog(ldm.layerStores[os], topLayer)
125 125
 					}
126 126
 					topLayer = l
127 127
 					missingLayer = false
... ...
@@ -165,7 +171,7 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima
165 165
 	if topDownload == nil {
166 166
 		return rootFS, func() {
167 167
 			if topLayer != nil {
168
-				layer.ReleaseAndLog(ldm.layerStore, topLayer)
168
+				layer.ReleaseAndLog(ldm.layerStores[os], topLayer)
169 169
 			}
170 170
 		}, nil
171 171
 	}
... ...
@@ -176,7 +182,7 @@ func (ldm *LayerDownloadManager) Download(ctx context.Context, initialRootFS ima
176 176
 
177 177
 	defer func() {
178 178
 		if topLayer != nil {
179
-			layer.ReleaseAndLog(ldm.layerStore, topLayer)
179
+			layer.ReleaseAndLog(ldm.layerStores[os], topLayer)
180 180
 		}
181 181
 	}()
182 182
 
... ...
@@ -216,7 +222,7 @@ func (ldm *LayerDownloadManager) makeDownloadFunc(descriptor DownloadDescriptor,
216 216
 	return func(progressChan chan<- progress.Progress, start <-chan struct{}, inactive chan<- struct{}) Transfer {
217 217
 		d := &downloadTransfer{
218 218
 			Transfer:   NewTransfer(),
219
-			layerStore: ldm.layerStore,
219
+			layerStore: ldm.layerStores[os],
220 220
 		}
221 221
 
222 222
 		go func() {
... ...
@@ -335,9 +341,9 @@ func (ldm *LayerDownloadManager) makeDownloadFunc(descriptor DownloadDescriptor,
335 335
 				src = fs.Descriptor()
336 336
 			}
337 337
 			if ds, ok := d.layerStore.(layer.DescribableStore); ok {
338
-				d.layer, err = ds.RegisterWithDescriptor(inflatedLayerData, parentLayer, os, src)
338
+				d.layer, err = ds.RegisterWithDescriptor(inflatedLayerData, parentLayer, src)
339 339
 			} else {
340
-				d.layer, err = d.layerStore.Register(inflatedLayerData, parentLayer, os)
340
+				d.layer, err = d.layerStore.Register(inflatedLayerData, parentLayer)
341 341
 			}
342 342
 			if err != nil {
343 343
 				select {
... ...
@@ -380,7 +386,7 @@ func (ldm *LayerDownloadManager) makeDownloadFuncFromDownload(descriptor Downloa
380 380
 	return func(progressChan chan<- progress.Progress, start <-chan struct{}, inactive chan<- struct{}) Transfer {
381 381
 		d := &downloadTransfer{
382 382
 			Transfer:   NewTransfer(),
383
-			layerStore: ldm.layerStore,
383
+			layerStore: ldm.layerStores[os],
384 384
 		}
385 385
 
386 386
 		go func() {
... ...
@@ -434,9 +440,9 @@ func (ldm *LayerDownloadManager) makeDownloadFuncFromDownload(descriptor Downloa
434 434
 				src = fs.Descriptor()
435 435
 			}
436 436
 			if ds, ok := d.layerStore.(layer.DescribableStore); ok {
437
-				d.layer, err = ds.RegisterWithDescriptor(layerReader, parentLayer, os, src)
437
+				d.layer, err = ds.RegisterWithDescriptor(layerReader, parentLayer, src)
438 438
 			} else {
439
-				d.layer, err = d.layerStore.Register(layerReader, parentLayer, os)
439
+				d.layer, err = d.layerStore.Register(layerReader, parentLayer)
440 440
 			}
441 441
 			if err != nil {
442 442
 				d.err = fmt.Errorf("failed to register layer: %v", err)
... ...
@@ -91,7 +91,7 @@ func (ls *mockLayerStore) Map() map[layer.ChainID]layer.Layer {
91 91
 	return layers
92 92
 }
93 93
 
94
-func (ls *mockLayerStore) Register(reader io.Reader, parentID layer.ChainID, os string) (layer.Layer, error) {
94
+func (ls *mockLayerStore) Register(reader io.Reader, parentID layer.ChainID) (layer.Layer, error) {
95 95
 	return ls.RegisterWithDescriptor(reader, parentID, distribution.Descriptor{})
96 96
 }
97 97
 
... ...
@@ -131,7 +131,7 @@ func (ls *mockLayerStore) Get(chainID layer.ChainID) (layer.Layer, error) {
131 131
 func (ls *mockLayerStore) Release(l layer.Layer) ([]layer.Metadata, error) {
132 132
 	return []layer.Metadata{}, nil
133 133
 }
134
-func (ls *mockLayerStore) CreateRWLayer(string, layer.ChainID, string, *layer.CreateRWLayerOpts) (layer.RWLayer, error) {
134
+func (ls *mockLayerStore) CreateRWLayer(string, layer.ChainID, *layer.CreateRWLayerOpts) (layer.RWLayer, error) {
135 135
 	return nil, errors.New("not implemented")
136 136
 }
137 137
 
... ...
@@ -150,14 +150,18 @@ func (ls *mockLayerStore) Cleanup() error {
150 150
 	return nil
151 151
 }
152 152
 
153
-func (ls *mockLayerStore) DriverStatus(string) [][2]string {
153
+func (ls *mockLayerStore) DriverStatus() [][2]string {
154 154
 	return [][2]string{}
155 155
 }
156 156
 
157
-func (ls *mockLayerStore) DriverName(string) string {
157
+func (ls *mockLayerStore) DriverName() string {
158 158
 	return "mock"
159 159
 }
160 160
 
161
+func (ls *mockLayerStore) OS() string {
162
+	return runtime.GOOS
163
+}
164
+
161 165
 type mockDownloadDescriptor struct {
162 166
 	currentDownloads *int32
163 167
 	id               string
... ...
@@ -272,7 +276,9 @@ func TestSuccessfulDownload(t *testing.T) {
272 272
 	}
273 273
 
274 274
 	layerStore := &mockLayerStore{make(map[layer.ChainID]*mockLayer)}
275
-	ldm := NewLayerDownloadManager(layerStore, maxDownloadConcurrency, func(m *LayerDownloadManager) { m.waitDuration = time.Millisecond })
275
+	lsMap := make(map[string]layer.Store)
276
+	lsMap[runtime.GOOS] = layerStore
277
+	ldm := NewLayerDownloadManager(lsMap, maxDownloadConcurrency, func(m *LayerDownloadManager) { m.waitDuration = time.Millisecond })
276 278
 
277 279
 	progressChan := make(chan progress.Progress)
278 280
 	progressDone := make(chan struct{})
... ...
@@ -291,7 +297,7 @@ func TestSuccessfulDownload(t *testing.T) {
291 291
 	firstDescriptor := descriptors[0].(*mockDownloadDescriptor)
292 292
 
293 293
 	// Pre-register the first layer to simulate an already-existing layer
294
-	l, err := layerStore.Register(firstDescriptor.mockTarStream(), "", runtime.GOOS)
294
+	l, err := layerStore.Register(firstDescriptor.mockTarStream(), "")
295 295
 	if err != nil {
296 296
 		t.Fatal(err)
297 297
 	}
... ...
@@ -334,8 +340,9 @@ func TestSuccessfulDownload(t *testing.T) {
334 334
 
335 335
 func TestCancelledDownload(t *testing.T) {
336 336
 	layerStore := &mockLayerStore{make(map[layer.ChainID]*mockLayer)}
337
-	ldm := NewLayerDownloadManager(layerStore, maxDownloadConcurrency, func(m *LayerDownloadManager) { m.waitDuration = time.Millisecond })
338
-
337
+	lsMap := make(map[string]layer.Store)
338
+	lsMap[runtime.GOOS] = layerStore
339
+	ldm := NewLayerDownloadManager(lsMap, maxDownloadConcurrency, func(m *LayerDownloadManager) { m.waitDuration = time.Millisecond })
339 340
 	progressChan := make(chan progress.Progress)
340 341
 	progressDone := make(chan struct{})
341 342
 
... ...
@@ -41,16 +41,16 @@ type imageMeta struct {
41 41
 
42 42
 type store struct {
43 43
 	sync.RWMutex
44
-	ls        LayerGetReleaser
44
+	lss       map[string]LayerGetReleaser
45 45
 	images    map[ID]*imageMeta
46 46
 	fs        StoreBackend
47 47
 	digestSet *digestset.Set
48 48
 }
49 49
 
50
-// NewImageStore returns new store object for given layer store
51
-func NewImageStore(fs StoreBackend, ls LayerGetReleaser) (Store, error) {
50
+// NewImageStore returns new store object for given set of layer stores
51
+func NewImageStore(fs StoreBackend, lss map[string]LayerGetReleaser) (Store, error) {
52 52
 	is := &store{
53
-		ls:        ls,
53
+		lss:       lss,
54 54
 		images:    make(map[ID]*imageMeta),
55 55
 		fs:        fs,
56 56
 		digestSet: digestset.NewSet(),
... ...
@@ -73,7 +73,7 @@ func (is *store) restore() error {
73 73
 		}
74 74
 		var l layer.Layer
75 75
 		if chainID := img.RootFS.ChainID(); chainID != "" {
76
-			l, err = is.ls.Get(chainID)
76
+			l, err = is.lss[img.OperatingSystem()].Get(chainID)
77 77
 			if err != nil {
78 78
 				return err
79 79
 			}
... ...
@@ -148,7 +148,7 @@ func (is *store) Create(config []byte) (ID, error) {
148 148
 
149 149
 	var l layer.Layer
150 150
 	if layerID != "" {
151
-		l, err = is.ls.Get(layerID)
151
+		l, err = is.lss[img.OperatingSystem()].Get(layerID)
152 152
 		if err != nil {
153 153
 			return "", errors.Wrapf(err, "failed to get layer %s", layerID)
154 154
 		}
... ...
@@ -231,7 +231,7 @@ func (is *store) Delete(id ID) ([]layer.Metadata, error) {
231 231
 	is.fs.Delete(id.Digest())
232 232
 
233 233
 	if imageMeta.layer != nil {
234
-		return is.ls.Release(imageMeta.layer)
234
+		return is.lss[imageMeta.layer.OS()].Release(imageMeta.layer)
235 235
 	}
236 236
 	return nil, nil
237 237
 }
... ...
@@ -1,6 +1,7 @@
1 1
 package image
2 2
 
3 3
 import (
4
+	"runtime"
4 5
 	"testing"
5 6
 
6 7
 	"github.com/docker/docker/internal/testutil"
... ...
@@ -25,7 +26,9 @@ func TestRestore(t *testing.T) {
25 25
 	err = fs.SetMetadata(id2, "parent", []byte(id1))
26 26
 	assert.NoError(t, err)
27 27
 
28
-	is, err := NewImageStore(fs, &mockLayerGetReleaser{})
28
+	mlgrMap := make(map[string]LayerGetReleaser)
29
+	mlgrMap[runtime.GOOS] = &mockLayerGetReleaser{}
30
+	is, err := NewImageStore(fs, mlgrMap)
29 31
 	assert.NoError(t, err)
30 32
 
31 33
 	assert.Len(t, is.Map(), 2)
... ...
@@ -142,7 +145,9 @@ func TestParentReset(t *testing.T) {
142 142
 func defaultImageStore(t *testing.T) (Store, func()) {
143 143
 	fsBackend, cleanup := defaultFSStoreBackend(t)
144 144
 
145
-	store, err := NewImageStore(fsBackend, &mockLayerGetReleaser{})
145
+	mlgrMap := make(map[string]LayerGetReleaser)
146
+	mlgrMap[runtime.GOOS] = &mockLayerGetReleaser{}
147
+	store, err := NewImageStore(fsBackend, mlgrMap)
146 148
 	assert.NoError(t, err)
147 149
 
148 150
 	return store, cleanup
... ...
@@ -107,14 +107,14 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool)
107 107
 			}
108 108
 			r := rootFS
109 109
 			r.Append(diffID)
110
-			newLayer, err := l.ls.Get(r.ChainID())
110
+			newLayer, err := l.lss[os].Get(r.ChainID())
111 111
 			if err != nil {
112 112
 				newLayer, err = l.loadLayer(layerPath, rootFS, diffID.String(), os, m.LayerSources[diffID], progressOutput)
113 113
 				if err != nil {
114 114
 					return err
115 115
 				}
116 116
 			}
117
-			defer layer.ReleaseAndLog(l.ls, newLayer)
117
+			defer layer.ReleaseAndLog(l.lss[os], newLayer)
118 118
 			if expected, actual := diffID, newLayer.DiffID(); expected != actual {
119 119
 				return fmt.Errorf("invalid diffID for layer %d: expected %q, got %q", i, expected, actual)
120 120
 			}
... ...
@@ -205,10 +205,10 @@ func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string,
205 205
 	}
206 206
 	defer inflatedLayerData.Close()
207 207
 
208
-	if ds, ok := l.ls.(layer.DescribableStore); ok {
209
-		return ds.RegisterWithDescriptor(inflatedLayerData, rootFS.ChainID(), os, foreignSrc)
208
+	if ds, ok := l.lss[os].(layer.DescribableStore); ok {
209
+		return ds.RegisterWithDescriptor(inflatedLayerData, rootFS.ChainID(), foreignSrc)
210 210
 	}
211
-	return l.ls.Register(inflatedLayerData, rootFS.ChainID(), os)
211
+	return l.lss[os].Register(inflatedLayerData, rootFS.ChainID())
212 212
 }
213 213
 
214 214
 func (l *tarexporter) setLoadedTag(ref reference.Named, imgID digest.Digest, outStream io.Writer) error {
... ...
@@ -302,6 +302,9 @@ func (l *tarexporter) legacyLoadImage(oldID, sourceDir string, loadedMap map[str
302 302
 	if err := checkCompatibleOS(img.OS); err != nil {
303 303
 		return err
304 304
 	}
305
+	if img.OS == "" {
306
+		img.OS = runtime.GOOS
307
+	}
305 308
 
306 309
 	var parentID image.ID
307 310
 	if img.Parent != "" {
... ...
@@ -335,7 +338,7 @@ func (l *tarexporter) legacyLoadImage(oldID, sourceDir string, loadedMap map[str
335 335
 	if err != nil {
336 336
 		return err
337 337
 	}
338
-	newLayer, err := l.loadLayer(layerPath, *rootFS, oldID, "", distribution.Descriptor{}, progressOutput)
338
+	newLayer, err := l.loadLayer(layerPath, *rootFS, oldID, img.OS, distribution.Descriptor{}, progressOutput)
339 339
 	if err != nil {
340 340
 		return err
341 341
 	}
... ...
@@ -356,7 +359,7 @@ func (l *tarexporter) legacyLoadImage(oldID, sourceDir string, loadedMap map[str
356 356
 		return err
357 357
 	}
358 358
 
359
-	metadata, err := l.ls.Release(newLayer)
359
+	metadata, err := l.lss[img.OS].Release(newLayer)
360 360
 	layer.LogReleaseMetadata(metadata)
361 361
 	if err != nil {
362 362
 		return err
... ...
@@ -7,6 +7,7 @@ import (
7 7
 	"io/ioutil"
8 8
 	"os"
9 9
 	"path/filepath"
10
+	"runtime"
10 11
 	"time"
11 12
 
12 13
 	"github.com/docker/distribution"
... ...
@@ -153,7 +154,11 @@ func (l *tarexporter) takeLayerReference(id image.ID, imgDescr *imageDescriptor)
153 153
 	if topLayerID == "" {
154 154
 		return nil
155 155
 	}
156
-	layer, err := l.ls.Get(topLayerID)
156
+	os := img.OS
157
+	if os == "" {
158
+		os = runtime.GOOS
159
+	}
160
+	layer, err := l.lss[os].Get(topLayerID)
157 161
 	if err != nil {
158 162
 		return err
159 163
 	}
... ...
@@ -165,7 +170,11 @@ func (l *tarexporter) takeLayerReference(id image.ID, imgDescr *imageDescriptor)
165 165
 func (l *tarexporter) releaseLayerReferences(imgDescr map[image.ID]*imageDescriptor) error {
166 166
 	for _, descr := range imgDescr {
167 167
 		if descr.layerRef != nil {
168
-			l.ls.Release(descr.layerRef)
168
+			os := descr.image.OS
169
+			if os == "" {
170
+				os = runtime.GOOS
171
+			}
172
+			l.lss[os].Release(descr.layerRef)
169 173
 		}
170 174
 	}
171 175
 	return nil
... ...
@@ -356,11 +365,15 @@ func (s *saveSession) saveLayer(id layer.ChainID, legacyImg image.V1Image, creat
356 356
 
357 357
 	// serialize filesystem
358 358
 	layerPath := filepath.Join(outDir, legacyLayerFileName)
359
-	l, err := s.ls.Get(id)
359
+	operatingSystem := legacyImg.OS
360
+	if operatingSystem == "" {
361
+		operatingSystem = runtime.GOOS
362
+	}
363
+	l, err := s.lss[operatingSystem].Get(id)
360 364
 	if err != nil {
361 365
 		return distribution.Descriptor{}, err
362 366
 	}
363
-	defer layer.ReleaseAndLog(s.ls, l)
367
+	defer layer.ReleaseAndLog(s.lss[operatingSystem], l)
364 368
 
365 369
 	if oldPath, exists := s.diffIDPaths[l.DiffID()]; exists {
366 370
 		relPath, err := filepath.Rel(outDir, oldPath)
... ...
@@ -25,7 +25,7 @@ type manifestItem struct {
25 25
 
26 26
 type tarexporter struct {
27 27
 	is             image.Store
28
-	ls             layer.Store
28
+	lss            map[string]layer.Store
29 29
 	rs             refstore.Store
30 30
 	loggerImgEvent LogImageEvent
31 31
 }
... ...
@@ -37,10 +37,10 @@ type LogImageEvent interface {
37 37
 }
38 38
 
39 39
 // NewTarExporter returns new Exporter for tar packages
40
-func NewTarExporter(is image.Store, ls layer.Store, rs refstore.Store, loggerImgEvent LogImageEvent) image.Exporter {
40
+func NewTarExporter(is image.Store, lss map[string]layer.Store, rs refstore.Store, loggerImgEvent LogImageEvent) image.Exporter {
41 41
 	return &tarexporter{
42 42
 		is:             is,
43
-		ls:             ls,
43
+		lss:            lss,
44 44
 		rs:             rs,
45 45
 		loggerImgEvent: loggerImgEvent,
46 46
 	}
... ...
@@ -6,7 +6,6 @@ import (
6 6
 	"fmt"
7 7
 	"io"
8 8
 	"io/ioutil"
9
-	"runtime"
10 9
 )
11 10
 
12 11
 // DigestSHA256EmptyTar is the canonical sha256 digest of empty tar file -
... ...
@@ -44,6 +43,10 @@ func (el *emptyLayer) Parent() Layer {
44 44
 	return nil
45 45
 }
46 46
 
47
+func (el *emptyLayer) OS() string {
48
+	return ""
49
+}
50
+
47 51
 func (el *emptyLayer) Size() (size int64, err error) {
48 52
 	return 0, nil
49 53
 }
... ...
@@ -56,10 +59,6 @@ func (el *emptyLayer) Metadata() (map[string]string, error) {
56 56
 	return make(map[string]string), nil
57 57
 }
58 58
 
59
-func (el *emptyLayer) OS() string {
60
-	return runtime.GOOS
61
-}
62
-
63 59
 // IsEmpty returns true if the layer is an EmptyLayer
64 60
 func IsEmpty(diffID DiffID) bool {
65 61
 	return diffID == DigestSHA256EmptyTar
... ...
@@ -186,25 +186,26 @@ type CreateRWLayerOpts struct {
186 186
 // Store represents a backend for managing both
187 187
 // read-only and read-write layers.
188 188
 type Store interface {
189
-	Register(io.Reader, ChainID, string) (Layer, error)
189
+	Register(io.Reader, ChainID) (Layer, error)
190 190
 	Get(ChainID) (Layer, error)
191 191
 	Map() map[ChainID]Layer
192 192
 	Release(Layer) ([]Metadata, error)
193 193
 
194
-	CreateRWLayer(id string, parent ChainID, os string, opts *CreateRWLayerOpts) (RWLayer, error)
194
+	CreateRWLayer(id string, parent ChainID, opts *CreateRWLayerOpts) (RWLayer, error)
195 195
 	GetRWLayer(id string) (RWLayer, error)
196 196
 	GetMountID(id string) (string, error)
197 197
 	ReleaseRWLayer(RWLayer) ([]Metadata, error)
198 198
 
199 199
 	Cleanup() error
200
-	DriverStatus(os string) [][2]string
201
-	DriverName(os string) string
200
+	DriverStatus() [][2]string
201
+	DriverName() string
202
+	OS() string
202 203
 }
203 204
 
204 205
 // DescribableStore represents a layer store capable of storing
205 206
 // descriptors for layers.
206 207
 type DescribableStore interface {
207
-	RegisterWithDescriptor(io.Reader, ChainID, string, distribution.Descriptor) (Layer, error)
208
+	RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error)
208 209
 }
209 210
 
210 211
 // MetadataTransaction represents functions for setting layer metadata
... ...
@@ -5,7 +5,6 @@ import (
5 5
 	"fmt"
6 6
 	"io"
7 7
 	"io/ioutil"
8
-	"runtime"
9 8
 	"sync"
10 9
 
11 10
 	"github.com/docker/distribution"
... ...
@@ -29,76 +28,70 @@ const maxLayerDepth = 125
29 29
 
30 30
 type layerStore struct {
31 31
 	store       MetadataStore
32
-	drivers     map[string]graphdriver.Driver
33
-	useTarSplit map[string]bool
32
+	driver      graphdriver.Driver
33
+	useTarSplit bool
34 34
 
35 35
 	layerMap map[ChainID]*roLayer
36 36
 	layerL   sync.Mutex
37 37
 
38 38
 	mounts map[string]*mountedLayer
39 39
 	mountL sync.Mutex
40
+	os     string
40 41
 }
41 42
 
42 43
 // StoreOptions are the options used to create a new Store instance
43 44
 type StoreOptions struct {
44 45
 	Root                      string
45
-	GraphDrivers              map[string]string
46 46
 	MetadataStorePathTemplate string
47
+	GraphDriver               string
47 48
 	GraphDriverOptions        []string
48 49
 	IDMappings                *idtools.IDMappings
49 50
 	PluginGetter              plugingetter.PluginGetter
50 51
 	ExperimentalEnabled       bool
52
+	OS                        string
51 53
 }
52 54
 
53 55
 // NewStoreFromOptions creates a new Store instance
54 56
 func NewStoreFromOptions(options StoreOptions) (Store, error) {
55
-	drivers := make(map[string]graphdriver.Driver)
56
-	for os, drivername := range options.GraphDrivers {
57
-		var err error
58
-		drivers[os], err = graphdriver.New(drivername,
59
-			options.PluginGetter,
60
-			graphdriver.Options{
61
-				Root:                options.Root,
62
-				DriverOptions:       options.GraphDriverOptions,
63
-				UIDMaps:             options.IDMappings.UIDs(),
64
-				GIDMaps:             options.IDMappings.GIDs(),
65
-				ExperimentalEnabled: options.ExperimentalEnabled,
66
-			})
67
-		if err != nil {
68
-			return nil, fmt.Errorf("error initializing graphdriver: %v", err)
69
-		}
70
-		logrus.Debugf("Initialized graph driver %s", drivername)
57
+	driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{
58
+		Root:                options.Root,
59
+		DriverOptions:       options.GraphDriverOptions,
60
+		UIDMaps:             options.IDMappings.UIDs(),
61
+		GIDMaps:             options.IDMappings.GIDs(),
62
+		ExperimentalEnabled: options.ExperimentalEnabled,
63
+	})
64
+	if err != nil {
65
+		return nil, fmt.Errorf("error initializing graphdriver: %v", err)
71 66
 	}
67
+	logrus.Debugf("Initialized graph driver %s", driver)
72 68
 
73
-	fms, err := NewFSMetadataStore(fmt.Sprintf(options.MetadataStorePathTemplate, options.GraphDrivers[runtime.GOOS]))
69
+	fms, err := NewFSMetadataStore(fmt.Sprintf(options.MetadataStorePathTemplate, driver))
74 70
 	if err != nil {
75 71
 		return nil, err
76 72
 	}
77 73
 
78
-	return NewStoreFromGraphDrivers(fms, drivers)
74
+	return NewStoreFromGraphDriver(fms, driver, options.OS)
79 75
 }
80 76
 
81
-// NewStoreFromGraphDrivers creates a new Store instance using the provided
82
-// metadata store and graph drivers. The metadata store will be used to restore
77
+// NewStoreFromGraphDriver creates a new Store instance using the provided
78
+// metadata store and graph driver. The metadata store will be used to restore
83 79
 // the Store.
84
-func NewStoreFromGraphDrivers(store MetadataStore, drivers map[string]graphdriver.Driver) (Store, error) {
85
-
86
-	useTarSplit := make(map[string]bool)
87
-	for os, driver := range drivers {
88
-
89
-		caps := graphdriver.Capabilities{}
90
-		if capDriver, ok := driver.(graphdriver.CapabilityDriver); ok {
91
-			caps = capDriver.Capabilities()
92
-		}
93
-		useTarSplit[os] = !caps.ReproducesExactDiffs
80
+func NewStoreFromGraphDriver(store MetadataStore, driver graphdriver.Driver, os string) (Store, error) {
81
+	if !system.IsOSSupported(os) {
82
+		return nil, fmt.Errorf("failed to initialize layer store as operating system '%s' is not supported", os)
83
+	}
84
+	caps := graphdriver.Capabilities{}
85
+	if capDriver, ok := driver.(graphdriver.CapabilityDriver); ok {
86
+		caps = capDriver.Capabilities()
94 87
 	}
95 88
 
96 89
 	ls := &layerStore{
97 90
 		store:       store,
98
-		drivers:     drivers,
91
+		driver:      driver,
99 92
 		layerMap:    map[ChainID]*roLayer{},
100 93
 		mounts:      map[string]*mountedLayer{},
101
-		useTarSplit: useTarSplit,
94
+		useTarSplit: !caps.ReproducesExactDiffs,
95
+		os:          os,
102 96
 	}
103 97
 
104 98
 	ids, mounts, err := store.List()
... ...
@@ -162,6 +155,10 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) {
162 162
 		return nil, fmt.Errorf("failed to get operating system for %s: %s", layer, err)
163 163
 	}
164 164
 
165
+	if os != ls.os {
166
+		return nil, fmt.Errorf("failed to load layer with os %s into layerstore for %s", os, ls.os)
167
+	}
168
+
165 169
 	cl = &roLayer{
166 170
 		chainID:    layer,
167 171
 		diffID:     diff,
... ...
@@ -170,7 +167,6 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) {
170 170
 		layerStore: ls,
171 171
 		references: map[Layer]struct{}{},
172 172
 		descriptor: descriptor,
173
-		os:         os,
174 173
 	}
175 174
 
176 175
 	if parent != "" {
... ...
@@ -234,7 +230,7 @@ func (ls *layerStore) applyTar(tx MetadataTransaction, ts io.Reader, parent stri
234 234
 	tr := io.TeeReader(ts, digester.Hash())
235 235
 
236 236
 	rdr := tr
237
-	if ls.useTarSplit[layer.os] {
237
+	if ls.useTarSplit {
238 238
 		tsw, err := tx.TarSplitWriter(true)
239 239
 		if err != nil {
240 240
 			return err
... ...
@@ -250,7 +246,7 @@ func (ls *layerStore) applyTar(tx MetadataTransaction, ts io.Reader, parent stri
250 250
 		}
251 251
 	}
252 252
 
253
-	applySize, err := ls.drivers[layer.os].ApplyDiff(layer.cacheID, parent, rdr)
253
+	applySize, err := ls.driver.ApplyDiff(layer.cacheID, parent, rdr)
254 254
 	if err != nil {
255 255
 		return err
256 256
 	}
... ...
@@ -266,11 +262,11 @@ func (ls *layerStore) applyTar(tx MetadataTransaction, ts io.Reader, parent stri
266 266
 	return nil
267 267
 }
268 268
 
269
-func (ls *layerStore) Register(ts io.Reader, parent ChainID, os string) (Layer, error) {
270
-	return ls.registerWithDescriptor(ts, parent, os, distribution.Descriptor{})
269
+func (ls *layerStore) Register(ts io.Reader, parent ChainID) (Layer, error) {
270
+	return ls.registerWithDescriptor(ts, parent, distribution.Descriptor{})
271 271
 }
272 272
 
273
-func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, os string, descriptor distribution.Descriptor) (Layer, error) {
273
+func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, descriptor distribution.Descriptor) (Layer, error) {
274 274
 	// err is used to hold the error which will always trigger
275 275
 	// cleanup of creates sources but may not be an error returned
276 276
 	// to the caller (already exists).
... ...
@@ -298,14 +294,6 @@ func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, os st
298 298
 		}
299 299
 	}
300 300
 
301
-	// Validate the operating system is valid
302
-	if os == "" {
303
-		os = runtime.GOOS
304
-	}
305
-	if err := system.ValidatePlatform(system.ParsePlatform(os)); err != nil {
306
-		return nil, err
307
-	}
308
-
309 301
 	// Create new roLayer
310 302
 	layer := &roLayer{
311 303
 		parent:         p,
... ...
@@ -314,10 +302,9 @@ func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, os st
314 314
 		layerStore:     ls,
315 315
 		references:     map[Layer]struct{}{},
316 316
 		descriptor:     descriptor,
317
-		os:             os,
318 317
 	}
319 318
 
320
-	if err = ls.drivers[os].Create(layer.cacheID, pid, nil); err != nil {
319
+	if err = ls.driver.Create(layer.cacheID, pid, nil); err != nil {
321 320
 		return nil, err
322 321
 	}
323 322
 
... ...
@@ -329,7 +316,7 @@ func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, os st
329 329
 	defer func() {
330 330
 		if err != nil {
331 331
 			logrus.Debugf("Cleaning up layer %s: %v", layer.cacheID, err)
332
-			if err := ls.drivers[os].Remove(layer.cacheID); err != nil {
332
+			if err := ls.driver.Remove(layer.cacheID); err != nil {
333 333
 				logrus.Errorf("Error cleaning up cache layer %s: %v", layer.cacheID, err)
334 334
 			}
335 335
 			if err := tx.Cancel(); err != nil {
... ...
@@ -413,7 +400,7 @@ func (ls *layerStore) Map() map[ChainID]Layer {
413 413
 }
414 414
 
415 415
 func (ls *layerStore) deleteLayer(layer *roLayer, metadata *Metadata) error {
416
-	err := ls.drivers[layer.os].Remove(layer.cacheID)
416
+	err := ls.driver.Remove(layer.cacheID)
417 417
 	if err != nil {
418 418
 		return err
419 419
 	}
... ...
@@ -483,7 +470,7 @@ func (ls *layerStore) Release(l Layer) ([]Metadata, error) {
483 483
 	return ls.releaseLayer(layer)
484 484
 }
485 485
 
486
-func (ls *layerStore) CreateRWLayer(name string, parent ChainID, os string, opts *CreateRWLayerOpts) (RWLayer, error) {
486
+func (ls *layerStore) CreateRWLayer(name string, parent ChainID, opts *CreateRWLayerOpts) (RWLayer, error) {
487 487
 	var (
488 488
 		storageOpt map[string]string
489 489
 		initFunc   MountInit
... ...
@@ -523,21 +510,16 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, os string, opts
523 523
 		}()
524 524
 	}
525 525
 
526
-	// Ensure the operating system is set to the host OS if not populated.
527
-	if os == "" {
528
-		os = runtime.GOOS
529
-	}
530 526
 	m = &mountedLayer{
531 527
 		name:       name,
532 528
 		parent:     p,
533 529
 		mountID:    ls.mountID(name),
534 530
 		layerStore: ls,
535 531
 		references: map[RWLayer]*referencedRWLayer{},
536
-		os:         os,
537 532
 	}
538 533
 
539 534
 	if initFunc != nil {
540
-		pid, err = ls.initMount(m.mountID, m.os, pid, mountLabel, initFunc, storageOpt)
535
+		pid, err = ls.initMount(m.mountID, pid, mountLabel, initFunc, storageOpt)
541 536
 		if err != nil {
542 537
 			return nil, err
543 538
 		}
... ...
@@ -548,7 +530,7 @@ func (ls *layerStore) CreateRWLayer(name string, parent ChainID, os string, opts
548 548
 		StorageOpt: storageOpt,
549 549
 	}
550 550
 
551
-	if err = ls.drivers[os].CreateReadWrite(m.mountID, pid, createOpts); err != nil {
551
+	if err = ls.driver.CreateReadWrite(m.mountID, pid, createOpts); err != nil {
552 552
 		return nil, err
553 553
 	}
554 554
 	if err = ls.saveMount(m); err != nil {
... ...
@@ -597,14 +579,14 @@ func (ls *layerStore) ReleaseRWLayer(l RWLayer) ([]Metadata, error) {
597 597
 		return []Metadata{}, nil
598 598
 	}
599 599
 
600
-	if err := ls.drivers[l.OS()].Remove(m.mountID); err != nil {
600
+	if err := ls.driver.Remove(m.mountID); err != nil {
601 601
 		logrus.Errorf("Error removing mounted layer %s: %s", m.name, err)
602 602
 		m.retakeReference(l)
603 603
 		return nil, err
604 604
 	}
605 605
 
606 606
 	if m.initID != "" {
607
-		if err := ls.drivers[l.OS()].Remove(m.initID); err != nil {
607
+		if err := ls.driver.Remove(m.initID); err != nil {
608 608
 			logrus.Errorf("Error removing init layer %s: %s", m.name, err)
609 609
 			m.retakeReference(l)
610 610
 			return nil, err
... ...
@@ -650,7 +632,7 @@ func (ls *layerStore) saveMount(mount *mountedLayer) error {
650 650
 	return nil
651 651
 }
652 652
 
653
-func (ls *layerStore) initMount(graphID, os, parent, mountLabel string, initFunc MountInit, storageOpt map[string]string) (string, error) {
653
+func (ls *layerStore) initMount(graphID, parent, mountLabel string, initFunc MountInit, storageOpt map[string]string) (string, error) {
654 654
 	// Use "<graph-id>-init" to maintain compatibility with graph drivers
655 655
 	// which are expecting this layer with this special name. If all
656 656
 	// graph drivers can be updated to not rely on knowing about this layer
... ...
@@ -662,20 +644,20 @@ func (ls *layerStore) initMount(graphID, os, parent, mountLabel string, initFunc
662 662
 		StorageOpt: storageOpt,
663 663
 	}
664 664
 
665
-	if err := ls.drivers[os].CreateReadWrite(initID, parent, createOpts); err != nil {
665
+	if err := ls.driver.CreateReadWrite(initID, parent, createOpts); err != nil {
666 666
 		return "", err
667 667
 	}
668
-	p, err := ls.drivers[os].Get(initID, "")
668
+	p, err := ls.driver.Get(initID, "")
669 669
 	if err != nil {
670 670
 		return "", err
671 671
 	}
672 672
 
673 673
 	if err := initFunc(p); err != nil {
674
-		ls.drivers[os].Put(initID)
674
+		ls.driver.Put(initID)
675 675
 		return "", err
676 676
 	}
677 677
 
678
-	if err := ls.drivers[os].Put(initID); err != nil {
678
+	if err := ls.driver.Put(initID); err != nil {
679 679
 		return "", err
680 680
 	}
681 681
 
... ...
@@ -683,13 +665,13 @@ func (ls *layerStore) initMount(graphID, os, parent, mountLabel string, initFunc
683 683
 }
684 684
 
685 685
 func (ls *layerStore) getTarStream(rl *roLayer) (io.ReadCloser, error) {
686
-	if !ls.useTarSplit[rl.os] {
686
+	if !ls.useTarSplit {
687 687
 		var parentCacheID string
688 688
 		if rl.parent != nil {
689 689
 			parentCacheID = rl.parent.cacheID
690 690
 		}
691 691
 
692
-		return ls.drivers[rl.os].Diff(rl.cacheID, parentCacheID)
692
+		return ls.driver.Diff(rl.cacheID, parentCacheID)
693 693
 	}
694 694
 
695 695
 	r, err := ls.store.TarSplitReader(rl.chainID)
... ...
@@ -699,7 +681,7 @@ func (ls *layerStore) getTarStream(rl *roLayer) (io.ReadCloser, error) {
699 699
 
700 700
 	pr, pw := io.Pipe()
701 701
 	go func() {
702
-		err := ls.assembleTarTo(rl.cacheID, rl.os, r, nil, pw)
702
+		err := ls.assembleTarTo(rl.cacheID, r, nil, pw)
703 703
 		if err != nil {
704 704
 			pw.CloseWithError(err)
705 705
 		} else {
... ...
@@ -710,10 +692,10 @@ func (ls *layerStore) getTarStream(rl *roLayer) (io.ReadCloser, error) {
710 710
 	return pr, nil
711 711
 }
712 712
 
713
-func (ls *layerStore) assembleTarTo(graphID, os string, metadata io.ReadCloser, size *int64, w io.Writer) error {
714
-	diffDriver, ok := ls.drivers[os].(graphdriver.DiffGetterDriver)
713
+func (ls *layerStore) assembleTarTo(graphID string, metadata io.ReadCloser, size *int64, w io.Writer) error {
714
+	diffDriver, ok := ls.driver.(graphdriver.DiffGetterDriver)
715 715
 	if !ok {
716
-		diffDriver = &naiveDiffPathDriver{ls.drivers[os]}
716
+		diffDriver = &naiveDiffPathDriver{ls.driver}
717 717
 	}
718 718
 
719 719
 	defer metadata.Close()
... ...
@@ -732,27 +714,19 @@ func (ls *layerStore) assembleTarTo(graphID, os string, metadata io.ReadCloser,
732 732
 }
733 733
 
734 734
 func (ls *layerStore) Cleanup() error {
735
-	var err error
736
-	for _, driver := range ls.drivers {
737
-		if e := driver.Cleanup(); e != nil {
738
-			err = fmt.Errorf("%s - %s", err.Error(), e.Error())
739
-		}
740
-	}
741
-	return err
735
+	return ls.driver.Cleanup()
742 736
 }
743 737
 
744
-func (ls *layerStore) DriverStatus(os string) [][2]string {
745
-	if os == "" {
746
-		os = runtime.GOOS
747
-	}
748
-	return ls.drivers[os].Status()
738
+func (ls *layerStore) DriverStatus() [][2]string {
739
+	return ls.driver.Status()
749 740
 }
750 741
 
751
-func (ls *layerStore) DriverName(os string) string {
752
-	if os == "" {
753
-		os = runtime.GOOS
754
-	}
755
-	return ls.drivers[os].String()
742
+func (ls *layerStore) DriverName() string {
743
+	return ls.driver.String()
744
+}
745
+
746
+func (ls *layerStore) OS() string {
747
+	return ls.os
756 748
 }
757 749
 
758 750
 type naiveDiffPathDriver struct {
... ...
@@ -6,6 +6,6 @@ import (
6 6
 	"github.com/docker/distribution"
7 7
 )
8 8
 
9
-func (ls *layerStore) RegisterWithDescriptor(ts io.Reader, parent ChainID, os string, descriptor distribution.Descriptor) (Layer, error) {
10
-	return ls.registerWithDescriptor(ts, parent, os, descriptor)
9
+func (ls *layerStore) RegisterWithDescriptor(ts io.Reader, parent ChainID, descriptor distribution.Descriptor) (Layer, error) {
10
+	return ls.registerWithDescriptor(ts, parent, descriptor)
11 11
 }
... ...
@@ -73,9 +73,7 @@ func newTestStore(t *testing.T) (Store, string, func()) {
73 73
 	if err != nil {
74 74
 		t.Fatal(err)
75 75
 	}
76
-	graphs := make(map[string]graphdriver.Driver)
77
-	graphs[runtime.GOOS] = graph
78
-	ls, err := NewStoreFromGraphDrivers(fms, graphs)
76
+	ls, err := NewStoreFromGraphDriver(fms, graph, runtime.GOOS)
79 77
 	if err != nil {
80 78
 		t.Fatal(err)
81 79
 	}
... ...
@@ -90,7 +88,7 @@ type layerInit func(root containerfs.ContainerFS) error
90 90
 
91 91
 func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) {
92 92
 	containerID := stringid.GenerateRandomID()
93
-	mount, err := ls.CreateRWLayer(containerID, parent, runtime.GOOS, nil)
93
+	mount, err := ls.CreateRWLayer(containerID, parent, nil)
94 94
 	if err != nil {
95 95
 		return nil, err
96 96
 	}
... ...
@@ -110,7 +108,7 @@ func createLayer(ls Store, parent ChainID, layerFunc layerInit) (Layer, error) {
110 110
 	}
111 111
 	defer ts.Close()
112 112
 
113
-	layer, err := ls.Register(ts, parent, runtime.GOOS)
113
+	layer, err := ls.Register(ts, parent)
114 114
 	if err != nil {
115 115
 		return nil, err
116 116
 	}
... ...
@@ -279,7 +277,7 @@ func TestMountAndRegister(t *testing.T) {
279 279
 	size, _ := layer.Size()
280 280
 	t.Logf("Layer size: %d", size)
281 281
 
282
-	mount2, err := ls.CreateRWLayer("new-test-mount", layer.ChainID(), runtime.GOOS, nil)
282
+	mount2, err := ls.CreateRWLayer("new-test-mount", layer.ChainID(), nil)
283 283
 	if err != nil {
284 284
 		t.Fatal(err)
285 285
 	}
... ...
@@ -387,7 +385,7 @@ func TestStoreRestore(t *testing.T) {
387 387
 		t.Fatal(err)
388 388
 	}
389 389
 
390
-	m, err := ls.CreateRWLayer("some-mount_name", layer3.ChainID(), runtime.GOOS, nil)
390
+	m, err := ls.CreateRWLayer("some-mount_name", layer3.ChainID(), nil)
391 391
 	if err != nil {
392 392
 		t.Fatal(err)
393 393
 	}
... ...
@@ -405,7 +403,7 @@ func TestStoreRestore(t *testing.T) {
405 405
 		t.Fatal(err)
406 406
 	}
407 407
 
408
-	ls2, err := NewStoreFromGraphDrivers(ls.(*layerStore).store, ls.(*layerStore).drivers)
408
+	ls2, err := NewStoreFromGraphDriver(ls.(*layerStore).store, ls.(*layerStore).driver, runtime.GOOS)
409 409
 	if err != nil {
410 410
 		t.Fatal(err)
411 411
 	}
... ...
@@ -418,7 +416,7 @@ func TestStoreRestore(t *testing.T) {
418 418
 	assertLayerEqual(t, layer3b, layer3)
419 419
 
420 420
 	// Create again with same name, should return error
421
-	if _, err := ls2.CreateRWLayer("some-mount_name", layer3b.ChainID(), runtime.GOOS, nil); err == nil {
421
+	if _, err := ls2.CreateRWLayer("some-mount_name", layer3b.ChainID(), nil); err == nil {
422 422
 		t.Fatal("Expected error creating mount with same name")
423 423
 	} else if err != ErrMountNameConflict {
424 424
 		t.Fatal(err)
... ...
@@ -500,13 +498,13 @@ func TestTarStreamStability(t *testing.T) {
500 500
 		t.Fatal(err)
501 501
 	}
502 502
 
503
-	layer1, err := ls.Register(bytes.NewReader(tar1), "", runtime.GOOS)
503
+	layer1, err := ls.Register(bytes.NewReader(tar1), "")
504 504
 	if err != nil {
505 505
 		t.Fatal(err)
506 506
 	}
507 507
 
508 508
 	// hack layer to add file
509
-	p, err := ls.(*layerStore).drivers[runtime.GOOS].Get(layer1.(*referencedCacheLayer).cacheID, "")
509
+	p, err := ls.(*layerStore).driver.Get(layer1.(*referencedCacheLayer).cacheID, "")
510 510
 	if err != nil {
511 511
 		t.Fatal(err)
512 512
 	}
... ...
@@ -515,11 +513,11 @@ func TestTarStreamStability(t *testing.T) {
515 515
 		t.Fatal(err)
516 516
 	}
517 517
 
518
-	if err := ls.(*layerStore).drivers[runtime.GOOS].Put(layer1.(*referencedCacheLayer).cacheID); err != nil {
518
+	if err := ls.(*layerStore).driver.Put(layer1.(*referencedCacheLayer).cacheID); err != nil {
519 519
 		t.Fatal(err)
520 520
 	}
521 521
 
522
-	layer2, err := ls.Register(bytes.NewReader(tar2), layer1.ChainID(), runtime.GOOS)
522
+	layer2, err := ls.Register(bytes.NewReader(tar2), layer1.ChainID())
523 523
 	if err != nil {
524 524
 		t.Fatal(err)
525 525
 	}
... ...
@@ -687,12 +685,12 @@ func TestRegisterExistingLayer(t *testing.T) {
687 687
 		t.Fatal(err)
688 688
 	}
689 689
 
690
-	layer2a, err := ls.Register(bytes.NewReader(tar1), layer1.ChainID(), runtime.GOOS)
690
+	layer2a, err := ls.Register(bytes.NewReader(tar1), layer1.ChainID())
691 691
 	if err != nil {
692 692
 		t.Fatal(err)
693 693
 	}
694 694
 
695
-	layer2b, err := ls.Register(bytes.NewReader(tar1), layer1.ChainID(), runtime.GOOS)
695
+	layer2b, err := ls.Register(bytes.NewReader(tar1), layer1.ChainID())
696 696
 	if err != nil {
697 697
 		t.Fatal(err)
698 698
 	}
... ...
@@ -727,12 +725,12 @@ func TestTarStreamVerification(t *testing.T) {
727 727
 		t.Fatal(err)
728 728
 	}
729 729
 
730
-	layer1, err := ls.Register(bytes.NewReader(tar1), "", runtime.GOOS)
730
+	layer1, err := ls.Register(bytes.NewReader(tar1), "")
731 731
 	if err != nil {
732 732
 		t.Fatal(err)
733 733
 	}
734 734
 
735
-	layer2, err := ls.Register(bytes.NewReader(tar2), "", runtime.GOOS)
735
+	layer2, err := ls.Register(bytes.NewReader(tar2), "")
736 736
 	if err != nil {
737 737
 		t.Fatal(err)
738 738
 	}
... ...
@@ -3,7 +3,6 @@
3 3
 package layer
4 4
 
5 5
 import (
6
-	"runtime"
7 6
 	"testing"
8 7
 )
9 8
 
... ...
@@ -13,7 +12,7 @@ func graphDiffSize(ls Store, l Layer) (int64, error) {
13 13
 	if cl.parent != nil {
14 14
 		parent = cl.parent.cacheID
15 15
 	}
16
-	return ls.(*layerStore).drivers[runtime.GOOS].DiffSize(cl.cacheID, parent)
16
+	return ls.(*layerStore).driver.DiffSize(cl.cacheID, parent)
17 17
 }
18 18
 
19 19
 // Unix as Windows graph driver does not support Changes which is indirectly
... ...
@@ -25,15 +25,15 @@ func GetLayerPath(s Store, layer ChainID) (string, error) {
25 25
 		return "", ErrLayerDoesNotExist
26 26
 	}
27 27
 
28
-	if layerGetter, ok := ls.drivers[rl.os].(Getter); ok {
28
+	if layerGetter, ok := ls.driver.(Getter); ok {
29 29
 		return layerGetter.GetLayerPath(rl.cacheID)
30 30
 	}
31
-	path, err := ls.drivers[rl.os].Get(rl.cacheID, "")
31
+	path, err := ls.driver.Get(rl.cacheID, "")
32 32
 	if err != nil {
33 33
 		return "", err
34 34
 	}
35 35
 
36
-	if err := ls.drivers[rl.os].Put(rl.cacheID); err != nil {
36
+	if err := ls.driver.Put(rl.cacheID); err != nil {
37 37
 		return "", err
38 38
 	}
39 39
 
... ...
@@ -6,7 +6,6 @@ import (
6 6
 	"fmt"
7 7
 	"io"
8 8
 	"os"
9
-	"runtime"
10 9
 
11 10
 	"github.com/opencontainers/go-digest"
12 11
 	"github.com/sirupsen/logrus"
... ...
@@ -17,7 +16,7 @@ import (
17 17
 // CreateRWLayerByGraphID creates a RWLayer in the layer store using
18 18
 // the provided name with the given graphID. To get the RWLayer
19 19
 // after migration the layer may be retrieved by the given name.
20
-func (ls *layerStore) CreateRWLayerByGraphID(name, graphID, os string, parent ChainID) (err error) {
20
+func (ls *layerStore) CreateRWLayerByGraphID(name, graphID string, parent ChainID) (err error) {
21 21
 	ls.mountL.Lock()
22 22
 	defer ls.mountL.Unlock()
23 23
 	m, ok := ls.mounts[name]
... ...
@@ -32,11 +31,7 @@ func (ls *layerStore) CreateRWLayerByGraphID(name, graphID, os string, parent Ch
32 32
 		return nil
33 33
 	}
34 34
 
35
-	// Ensure the operating system is set to the host OS if not populated.
36
-	if os == "" {
37
-		os = runtime.GOOS
38
-	}
39
-	if !ls.drivers[os].Exists(graphID) {
35
+	if !ls.driver.Exists(graphID) {
40 36
 		return fmt.Errorf("graph ID does not exist: %q", graphID)
41 37
 	}
42 38
 
... ...
@@ -65,12 +60,11 @@ func (ls *layerStore) CreateRWLayerByGraphID(name, graphID, os string, parent Ch
65 65
 		mountID:    graphID,
66 66
 		layerStore: ls,
67 67
 		references: map[RWLayer]*referencedRWLayer{},
68
-		os:         os,
69 68
 	}
70 69
 
71 70
 	// Check for existing init layer
72 71
 	initID := fmt.Sprintf("%s-init", graphID)
73
-	if ls.drivers[os].Exists(initID) {
72
+	if ls.driver.Exists(initID) {
74 73
 		m.initID = initID
75 74
 	}
76 75
 
... ...
@@ -101,10 +95,7 @@ func (ls *layerStore) ChecksumForGraphID(id, parent, oldTarDataPath, newTarDataP
101 101
 	}
102 102
 
103 103
 	dgst := digest.Canonical.Digester()
104
-	// Note - we use the host OS here. This is a safe assumption as its during migration, and
105
-	// no host OS which supports migration also supports multiple image OS's. In other words,
106
-	// it's only on Linux, not on Windows.
107
-	err = ls.assembleTarTo(id, runtime.GOOS, uncompressed, &size, dgst.Hash())
104
+	err = ls.assembleTarTo(id, uncompressed, &size, dgst.Hash())
108 105
 	if err != nil {
109 106
 		return
110 107
 	}
... ...
@@ -120,10 +111,7 @@ func (ls *layerStore) ChecksumForGraphID(id, parent, oldTarDataPath, newTarDataP
120 120
 }
121 121
 
122 122
 func (ls *layerStore) checksumForGraphIDNoTarsplit(id, parent, newTarDataPath string) (diffID DiffID, size int64, err error) {
123
-	// Note - we use the host OS here. This is a safe assumption as its during migration, and
124
-	// no host OS which supports migration also supports multiple image OS's. In other words,
125
-	// it's only on Linux, not on Windows.
126
-	rawarchive, err := ls.drivers[runtime.GOOS].Diff(id, parent)
123
+	rawarchive, err := ls.driver.Diff(id, parent)
127 124
 	if err != nil {
128 125
 		return
129 126
 	}
... ...
@@ -94,9 +94,7 @@ func TestLayerMigration(t *testing.T) {
94 94
 	if err != nil {
95 95
 		t.Fatal(err)
96 96
 	}
97
-	graphs := make(map[string]graphdriver.Driver)
98
-	graphs[runtime.GOOS] = graph
99
-	ls, err := NewStoreFromGraphDrivers(fms, graphs)
97
+	ls, err := NewStoreFromGraphDriver(fms, graph, runtime.GOOS)
100 98
 	if err != nil {
101 99
 		t.Fatal(err)
102 100
 	}
... ...
@@ -112,14 +110,14 @@ func TestLayerMigration(t *testing.T) {
112 112
 		t.Fatal(err)
113 113
 	}
114 114
 
115
-	layer1b, err := ls.Register(bytes.NewReader(tar1), "", runtime.GOOS)
115
+	layer1b, err := ls.Register(bytes.NewReader(tar1), "")
116 116
 	if err != nil {
117 117
 		t.Fatal(err)
118 118
 	}
119 119
 
120 120
 	assertReferences(t, layer1a, layer1b)
121 121
 	// Attempt register, should be same
122
-	layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID(), runtime.GOOS)
122
+	layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID())
123 123
 	if err != nil {
124 124
 		t.Fatal(err)
125 125
 	}
... ...
@@ -224,9 +222,7 @@ func TestLayerMigrationNoTarsplit(t *testing.T) {
224 224
 	if err != nil {
225 225
 		t.Fatal(err)
226 226
 	}
227
-	graphs := make(map[string]graphdriver.Driver)
228
-	graphs[runtime.GOOS] = graph
229
-	ls, err := NewStoreFromGraphDrivers(fms, graphs)
227
+	ls, err := NewStoreFromGraphDriver(fms, graph, runtime.GOOS)
230 228
 	if err != nil {
231 229
 		t.Fatal(err)
232 230
 	}
... ...
@@ -242,7 +238,7 @@ func TestLayerMigrationNoTarsplit(t *testing.T) {
242 242
 		t.Fatal(err)
243 243
 	}
244 244
 
245
-	layer1b, err := ls.Register(bytes.NewReader(tar1), "", runtime.GOOS)
245
+	layer1b, err := ls.Register(bytes.NewReader(tar1), "")
246 246
 	if err != nil {
247 247
 		t.Fatal(err)
248 248
 	}
... ...
@@ -250,7 +246,7 @@ func TestLayerMigrationNoTarsplit(t *testing.T) {
250 250
 	assertReferences(t, layer1a, layer1b)
251 251
 
252 252
 	// Attempt register, should be same
253
-	layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID(), runtime.GOOS)
253
+	layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID())
254 254
 	if err != nil {
255 255
 		t.Fatal(err)
256 256
 	}
... ...
@@ -312,7 +308,7 @@ func TestMountMigration(t *testing.T) {
312 312
 		t.Fatal(err)
313 313
 	}
314 314
 
315
-	graph := ls.(*layerStore).drivers[runtime.GOOS]
315
+	graph := ls.(*layerStore).driver
316 316
 
317 317
 	layer1, err := createLayer(ls, "", initWithFiles(baseFiles...))
318 318
 	if err != nil {
... ...
@@ -338,7 +334,7 @@ func TestMountMigration(t *testing.T) {
338 338
 		t.Fatal(err)
339 339
 	}
340 340
 
341
-	if err := ls.(*layerStore).CreateRWLayerByGraphID("migration-mount", containerID, runtime.GOOS, layer1.ChainID()); err != nil {
341
+	if err := ls.(*layerStore).CreateRWLayerByGraphID("migration-mount", containerID, layer1.ChainID()); err != nil {
342 342
 		t.Fatal(err)
343 343
 	}
344 344
 
... ...
@@ -384,7 +380,7 @@ func TestMountMigration(t *testing.T) {
384 384
 		Kind: archive.ChangeAdd,
385 385
 	})
386 386
 
387
-	if _, err := ls.CreateRWLayer("migration-mount", layer1.ChainID(), runtime.GOOS, nil); err == nil {
387
+	if _, err := ls.CreateRWLayer("migration-mount", layer1.ChainID(), nil); err == nil {
388 388
 		t.Fatal("Expected error creating mount with same name")
389 389
 	} else if err != ErrMountNameConflict {
390 390
 		t.Fatal(err)
... ...
@@ -35,7 +35,7 @@ func TestMountInit(t *testing.T) {
35 35
 	rwLayerOpts := &CreateRWLayerOpts{
36 36
 		InitFunc: mountInit,
37 37
 	}
38
-	m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), runtime.GOOS, rwLayerOpts)
38
+	m, err := ls.CreateRWLayer("fun-mount", layer.ChainID(), rwLayerOpts)
39 39
 	if err != nil {
40 40
 		t.Fatal(err)
41 41
 	}
... ...
@@ -95,7 +95,7 @@ func TestMountSize(t *testing.T) {
95 95
 		InitFunc: mountInit,
96 96
 	}
97 97
 
98
-	m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), runtime.GOOS, rwLayerOpts)
98
+	m, err := ls.CreateRWLayer("mount-size", layer.ChainID(), rwLayerOpts)
99 99
 	if err != nil {
100 100
 		t.Fatal(err)
101 101
 	}
... ...
@@ -147,7 +147,7 @@ func TestMountChanges(t *testing.T) {
147 147
 		InitFunc: mountInit,
148 148
 	}
149 149
 
150
-	m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), runtime.GOOS, rwLayerOpts)
150
+	m, err := ls.CreateRWLayer("mount-changes", layer.ChainID(), rwLayerOpts)
151 151
 	if err != nil {
152 152
 		t.Fatal(err)
153 153
 	}
... ...
@@ -2,7 +2,6 @@ package layer
2 2
 
3 3
 import (
4 4
 	"io"
5
-	"runtime"
6 5
 
7 6
 	"github.com/docker/docker/pkg/archive"
8 7
 	"github.com/docker/docker/pkg/containerfs"
... ...
@@ -15,7 +14,6 @@ type mountedLayer struct {
15 15
 	parent     *roLayer
16 16
 	path       string
17 17
 	layerStore *layerStore
18
-	os         string
19 18
 
20 19
 	references map[RWLayer]*referencedRWLayer
21 20
 }
... ...
@@ -31,7 +29,7 @@ func (ml *mountedLayer) cacheParent() string {
31 31
 }
32 32
 
33 33
 func (ml *mountedLayer) TarStream() (io.ReadCloser, error) {
34
-	return ml.layerStore.drivers[ml.OS()].Diff(ml.mountID, ml.cacheParent())
34
+	return ml.layerStore.driver.Diff(ml.mountID, ml.cacheParent())
35 35
 }
36 36
 
37 37
 func (ml *mountedLayer) Name() string {
... ...
@@ -49,23 +47,19 @@ func (ml *mountedLayer) Parent() Layer {
49 49
 }
50 50
 
51 51
 func (ml *mountedLayer) OS() string {
52
-	// For backwards compatibility, return the host OS if not set.
53
-	if ml.os == "" {
54
-		return runtime.GOOS
55
-	}
56
-	return ml.os
52
+	return ml.layerStore.os
57 53
 }
58 54
 
59 55
 func (ml *mountedLayer) Size() (int64, error) {
60
-	return ml.layerStore.drivers[ml.OS()].DiffSize(ml.mountID, ml.cacheParent())
56
+	return ml.layerStore.driver.DiffSize(ml.mountID, ml.cacheParent())
61 57
 }
62 58
 
63 59
 func (ml *mountedLayer) Changes() ([]archive.Change, error) {
64
-	return ml.layerStore.drivers[ml.OS()].Changes(ml.mountID, ml.cacheParent())
60
+	return ml.layerStore.driver.Changes(ml.mountID, ml.cacheParent())
65 61
 }
66 62
 
67 63
 func (ml *mountedLayer) Metadata() (map[string]string, error) {
68
-	return ml.layerStore.drivers[ml.OS()].GetMetadata(ml.mountID)
64
+	return ml.layerStore.driver.GetMetadata(ml.mountID)
69 65
 }
70 66
 
71 67
 func (ml *mountedLayer) getReference() RWLayer {
... ...
@@ -100,11 +94,11 @@ type referencedRWLayer struct {
100 100
 }
101 101
 
102 102
 func (rl *referencedRWLayer) Mount(mountLabel string) (containerfs.ContainerFS, error) {
103
-	return rl.layerStore.drivers[rl.OS()].Get(rl.mountedLayer.mountID, mountLabel)
103
+	return rl.layerStore.driver.Get(rl.mountedLayer.mountID, mountLabel)
104 104
 }
105 105
 
106 106
 // Unmount decrements the activity count and unmounts the underlying layer
107 107
 // Callers should only call `Unmount` once per call to `Mount`, even on error.
108 108
 func (rl *referencedRWLayer) Unmount() error {
109
-	return rl.layerStore.drivers[rl.OS()].Put(rl.mountedLayer.mountID)
109
+	return rl.layerStore.driver.Put(rl.mountedLayer.mountID)
110 110
 }
... ...
@@ -16,7 +16,6 @@ type roLayer struct {
16 16
 	size       int64
17 17
 	layerStore *layerStore
18 18
 	descriptor distribution.Descriptor
19
-	os         string
20 19
 
21 20
 	referenceCount int
22 21
 	references     map[Layer]struct{}
... ...
@@ -52,7 +51,7 @@ func (rl *roLayer) TarStreamFrom(parent ChainID) (io.ReadCloser, error) {
52 52
 	if parent != ChainID("") && parentCacheID == "" {
53 53
 		return nil, fmt.Errorf("layer ID '%s' is not a parent of the specified layer: cannot provide diff to non-parent", parent)
54 54
 	}
55
-	return rl.layerStore.drivers[rl.OS()].Diff(rl.cacheID, parentCacheID)
55
+	return rl.layerStore.driver.Diff(rl.cacheID, parentCacheID)
56 56
 }
57 57
 
58 58
 func (rl *roLayer) ChainID() ChainID {
... ...
@@ -70,6 +69,10 @@ func (rl *roLayer) Parent() Layer {
70 70
 	return rl.parent
71 71
 }
72 72
 
73
+func (rl *roLayer) OS() string {
74
+	return rl.layerStore.os
75
+}
76
+
73 77
 func (rl *roLayer) Size() (size int64, err error) {
74 78
 	if rl.parent != nil {
75 79
 		size, err = rl.parent.Size()
... ...
@@ -86,7 +89,7 @@ func (rl *roLayer) DiffSize() (size int64, err error) {
86 86
 }
87 87
 
88 88
 func (rl *roLayer) Metadata() (map[string]string, error) {
89
-	return rl.layerStore.drivers[rl.OS()].GetMetadata(rl.cacheID)
89
+	return rl.layerStore.driver.GetMetadata(rl.cacheID)
90 90
 }
91 91
 
92 92
 type referencedCacheLayer struct {
... ...
@@ -143,7 +146,11 @@ func storeLayer(tx MetadataTransaction, layer *roLayer) error {
143 143
 			return err
144 144
 		}
145 145
 	}
146
-	return tx.SetOS(layer.os)
146
+	if err := tx.SetOS(layer.layerStore.os); err != nil {
147
+		return err
148
+	}
149
+
150
+	return nil
147 151
 }
148 152
 
149 153
 func newVerifiedReadCloser(rc io.ReadCloser, dgst digest.Digest) (io.ReadCloser, error) {
150 154
deleted file mode 100644
... ...
@@ -1,9 +0,0 @@
1
-// +build !windows
2
-
3
-package layer
4
-
5
-import "runtime"
6
-
7
-func (rl *roLayer) OS() string {
8
-	return runtime.GOOS
9
-}
... ...
@@ -7,10 +7,3 @@ var _ distribution.Describable = &roLayer{}
7 7
 func (rl *roLayer) Descriptor() distribution.Descriptor {
8 8
 	return rl.descriptor
9 9
 }
10
-
11
-func (rl *roLayer) OS() string {
12
-	if rl.os == "" {
13
-		return "windows"
14
-	}
15
-	return rl.os
16
-}
... ...
@@ -87,14 +87,15 @@ func TestMigrateContainers(t *testing.T) {
87 87
 		t.Fatal(err)
88 88
 	}
89 89
 
90
-	ls := &mockMounter{}
91
-
92 90
 	ifs, err := image.NewFSStoreBackend(filepath.Join(tmpdir, "imagedb"))
93 91
 	if err != nil {
94 92
 		t.Fatal(err)
95 93
 	}
96 94
 
97
-	is, err := image.NewImageStore(ifs, ls)
95
+	ls := &mockMounter{}
96
+	mmMap := make(map[string]image.LayerGetReleaser)
97
+	mmMap[runtime.GOOS] = ls
98
+	is, err := image.NewImageStore(ifs, mmMap)
98 99
 	if err != nil {
99 100
 		t.Fatal(err)
100 101
 	}
... ...
@@ -165,14 +166,15 @@ func TestMigrateImages(t *testing.T) {
165 165
 		t.Fatal(err)
166 166
 	}
167 167
 
168
-	ls := &mockRegistrar{}
169
-
170 168
 	ifs, err := image.NewFSStoreBackend(filepath.Join(tmpdir, "imagedb"))
171 169
 	if err != nil {
172 170
 		t.Fatal(err)
173 171
 	}
174 172
 
175
-	is, err := image.NewImageStore(ifs, ls)
173
+	ls := &mockRegistrar{}
174
+	mrMap := make(map[string]image.LayerGetReleaser)
175
+	mrMap[runtime.GOOS] = ls
176
+	is, err := image.NewImageStore(ifs, mrMap)
176 177
 	if err != nil {
177 178
 		t.Fatal(err)
178 179
 	}
... ...
@@ -56,3 +56,14 @@ func ParsePlatform(in string) *specs.Platform {
56 56
 	}
57 57
 	return p
58 58
 }
59
+
60
+// IsOSSupported determines if an operating system is supported by the host
61
+func IsOSSupported(os string) bool {
62
+	if runtime.GOOS == os {
63
+		return true
64
+	}
65
+	if LCOWSupported() && runtime.GOOS == "windows" && os == "linux" {
66
+		return true
67
+	}
68
+	return false
69
+}
... ...
@@ -10,6 +10,7 @@ import (
10 10
 	"os"
11 11
 	"path"
12 12
 	"path/filepath"
13
+	"runtime"
13 14
 	"strings"
14 15
 
15 16
 	"github.com/docker/distribution/manifest/schema2"
... ...
@@ -440,7 +441,8 @@ func (pm *Manager) Push(ctx context.Context, name string, metaHeader http.Header
440 440
 		pm:     pm,
441 441
 		plugin: p,
442 442
 	}
443
-	ls := &pluginLayerProvider{
443
+	lss := make(map[string]distribution.PushLayerProvider)
444
+	lss[runtime.GOOS] = &pluginLayerProvider{
444 445
 		pm:     pm,
445 446
 		plugin: p,
446 447
 	}
... ...
@@ -463,7 +465,7 @@ func (pm *Manager) Push(ctx context.Context, name string, metaHeader http.Header
463 463
 			RequireSchema2:   true,
464 464
 		},
465 465
 		ConfigMediaType: schema2.MediaTypePluginConfig,
466
-		LayerStore:      ls,
466
+		LayerStores:     lss,
467 467
 		UploadManager:   uploadManager,
468 468
 	}
469 469