Browse code

devmapper: Move all "raw" libdevmapper wrappers to devmapper.go

This separates out the DeviceSet logic a bit better from the raw
device mapper operations.

devicemapper: Serialize addess to the devicemapper deviceset

This code is not safe to run in multiple threads at the same time,
and neither is libdevmapper.

DeviceMapper: Move deactivate into UnmountDevice

This way the deactivate is atomic wrt othe device mapper operations
and will not fail with EBUSY if someone else starts a devicemapper
operation inbetween unmount and deactivate.

devmapper: Fix loopback mounting regression

Some changes were added to attach_loop_device which added
a perror() in a place that caused it to override errno so that
a later errno != EBUSY failed. This fixes that and cleans up
the error reporting a bit.

devmapper: Build on old kernels without LOOP_CTL_GET_FREE define

Alexander Larsson authored on 2013/10/07 21:06:24
Showing 5 changed files
... ...
@@ -6,7 +6,7 @@ type DeviceSet interface {
6 6
 	DeactivateDevice(hash string) error
7 7
 	RemoveDevice(hash string) error
8 8
 	MountDevice(hash, path string) error
9
-	UnmountDevice(hash, path string) error
9
+	UnmountDevice(hash, path string, deactivate bool) error
10 10
 	HasDevice(hash string) bool
11 11
 	HasInitializedDevice(hash string) bool
12 12
 	HasActivatedDevice(hash string) bool
... ...
@@ -13,6 +13,7 @@ import (
13 13
 	"strconv"
14 14
 	"strings"
15 15
 	"syscall"
16
+	"sync"
16 17
 )
17 18
 
18 19
 const (
... ...
@@ -36,6 +37,7 @@ type MetaData struct {
36 36
 
37 37
 type DeviceSetDM struct {
38 38
 	MetaData
39
+	sync.Mutex
39 40
 	initialized      bool
40 41
 	root             string
41 42
 	devicePrefix     string
... ...
@@ -77,74 +79,6 @@ func (devices *DeviceSetDM) getPoolDevName() string {
77 77
 	return getDevName(devices.getPoolName())
78 78
 }
79 79
 
80
-func (devices *DeviceSetDM) createTask(t TaskType, name string) (*Task, error) {
81
-	task := TaskCreate(t)
82
-	if task == nil {
83
-		return nil, fmt.Errorf("Can't create task of type %d", int(t))
84
-	}
85
-	if err := task.SetName(name); err != nil {
86
-		return nil, fmt.Errorf("Can't set task name %s", name)
87
-	}
88
-	return task, nil
89
-}
90
-
91
-func (devices *DeviceSetDM) getInfo(name string) (*Info, error) {
92
-	task, err := devices.createTask(DeviceInfo, name)
93
-	if task == nil {
94
-		return nil, err
95
-	}
96
-	if err := task.Run(); err != nil {
97
-		return nil, err
98
-	}
99
-	return task.GetInfo()
100
-}
101
-
102
-func (devices *DeviceSetDM) getStatus(name string) (uint64, uint64, string, string, error) {
103
-	task, err := devices.createTask(DeviceStatus, name)
104
-	if task == nil {
105
-		utils.Debugf("getStatus: Error createTask: %s", err)
106
-		return 0, 0, "", "", err
107
-	}
108
-	if err := task.Run(); err != nil {
109
-		utils.Debugf("getStatus: Error Run: %s", err)
110
-		return 0, 0, "", "", err
111
-	}
112
-
113
-	devinfo, err := task.GetInfo()
114
-	if err != nil {
115
-		utils.Debugf("getStatus: Error GetInfo: %s", err)
116
-		return 0, 0, "", "", err
117
-	}
118
-	if devinfo.Exists == 0 {
119
-		utils.Debugf("getStatus: Non existing device %s", name)
120
-		return 0, 0, "", "", fmt.Errorf("Non existing device %s", name)
121
-	}
122
-
123
-	_, start, length, target_type, params := task.GetNextTarget(0)
124
-	return start, length, target_type, params, nil
125
-}
126
-
127
-func (devices *DeviceSetDM) setTransactionId(oldId uint64, newId uint64) error {
128
-	task, err := devices.createTask(DeviceTargetMsg, devices.getPoolDevName())
129
-	if task == nil {
130
-		utils.Debugf("\n--->Err: %s\n", err)
131
-		return err
132
-	}
133
-
134
-	if err := task.SetSector(0); err != nil {
135
-		return fmt.Errorf("Can't set sector")
136
-	}
137
-
138
-	if err := task.SetMessage(fmt.Sprintf("set_transaction_id %d %d", oldId, newId)); err != nil {
139
-		return fmt.Errorf("Can't set message")
140
-	}
141
-
142
-	if err := task.Run(); err != nil {
143
-		return fmt.Errorf("Error running setTransactionId")
144
-	}
145
-	return nil
146
-}
147
-
148 80
 func (devices *DeviceSetDM) hasImage(name string) bool {
149 81
 	dirname := devices.loopbackDir()
150 82
 	filename := path.Join(dirname, name)
... ...
@@ -178,194 +112,6 @@ func (devices *DeviceSetDM) ensureImage(name string, size int64) (string, error)
178 178
 	return filename, nil
179 179
 }
180 180
 
181
-func (devices *DeviceSetDM) createPool(dataFile *os.File, metadataFile *os.File) error {
182
-	utils.Debugf("Activating device-mapper pool %s", devices.getPoolName())
183
-	task, err := devices.createTask(DeviceCreate, devices.getPoolName())
184
-	if task == nil {
185
-		utils.Debugf("\n--->Err: %s\n", err)
186
-		return err
187
-	}
188
-
189
-	size, err := GetBlockDeviceSize(dataFile)
190
-	if err != nil {
191
-		return fmt.Errorf("Can't get data size")
192
-	}
193
-
194
-	params := metadataFile.Name() + " " + dataFile.Name() + " 512 8192"
195
-	if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
196
-		return fmt.Errorf("Can't add target")
197
-	}
198
-
199
-	var cookie uint32 = 0
200
-	if err := task.SetCookie(&cookie, 0); err != nil {
201
-		return fmt.Errorf("Can't set cookie")
202
-	}
203
-
204
-	if err := task.Run(); err != nil {
205
-		return fmt.Errorf("Error running DeviceCreate")
206
-	}
207
-
208
-	UdevWait(cookie)
209
-
210
-	return nil
211
-}
212
-
213
-func (devices *DeviceSetDM) suspendDevice(info *DevInfo) error {
214
-	task, err := devices.createTask(DeviceSuspend, info.Name())
215
-	if task == nil {
216
-		utils.Debugf("\n--->Err: %s\n", err)
217
-		return err
218
-	}
219
-	if err := task.Run(); err != nil {
220
-		return fmt.Errorf("Error running DeviceSuspend")
221
-	}
222
-	return nil
223
-}
224
-
225
-func (devices *DeviceSetDM) resumeDevice(info *DevInfo) error {
226
-	task, err := devices.createTask(DeviceResume, info.Name())
227
-	if task == nil {
228
-		utils.Debugf("\n--->Err: %s\n", err)
229
-		return err
230
-	}
231
-
232
-	var cookie uint32 = 0
233
-	if err := task.SetCookie(&cookie, 0); err != nil {
234
-		return fmt.Errorf("Can't set cookie")
235
-	}
236
-
237
-	if err := task.Run(); err != nil {
238
-		return fmt.Errorf("Error running DeviceSuspend")
239
-	}
240
-
241
-	UdevWait(cookie)
242
-
243
-	return nil
244
-}
245
-
246
-func (devices *DeviceSetDM) createDevice(deviceId int) error {
247
-	task, err := devices.createTask(DeviceTargetMsg, devices.getPoolDevName())
248
-	if task == nil {
249
-		utils.Debugf("\n--->Err: %s\n", err)
250
-		return err
251
-	}
252
-
253
-	if err := task.SetSector(0); err != nil {
254
-		return fmt.Errorf("Can't set sector")
255
-	}
256
-
257
-	if err := task.SetMessage(fmt.Sprintf("create_thin %d", deviceId)); err != nil {
258
-		return fmt.Errorf("Can't set message")
259
-	}
260
-
261
-	if err := task.Run(); err != nil {
262
-		return fmt.Errorf("Error running createDevice")
263
-	}
264
-	return nil
265
-}
266
-
267
-func (devices *DeviceSetDM) createSnapDevice(deviceId int, baseInfo *DevInfo) error {
268
-	devinfo, _ := devices.getInfo(baseInfo.Name())
269
-	doSuspend := devinfo != nil && devinfo.Exists != 0
270
-
271
-	if doSuspend {
272
-		if err := devices.suspendDevice(baseInfo); err != nil {
273
-			utils.Debugf("\n--->Err: %s\n", err)
274
-			return err
275
-		}
276
-	}
277
-
278
-	task, err := devices.createTask(DeviceTargetMsg, devices.getPoolDevName())
279
-	if task == nil {
280
-		devices.resumeDevice(baseInfo)
281
-		utils.Debugf("\n--->Err: %s\n", err)
282
-		return err
283
-	}
284
-
285
-	if err := task.SetSector(0); err != nil {
286
-		devices.resumeDevice(baseInfo)
287
-		return fmt.Errorf("Can't set sector")
288
-	}
289
-
290
-	if err := task.SetMessage(fmt.Sprintf("create_snap %d %d", deviceId, baseInfo.DeviceId)); err != nil {
291
-		devices.resumeDevice(baseInfo)
292
-		return fmt.Errorf("Can't set message")
293
-	}
294
-
295
-	if err := task.Run(); err != nil {
296
-		devices.resumeDevice(baseInfo)
297
-		return fmt.Errorf("Error running DeviceCreate")
298
-	}
299
-
300
-	if doSuspend {
301
-		if err := devices.resumeDevice(baseInfo); err != nil {
302
-			utils.Debugf("\n--->Err: %s\n", err)
303
-			return err
304
-		}
305
-	}
306
-
307
-	return nil
308
-}
309
-
310
-func (devices *DeviceSetDM) deleteDevice(deviceId int) error {
311
-	task, err := devices.createTask(DeviceTargetMsg, devices.getPoolDevName())
312
-	if task == nil {
313
-		utils.Debugf("\n--->Err: %s\n", err)
314
-		return err
315
-	}
316
-
317
-	if err := task.SetSector(0); err != nil {
318
-		return fmt.Errorf("Can't set sector")
319
-	}
320
-
321
-	if err := task.SetMessage(fmt.Sprintf("delete %d", deviceId)); err != nil {
322
-		return fmt.Errorf("Can't set message")
323
-	}
324
-
325
-	if err := task.Run(); err != nil {
326
-		return fmt.Errorf("Error running deleteDevice")
327
-	}
328
-	return nil
329
-}
330
-
331
-func (devices *DeviceSetDM) removeDevice(name string) error {
332
-	task, err := devices.createTask(DeviceRemove, name)
333
-	if task == nil {
334
-		utils.Debugf("\n--->Err: %s\n", err)
335
-		return err
336
-	}
337
-	if err = task.Run(); err != nil {
338
-		return fmt.Errorf("Error running removeDevice")
339
-	}
340
-	return nil
341
-}
342
-
343
-func (devices *DeviceSetDM) activateDevice(info *DevInfo) error {
344
-	task, err := devices.createTask(DeviceCreate, info.Name())
345
-	if task == nil {
346
-		utils.Debugf("\n--->Err: %s\n", err)
347
-		return err
348
-	}
349
-
350
-	params := fmt.Sprintf("%s %d", devices.getPoolDevName(), info.DeviceId)
351
-	if err := task.AddTarget(0, info.Size/512, "thin", params); err != nil {
352
-		return fmt.Errorf("Can't add target")
353
-	}
354
-
355
-	var cookie uint32 = 0
356
-	if err := task.SetCookie(&cookie, 0); err != nil {
357
-		return fmt.Errorf("Can't set cookie")
358
-	}
359
-
360
-	if err := task.Run(); err != nil {
361
-		return fmt.Errorf("Error running DeviceCreate")
362
-	}
363
-
364
-	UdevWait(cookie)
365
-
366
-	return nil
367
-}
368
-
369 181
 func (devices *DeviceSetDM) allocateDeviceId() int {
370 182
 	// TODO: Add smarter reuse of deleted devices
371 183
 	id := devices.nextFreeDevice
... ...
@@ -412,7 +158,7 @@ func (devices *DeviceSetDM) saveMetadata() error {
412 412
 	}
413 413
 
414 414
 	if devices.NewTransactionId != devices.TransactionId {
415
-		if err = devices.setTransactionId(devices.TransactionId, devices.NewTransactionId); err != nil {
415
+		if err = setTransactionId(devices.getPoolDevName(), devices.TransactionId, devices.NewTransactionId); err != nil {
416 416
 			utils.Debugf("\n--->Err: %s\n", err)
417 417
 			return err
418 418
 		}
... ...
@@ -448,11 +194,11 @@ func (devices *DeviceSetDM) activateDeviceIfNeeded(hash string) error {
448 448
 		return fmt.Errorf("Unknown device %s", hash)
449 449
 	}
450 450
 
451
-	if devinfo, _ := devices.getInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 {
451
+	if devinfo, _ := getInfo(info.Name()); devinfo != nil && devinfo.Exists != 0 {
452 452
 		return nil
453 453
 	}
454 454
 
455
-	return devices.activateDevice(info)
455
+	return activateDevice(devices.getPoolDevName(), info.Name(), info.DeviceId, info.Size)
456 456
 }
457 457
 
458 458
 func (devices *DeviceSetDM) createFilesystem(info *DevInfo) error {
... ...
@@ -470,7 +216,7 @@ func (devices *DeviceSetDM) createFilesystem(info *DevInfo) error {
470 470
 }
471 471
 
472 472
 func (devices *DeviceSetDM) loadMetaData() error {
473
-	_, _, _, params, err := devices.getStatus(devices.getPoolName())
473
+	_, _, _, params, err := getStatus(devices.getPoolName())
474 474
 	if err != nil {
475 475
 		utils.Debugf("\n--->Err: %s\n", err)
476 476
 		return err
... ...
@@ -521,7 +267,7 @@ func (devices *DeviceSetDM) setupBaseImage() error {
521 521
 
522 522
 	if oldInfo != nil && !oldInfo.Initialized {
523 523
 		utils.Debugf("Removing uninitialized base image")
524
-		if err := devices.RemoveDevice(""); err != nil {
524
+		if err := devices.removeDevice(""); err != nil {
525 525
 			utils.Debugf("\n--->Err: %s\n", err)
526 526
 			return err
527 527
 		}
... ...
@@ -532,14 +278,14 @@ func (devices *DeviceSetDM) setupBaseImage() error {
532 532
 	id := devices.allocateDeviceId()
533 533
 
534 534
 	// Create initial device
535
-	if err := devices.createDevice(id); err != nil {
535
+	if err := createDevice(devices.getPoolDevName(), id); err != nil {
536 536
 		utils.Debugf("\n--->Err: %s\n", err)
537 537
 		return err
538 538
 	}
539 539
 
540 540
 	info, err := devices.registerDevice(id, "", defaultBaseFsSize)
541 541
 	if err != nil {
542
-		_ = devices.deleteDevice(id)
542
+		_ = deleteDevice(devices.getPoolDevName(), id)
543 543
 		utils.Debugf("\n--->Err: %s\n", err)
544 544
 		return err
545 545
 	}
... ...
@@ -582,7 +328,7 @@ func setCloseOnExec(name string) {
582 582
 }
583 583
 
584 584
 func (devices *DeviceSetDM) initDevmapper() error {
585
-	info, err := devices.getInfo(devices.getPoolName())
585
+	info, err := getInfo(devices.getPoolName())
586 586
 	if info == nil {
587 587
 		utils.Debugf("Error device getInfo: %s", err)
588 588
 		return err
... ...
@@ -636,7 +382,7 @@ func (devices *DeviceSetDM) initDevmapper() error {
636 636
 	}
637 637
 	defer metadataFile.Close()
638 638
 
639
-	if err := devices.createPool(dataFile, metadataFile); err != nil {
639
+	if err := createPool(devices.getPoolName(), dataFile, metadataFile); err != nil {
640 640
 		utils.Debugf("\n--->Err: %s\n", err)
641 641
 		return err
642 642
 	}
... ...
@@ -657,6 +403,9 @@ func (devices *DeviceSetDM) initDevmapper() error {
657 657
 }
658 658
 
659 659
 func (devices *DeviceSetDM) AddDevice(hash, baseHash string) error {
660
+	devices.Lock()
661
+	defer devices.Unlock()
662
+
660 663
 	if err := devices.ensureInit(); err != nil {
661 664
 		utils.Debugf("Error init: %s\n", err)
662 665
 		return err
... ...
@@ -674,33 +423,28 @@ func (devices *DeviceSetDM) AddDevice(hash, baseHash string) error {
674 674
 
675 675
 	deviceId := devices.allocateDeviceId()
676 676
 
677
-	if err := devices.createSnapDevice(deviceId, baseInfo); err != nil {
677
+	if err := devices.createSnapDevice(devices.getPoolDevName(), deviceId, baseInfo.Name(), baseInfo.DeviceId); err != nil {
678 678
 		utils.Debugf("Error creating snap device: %s\n", err)
679 679
 		return err
680 680
 	}
681 681
 
682 682
 	if _, err := devices.registerDevice(deviceId, hash, baseInfo.Size); err != nil {
683
-		devices.deleteDevice(deviceId)
683
+		deleteDevice(devices.getPoolDevName(), deviceId)
684 684
 		utils.Debugf("Error registering device: %s\n", err)
685 685
 		return err
686 686
 	}
687 687
 	return nil
688 688
 }
689 689
 
690
-func (devices *DeviceSetDM) RemoveDevice(hash string) error {
691
-	if err := devices.ensureInit(); err != nil {
692
-		utils.Debugf("\n--->Err: %s\n", err)
693
-		return err
694
-	}
695
-
690
+func (devices *DeviceSetDM) removeDevice(hash string) error {
696 691
 	info := devices.Devices[hash]
697 692
 	if info == nil {
698 693
 		return fmt.Errorf("hash %s doesn't exists", hash)
699 694
 	}
700 695
 
701
-	devinfo, _ := devices.getInfo(info.Name())
696
+	devinfo, _ := getInfo(info.Name())
702 697
 	if devinfo != nil && devinfo.Exists != 0 {
703
-		if err := devices.removeDevice(info.Name()); err != nil {
698
+		if err := removeDevice(info.Name()); err != nil {
704 699
 			utils.Debugf("Error removing device: %s\n", err)
705 700
 			return err
706 701
 		}
... ...
@@ -714,7 +458,7 @@ func (devices *DeviceSetDM) RemoveDevice(hash string) error {
714 714
 		}
715 715
 	}
716 716
 
717
-	if err := devices.deleteDevice(info.DeviceId); err != nil {
717
+	if err := deleteDevice(devices.getPoolDevName(), info.DeviceId); err != nil {
718 718
 		utils.Debugf("Error deleting device: %s\n", err)
719 719
 		return err
720 720
 	}
... ...
@@ -731,24 +475,32 @@ func (devices *DeviceSetDM) RemoveDevice(hash string) error {
731 731
 	return nil
732 732
 }
733 733
 
734
-func (devices *DeviceSetDM) DeactivateDevice(hash string) error {
734
+func (devices *DeviceSetDM) RemoveDevice(hash string) error {
735
+	devices.Lock()
736
+	defer devices.Unlock()
737
+
735 738
 	if err := devices.ensureInit(); err != nil {
736 739
 		utils.Debugf("\n--->Err: %s\n", err)
737 740
 		return err
738 741
 	}
739 742
 
743
+
744
+	return devices.removeDevice(hash)
745
+}
746
+
747
+func (devices *DeviceSetDM) deactivateDevice(hash string) error {
740 748
 	info := devices.Devices[hash]
741 749
 	if info == nil {
742 750
 		return fmt.Errorf("hash %s doesn't exists", hash)
743 751
 	}
744 752
 
745
-	devinfo, err := devices.getInfo(info.Name())
753
+	devinfo, err := getInfo(info.Name())
746 754
 	if err != nil {
747 755
 		utils.Debugf("\n--->Err: %s\n", err)
748 756
 		return err
749 757
 	}
750 758
 	if devinfo.Exists != 0 {
751
-		if err := devices.removeDevice(info.Name()); err != nil {
759
+		if err := removeDevice(info.Name()); err != nil {
752 760
 			utils.Debugf("\n--->Err: %s\n", err)
753 761
 			return err
754 762
 		}
... ...
@@ -757,7 +509,24 @@ func (devices *DeviceSetDM) DeactivateDevice(hash string) error {
757 757
 	return nil
758 758
 }
759 759
 
760
+func (devices *DeviceSetDM) DeactivateDevice(hash string) error {
761
+	devices.Lock()
762
+	defer devices.Unlock()
763
+
764
+	if err := devices.ensureInit(); err != nil {
765
+		utils.Debugf("\n--->Err: %s\n", err)
766
+		return err
767
+	}
768
+
769
+	utils.Debugf("DeactivateDevice %s", hash)
770
+	return devices.deactivateDevice(hash);
771
+}
772
+
773
+
760 774
 func (devices *DeviceSetDM) Shutdown() error {
775
+	devices.Lock()
776
+	defer devices.Unlock()
777
+
761 778
 	if !devices.initialized {
762 779
 		return nil
763 780
 	}
... ...
@@ -772,14 +541,14 @@ func (devices *DeviceSetDM) Shutdown() error {
772 772
 	}
773 773
 
774 774
 	for _, d := range devices.Devices {
775
-		if err := devices.DeactivateDevice(d.Hash); err != nil {
775
+		if err := devices.deactivateDevice(d.Hash); err != nil {
776 776
 			utils.Debugf("Shutdown deactivate %s , error: %s\n", d.Hash, err)
777 777
 		}
778 778
 	}
779 779
 
780 780
 	pool := devices.getPoolDevName()
781
-	if devinfo, err := devices.getInfo(pool); err == nil && devinfo.Exists != 0 {
782
-		if err := devices.removeDevice(pool); err != nil {
781
+	if devinfo, err := getInfo(pool); err == nil && devinfo.Exists != 0 {
782
+		if err := removeDevice(pool); err != nil {
783 783
 			utils.Debugf("Shutdown deactivate %s , error: %s\n", pool, err)
784 784
 		}
785 785
 	}
... ...
@@ -788,6 +557,9 @@ func (devices *DeviceSetDM) Shutdown() error {
788 788
 }
789 789
 
790 790
 func (devices *DeviceSetDM) MountDevice(hash, path string) error {
791
+	devices.Lock()
792
+	defer devices.Unlock()
793
+
791 794
 	if err := devices.ensureInit(); err != nil {
792 795
 		utils.Debugf("\n--->Err: %s\n", err)
793 796
 		return err
... ...
@@ -815,7 +587,10 @@ func (devices *DeviceSetDM) MountDevice(hash, path string) error {
815 815
 	return nil
816 816
 }
817 817
 
818
-func (devices *DeviceSetDM) UnmountDevice(hash, path string) error {
818
+func (devices *DeviceSetDM) UnmountDevice(hash, path string, deactivate bool) error {
819
+	devices.Lock()
820
+	defer devices.Unlock()
821
+
819 822
 	if err := syscall.Unmount(path, 0); err != nil {
820 823
 		utils.Debugf("\n--->Err: %s\n", err)
821 824
 		return err
... ...
@@ -827,10 +602,17 @@ func (devices *DeviceSetDM) UnmountDevice(hash, path string) error {
827 827
 		delete(devices.activeMounts, path)
828 828
 	}
829 829
 
830
+	if deactivate {
831
+		devices.deactivateDevice(hash)
832
+	}
833
+
830 834
 	return nil
831 835
 }
832 836
 
833 837
 func (devices *DeviceSetDM) HasDevice(hash string) bool {
838
+	devices.Lock()
839
+	defer devices.Unlock()
840
+
834 841
 	if err := devices.ensureInit(); err != nil {
835 842
 		return false
836 843
 	}
... ...
@@ -838,6 +620,9 @@ func (devices *DeviceSetDM) HasDevice(hash string) bool {
838 838
 }
839 839
 
840 840
 func (devices *DeviceSetDM) HasInitializedDevice(hash string) bool {
841
+	devices.Lock()
842
+	defer devices.Unlock()
843
+
841 844
 	if err := devices.ensureInit(); err != nil {
842 845
 		return false
843 846
 	}
... ...
@@ -847,6 +632,9 @@ func (devices *DeviceSetDM) HasInitializedDevice(hash string) bool {
847 847
 }
848 848
 
849 849
 func (devices *DeviceSetDM) HasActivatedDevice(hash string) bool {
850
+	devices.Lock()
851
+	defer devices.Unlock()
852
+
850 853
 	if err := devices.ensureInit(); err != nil {
851 854
 		return false
852 855
 	}
... ...
@@ -855,11 +643,14 @@ func (devices *DeviceSetDM) HasActivatedDevice(hash string) bool {
855 855
 	if info == nil {
856 856
 		return false
857 857
 	}
858
-	devinfo, _ := devices.getInfo(info.Name())
858
+	devinfo, _ := getInfo(info.Name())
859 859
 	return devinfo != nil && devinfo.Exists != 0
860 860
 }
861 861
 
862 862
 func (devices *DeviceSetDM) SetInitialized(hash string) error {
863
+	devices.Lock()
864
+	defer devices.Unlock()
865
+
863 866
 	if err := devices.ensureInit(); err != nil {
864 867
 		utils.Debugf("\n--->Err: %s\n", err)
865 868
 		return err
... ...
@@ -14,6 +14,10 @@ package devmapper
14 14
 #include <linux/fs.h>
15 15
 #include <errno.h>
16 16
 
17
+#ifndef LOOP_CTL_GET_FREE
18
+#define LOOP_CTL_GET_FREE       0x4C82
19
+#endif
20
+
17 21
 char*			attach_loop_device(const char *filename, int *loop_fd_out)
18 22
 {
19 23
   struct loop_info64	loopinfo = {0};
... ...
@@ -56,19 +60,18 @@ char*			attach_loop_device(const char *filename, int *loop_fd_out)
56 56
     loop_fd = open(buf, O_RDWR);
57 57
     if (loop_fd < 0 && errno == ENOENT) {
58 58
       close(fd);
59
-      perror("open");
60 59
       fprintf (stderr, "no available loopback device!");
61 60
       return NULL;
62 61
     } else if (loop_fd < 0)
63 62
       continue;
64 63
 
65 64
     if (ioctl (loop_fd, LOOP_SET_FD, (void *)(size_t)fd) < 0) {
66
-      perror("ioctl");
65
+      int errsv = errno;
67 66
       close(loop_fd);
68 67
       loop_fd = -1;
69
-      if (errno != EBUSY) {
68
+      if (errsv != EBUSY) {
70 69
         close (fd);
71
-        fprintf (stderr, "cannot set up loopback device %s", buf);
70
+        fprintf (stderr, "cannot set up loopback device %s: %s", buf, strerror(errsv));
72 71
         return NULL;
73 72
       }
74 73
       continue;
... ...
@@ -388,3 +391,255 @@ func RemoveDevice(name string) error {
388 388
 func free(p *C.char) {
389 389
 	C.free(unsafe.Pointer(p))
390 390
 }
391
+
392
+func createPool(poolName string, dataFile *os.File, metadataFile *os.File) error {
393
+	task, err := createTask(DeviceCreate, poolName)
394
+	if task == nil {
395
+		return err
396
+	}
397
+
398
+	size, err := GetBlockDeviceSize(dataFile)
399
+	if err != nil {
400
+		return fmt.Errorf("Can't get data size")
401
+	}
402
+
403
+	params := metadataFile.Name() + " " + dataFile.Name() + " 512 8192"
404
+	if err := task.AddTarget(0, size/512, "thin-pool", params); err != nil {
405
+		return fmt.Errorf("Can't add target")
406
+	}
407
+
408
+	var cookie uint32 = 0
409
+	if err := task.SetCookie(&cookie, 0); err != nil {
410
+		return fmt.Errorf("Can't set cookie")
411
+	}
412
+
413
+	if err := task.Run(); err != nil {
414
+		return fmt.Errorf("Error running DeviceCreate")
415
+	}
416
+
417
+	UdevWait(cookie)
418
+
419
+	return nil
420
+}
421
+
422
+func createTask(t TaskType, name string) (*Task, error) {
423
+	task := TaskCreate(t)
424
+	if task == nil {
425
+		return nil, fmt.Errorf("Can't create task of type %d", int(t))
426
+	}
427
+	if err := task.SetName(name); err != nil {
428
+		return nil, fmt.Errorf("Can't set task name %s", name)
429
+	}
430
+	return task, nil
431
+}
432
+
433
+func getInfo(name string) (*Info, error) {
434
+	task, err := createTask(DeviceInfo, name)
435
+	if task == nil {
436
+		return nil, err
437
+	}
438
+	if err := task.Run(); err != nil {
439
+		return nil, err
440
+	}
441
+	return task.GetInfo()
442
+}
443
+
444
+func getStatus(name string) (uint64, uint64, string, string, error) {
445
+	task, err := createTask(DeviceStatus, name)
446
+	if task == nil {
447
+		utils.Debugf("getStatus: Error createTask: %s", err)
448
+		return 0, 0, "", "", err
449
+	}
450
+	if err := task.Run(); err != nil {
451
+		utils.Debugf("getStatus: Error Run: %s", err)
452
+		return 0, 0, "", "", err
453
+	}
454
+
455
+	devinfo, err := task.GetInfo()
456
+	if err != nil {
457
+		utils.Debugf("getStatus: Error GetInfo: %s", err)
458
+		return 0, 0, "", "", err
459
+	}
460
+	if devinfo.Exists == 0 {
461
+		utils.Debugf("getStatus: Non existing device %s", name)
462
+		return 0, 0, "", "", fmt.Errorf("Non existing device %s", name)
463
+	}
464
+
465
+	_, start, length, target_type, params := task.GetNextTarget(0)
466
+	return start, length, target_type, params, nil
467
+}
468
+
469
+func setTransactionId(poolName string, oldId uint64, newId uint64) error {
470
+	task, err := createTask(DeviceTargetMsg, poolName)
471
+	if task == nil {
472
+		return err
473
+	}
474
+
475
+	if err := task.SetSector(0); err != nil {
476
+		return fmt.Errorf("Can't set sector")
477
+	}
478
+
479
+	if err := task.SetMessage(fmt.Sprintf("set_transaction_id %d %d", oldId, newId)); err != nil {
480
+		return fmt.Errorf("Can't set message")
481
+	}
482
+
483
+	if err := task.Run(); err != nil {
484
+		return fmt.Errorf("Error running setTransactionId")
485
+	}
486
+	return nil
487
+}
488
+
489
+func suspendDevice(name string) error {
490
+	task, err := createTask(DeviceSuspend, name)
491
+	if task == nil {
492
+		return err
493
+	}
494
+	if err := task.Run(); err != nil {
495
+		return fmt.Errorf("Error running DeviceSuspend")
496
+	}
497
+	return nil
498
+}
499
+
500
+func resumeDevice(name string) error {
501
+	task, err := createTask(DeviceResume, name)
502
+	if task == nil {
503
+		return err
504
+	}
505
+
506
+	var cookie uint32 = 0
507
+	if err := task.SetCookie(&cookie, 0); err != nil {
508
+		return fmt.Errorf("Can't set cookie")
509
+	}
510
+
511
+	if err := task.Run(); err != nil {
512
+		return fmt.Errorf("Error running DeviceSuspend")
513
+	}
514
+
515
+	UdevWait(cookie)
516
+
517
+	return nil
518
+}
519
+
520
+func createDevice(poolName string, deviceId int) error {
521
+	task, err := createTask(DeviceTargetMsg, poolName)
522
+	if task == nil {
523
+		return err
524
+	}
525
+
526
+	if err := task.SetSector(0); err != nil {
527
+		return fmt.Errorf("Can't set sector")
528
+	}
529
+
530
+	if err := task.SetMessage(fmt.Sprintf("create_thin %d", deviceId)); err != nil {
531
+		return fmt.Errorf("Can't set message")
532
+	}
533
+
534
+	if err := task.Run(); err != nil {
535
+		return fmt.Errorf("Error running createDevice")
536
+	}
537
+	return nil
538
+}
539
+
540
+func deleteDevice(poolName string, deviceId int) error {
541
+	task, err := createTask(DeviceTargetMsg, poolName)
542
+	if task == nil {
543
+		return err
544
+	}
545
+
546
+	if err := task.SetSector(0); err != nil {
547
+		return fmt.Errorf("Can't set sector")
548
+	}
549
+
550
+	if err := task.SetMessage(fmt.Sprintf("delete %d", deviceId)); err != nil {
551
+		return fmt.Errorf("Can't set message")
552
+	}
553
+
554
+	if err := task.Run(); err != nil {
555
+		return fmt.Errorf("Error running deleteDevice")
556
+	}
557
+	return nil
558
+}
559
+
560
+func removeDevice(name string) error {
561
+	task, err := createTask(DeviceRemove, name)
562
+	if task == nil {
563
+		return err
564
+	}
565
+	if err = task.Run(); err != nil {
566
+		return fmt.Errorf("Error running removeDevice")
567
+	}
568
+	return nil
569
+}
570
+
571
+func activateDevice(poolName string, name string, deviceId int, size uint64) error {
572
+	task, err := createTask(DeviceCreate, name)
573
+	if task == nil {
574
+		return err
575
+	}
576
+
577
+	params := fmt.Sprintf("%s %d", poolName, deviceId)
578
+	if err := task.AddTarget(0, size/512, "thin", params); err != nil {
579
+		return fmt.Errorf("Can't add target")
580
+	}
581
+
582
+	var cookie uint32 = 0
583
+	if err := task.SetCookie(&cookie, 0); err != nil {
584
+		return fmt.Errorf("Can't set cookie")
585
+	}
586
+
587
+	if err := task.Run(); err != nil {
588
+		return fmt.Errorf("Error running DeviceCreate")
589
+	}
590
+
591
+	UdevWait(cookie)
592
+
593
+	return nil
594
+}
595
+
596
+func (devices *DeviceSetDM) createSnapDevice(poolName string, deviceId int, baseName string, baseDeviceId int) error {
597
+	devinfo, _ := getInfo(baseName)
598
+	doSuspend := devinfo != nil && devinfo.Exists != 0
599
+
600
+	if doSuspend {
601
+		if err := suspendDevice(baseName); err != nil {
602
+			return err
603
+		}
604
+	}
605
+
606
+	task, err := createTask(DeviceTargetMsg, poolName)
607
+	if task == nil {
608
+		if doSuspend {
609
+			resumeDevice(baseName)
610
+		}
611
+		return err
612
+	}
613
+
614
+	if err := task.SetSector(0); err != nil {
615
+		if doSuspend {
616
+			resumeDevice(baseName)
617
+		}
618
+		return fmt.Errorf("Can't set sector")
619
+	}
620
+
621
+	if err := task.SetMessage(fmt.Sprintf("create_snap %d %d", deviceId, baseDeviceId)); err != nil {
622
+		if doSuspend {
623
+			resumeDevice(baseName)
624
+		}
625
+		return fmt.Errorf("Can't set message")
626
+	}
627
+
628
+	if err := task.Run(); err != nil {
629
+		if doSuspend {
630
+			resumeDevice(baseName)
631
+		}
632
+		return fmt.Errorf("Error running DeviceCreate")
633
+	}
634
+
635
+	if doSuspend {
636
+		if err := resumeDevice(baseName); err != nil {
637
+			return err
638
+		}
639
+	}
640
+
641
+	return nil
642
+}
... ...
@@ -391,14 +391,14 @@ func (image *Image) ensureImageDevice(devices DeviceSet) error {
391 391
 
392 392
 	if err := ioutil.WriteFile(path.Join(mountDir, ".docker-id"), []byte(image.ID), 0600); err != nil {
393 393
 		utils.Debugf("Error writing file: %s", err)
394
-		devices.UnmountDevice(image.ID, mountDir)
394
+		devices.UnmountDevice(image.ID, mountDir, true)
395 395
 		devices.RemoveDevice(image.ID)
396 396
 		return err
397 397
 	}
398 398
 
399 399
 	if err = image.applyLayer(layerPath(root), mountDir); err != nil {
400 400
 		utils.Debugf("Error applying layer: %s", err)
401
-		devices.UnmountDevice(image.ID, mountDir)
401
+		devices.UnmountDevice(image.ID, mountDir, true)
402 402
 		devices.RemoveDevice(image.ID)
403 403
 		return err
404 404
 	}
... ...
@@ -411,28 +411,24 @@ func (image *Image) ensureImageDevice(devices DeviceSet) error {
411 411
 	// part of the container changes
412 412
 	dockerinitLayer, err := image.getDockerInitLayer()
413 413
 	if err != nil {
414
-		devices.UnmountDevice(image.ID, mountDir)
414
+		devices.UnmountDevice(image.ID, mountDir, true)
415 415
 		devices.RemoveDevice(image.ID)
416 416
 		return err
417 417
 	}
418 418
 
419 419
 	if err := image.applyLayer(dockerinitLayer, mountDir); err != nil {
420
-		devices.UnmountDevice(image.ID, mountDir)
420
+		devices.UnmountDevice(image.ID, mountDir, true)
421 421
 		devices.RemoveDevice(image.ID)
422 422
 		return err
423 423
 	}
424 424
 
425
-	if err := devices.UnmountDevice(image.ID, mountDir); err != nil {
425
+	if err := devices.UnmountDevice(image.ID, mountDir, true); err != nil {
426 426
 		devices.RemoveDevice(image.ID)
427 427
 		return err
428 428
 	}
429 429
 
430 430
 	devices.SetInitialized(image.ID)
431 431
 
432
-	// No need to the device-mapper device to hang around once we've written
433
-	// the image, it can be enabled on-demand when needed
434
-	devices.DeactivateDevice(image.ID)
435
-
436 432
 	return nil
437 433
 }
438 434
 
... ...
@@ -491,11 +487,11 @@ func (image *Image) Unmount(runtime *Runtime, root string, id string) error {
491 491
 		return err
492 492
 	}
493 493
 
494
-	if err = devices.UnmountDevice(id, root); err != nil {
494
+	if err = devices.UnmountDevice(id, root, true); err != nil {
495 495
 		return err
496 496
 	}
497 497
 
498
-	return devices.DeactivateDevice(id)
498
+	return nil
499 499
 }
500 500
 
501 501
 func (image *Image) Changes(runtime *Runtime, root, rw, id string) ([]Change, error) {
... ...
@@ -518,10 +514,7 @@ func (image *Image) Changes(runtime *Runtime, root, rw, id string) ([]Change, er
518 518
 	}
519 519
 
520 520
 	changes, err := ChangesDirs(root, rw)
521
-	devices.UnmountDevice(image.ID, rw)
522
-	if !wasActivated {
523
-		devices.DeactivateDevice(image.ID)
524
-	}
521
+	devices.UnmountDevice(image.ID, rw, !wasActivated)
525 522
 	if err != nil {
526 523
 		return nil, err
527 524
 	}
... ...
@@ -356,8 +356,8 @@ func (wrapper *DeviceSetWrapper) MountDevice(hash, path string) error {
356 356
 	return wrapper.wrapped.MountDevice(wrapper.wrap(hash), path)
357 357
 }
358 358
 
359
-func (wrapper *DeviceSetWrapper) UnmountDevice(hash, path string) error {
360
-	return wrapper.wrapped.UnmountDevice(wrapper.wrap(hash), path)
359
+func (wrapper *DeviceSetWrapper) UnmountDevice(hash, path string, deactivate bool) error {
360
+	return wrapper.wrapped.UnmountDevice(wrapper.wrap(hash), path, deactivate)
361 361
 }
362 362
 
363 363
 func (wrapper *DeviceSetWrapper) HasDevice(hash string) bool {