@@ -35,7 +35,8 @@ const (
35
35
)
36
36
37
37
type LinuxDeviceManager struct {
38
- volumeMounter * snapshot.VolumeMounter
38
+ volumeMounter snapshot.VolumeMounter
39
+ cmdRunner * snapshot.LocalCommandRunner
39
40
opts map [string ]string
40
41
}
41
42
@@ -46,6 +47,7 @@ func NewLinuxDeviceManager(shell []string, opts map[string]string) (*LinuxDevice
46
47
47
48
return & LinuxDeviceManager {
48
49
volumeMounter : snapshot .NewVolumeMounter (shell ),
50
+ cmdRunner : & snapshot.LocalCommandRunner {Shell : shell },
49
51
opts : opts ,
50
52
}, nil
51
53
}
@@ -161,7 +163,7 @@ func (d *LinuxDeviceManager) hintFSTypes(partitions []*snapshot.PartitionInfo) (
161
163
}
162
164
163
165
func (d * LinuxDeviceManager ) attemptFindFstab (dir string ) ([]resources.FstabEntry , error ) {
164
- cmd , err := d .volumeMounter . CmdRunner .RunCommand (fmt .Sprintf ("find %s -type f -wholename '*/etc/fstab'" , dir ))
166
+ cmd , err := d .cmdRunner .RunCommand (fmt .Sprintf ("find %s -type f -wholename '*/etc/fstab'" , dir ))
165
167
if err != nil {
166
168
log .Error ().Err (err ).Msg ("error searching for fstab" )
167
169
return nil , nil
@@ -281,46 +283,75 @@ func (d *LinuxDeviceManager) mountWithFstab(partitions []*snapshot.PartitionInfo
281
283
return pathDepth (entries [i ].Mountpoint ) < pathDepth (entries [j ].Mountpoint )
282
284
})
283
285
286
+ rootScanDir := ""
284
287
for _ , entry := range entries {
285
288
for i := range partitions {
286
- if ! cmpPartition2Fstab (partitions [i ], entry ) {
289
+ partition := partitions [i ]
290
+ mustAppend := false
291
+ if ! cmpPartition2Fstab (partition , entry ) {
287
292
continue
288
293
}
289
294
290
- if partitions [i ].MountPoint == "" {
291
- partitions [i ].MountOptions = entry .Options
292
- log .Debug ().Str ("device" , partitions [i ].Name ).
293
- Strs ("options" , partitions [i ].MountOptions ).
294
- Msg ("mounting partition" )
295
- mnt , err := d .Mount (partitions [i ])
296
- if err != nil {
297
- log .Error ().Err (err ).Str ("device" , partitions [i ].Name ).Msg ("unable to mount partition" )
298
- return partitions , err
295
+ log .Debug ().
296
+ Str ("device" , partition .Name ).
297
+ Str ("guest-mountpoint" , entry .Mountpoint ).
298
+ Str ("host-mountpouint" , partition .MountPoint ).
299
+ Msg ("partition matches fstab entry" )
300
+
301
+ // if the partition is already mounted
302
+ if partition .MountPoint != "" {
303
+ mountedWithFstab := strings .HasPrefix (partition .MountPoint , rootScanDir )
304
+ // mounted without fstab consideration, unmount it
305
+ if rootScanDir == "" || ! mountedWithFstab {
306
+ log .Debug ().Str ("device" , partition .Name ).Msg ("partition already mounted" )
307
+ // if the partition is mounted and is the root, we can keep it mounted
308
+ if entry .Mountpoint == "/" {
309
+ rootScanDir = partition .MountPoint
310
+ continue
311
+ }
312
+ if err := d .volumeMounter .UmountP (partition ); err != nil {
313
+ log .Error ().Err (err ).Str ("device" , partition .Name ).Msg ("unable to unmount partition" )
314
+ continue
315
+ }
316
+ partition .MountPoint = ""
317
+ } else if mountedWithFstab { // mounted with fstab, duplicate the partition (probably a subvolume)
318
+ partitionCopy := * partition
319
+ partition = & partitionCopy
320
+ mustAppend = true
299
321
}
300
- partitions [i ].MountPoint = mnt
301
-
302
- break
303
322
}
304
323
305
- // if partitions is already mounted, but there is an entry in fstab, we should register it and mount as subvolume
306
- partition := ptr .To (* partitions [i ]) // copy the partition
324
+ var scanDir * string
325
+ if rootScanDir != "" {
326
+ scanDir = ptr .To (path .Join (rootScanDir , entry .Mountpoint ))
327
+ }
307
328
partition .MountOptions = entry .Options
329
+
308
330
log .Debug ().Str ("device" , partition .Name ).
309
331
Strs ("options" , partition .MountOptions ).
310
- Str ("scan-dir" , path . Join ( partition . MountPoint , entry . Mountpoint ) ).
332
+ Any ("scan-dir" , scanDir ).
311
333
Msg ("mounting partition as subvolume" )
312
334
mnt , err := d .volumeMounter .MountP (& snapshot.MountPartitionDto {
313
335
PartitionInfo : partition ,
314
- ScanDir : ptr . To ( path . Join ( partition . MountPoint , entry . Mountpoint )) ,
336
+ ScanDir : scanDir ,
315
337
})
316
338
if err != nil {
317
339
log .Error ().Err (err ).Str ("device" , partition .Name ).Msg ("unable to mount partition" )
318
340
return partitions , err
319
341
}
342
+
320
343
partition .MountPoint = mnt
321
- partitions = append (partitions , partition )
344
+ if entry .Mountpoint == "/" {
345
+ rootScanDir = mnt
346
+ }
322
347
323
- break
348
+ if mustAppend {
349
+ partitions = append (partitions , partition )
350
+ } else {
351
+ partitions [i ] = partition
352
+ }
353
+
354
+ break // partition matched, no need to check the rest
324
355
}
325
356
}
326
357
return partitions , nil
@@ -348,6 +379,8 @@ func cmpPartition2Fstab(partition *snapshot.PartitionInfo, entry resources.Fstab
348
379
return partition .Uuid == parts [1 ]
349
380
case "LABEL" :
350
381
return partition .Label == parts [1 ]
382
+ case "PARTUUID" :
383
+ return partition .PartUuid == parts [1 ]
351
384
default :
352
385
log .Warn ().Str ("device" , entry .Device ).Msg ("couldn't identify fstab device" )
353
386
return false
@@ -443,7 +476,12 @@ func (c *LinuxDeviceManager) identifyDeviceViaLun(lun int) ([]snapshot.BlockDevi
443
476
}
444
477
445
478
func (c * LinuxDeviceManager ) identifyViaDeviceName (deviceName string , mountAll bool , includeMounted bool ) ([]* snapshot.PartitionInfo , error ) {
446
- blockDevices , err := c .volumeMounter .CmdRunner .GetBlockDevices ()
479
+ if deviceName == "" {
480
+ log .Warn ().Msg ("can't identify partition via device name, no device name provided" )
481
+ return []* snapshot.PartitionInfo {}, nil
482
+ }
483
+
484
+ blockDevices , err := c .cmdRunner .GetBlockDevices ()
447
485
if err != nil {
448
486
return nil , err
449
487
}
0 commit comments