8
8
"strings"
9
9
"syscall"
10
10
11
+ "github.com/pkg/errors"
11
12
"github.com/rs/zerolog/log"
12
13
13
14
"github.com/threefoldtech/zos/pkg"
@@ -174,6 +175,10 @@ func (p *btrfsPool) mounted(fs *Btrfs) (string, bool) {
174
175
return "" , false
175
176
}
176
177
178
+ func (p * btrfsPool ) ID () int {
179
+ return 0
180
+ }
181
+
177
182
func (p * btrfsPool ) Name () string {
178
183
return p .name
179
184
}
@@ -182,6 +187,16 @@ func (p *btrfsPool) Path() string {
182
187
return filepath .Join ("/mnt" , p .name )
183
188
}
184
189
190
+ // Limit on a pool is not supported yet
191
+ func (p * btrfsPool ) Limit (size uint64 ) error {
192
+ return fmt .Errorf ("not implemented" )
193
+ }
194
+
195
+ // FsType of the filesystem of this volume
196
+ func (p * btrfsPool ) FsType () string {
197
+ return "btrfs"
198
+ }
199
+
185
200
// Mount mounts the pool in it's default mount location under /mnt/name
186
201
func (p * btrfsPool ) Mount () (string , error ) {
187
202
ctx := context .Background ()
@@ -287,6 +302,7 @@ func (p *btrfsPool) Volumes() ([]Volume, error) {
287
302
288
303
for _ , sub := range subs {
289
304
volumes = append (volumes , newBtrfsVolume (
305
+ sub .ID ,
290
306
filepath .Join (mnt , sub .Path ),
291
307
p .utils ,
292
308
))
@@ -296,11 +312,17 @@ func (p *btrfsPool) Volumes() ([]Volume, error) {
296
312
}
297
313
298
314
func (p * btrfsPool ) addVolume (root string ) (* btrfsVolume , error ) {
299
- if err := p .utils .SubvolumeAdd (context .Background (), root ); err != nil {
315
+ ctx := context .Background ()
316
+ if err := p .utils .SubvolumeAdd (ctx , root ); err != nil {
317
+ return nil , err
318
+ }
319
+
320
+ volume , err := p .utils .SubvolumeInfo (ctx , root )
321
+ if err != nil {
300
322
return nil , err
301
323
}
302
324
303
- return newBtrfsVolume (root , p .utils ), nil
325
+ return newBtrfsVolume (volume . ID , root , p .utils ), nil
304
326
}
305
327
306
328
func (p * btrfsPool ) AddVolume (name string ) (Volume , error ) {
@@ -314,7 +336,23 @@ func (p *btrfsPool) AddVolume(name string) (Volume, error) {
314
336
}
315
337
316
338
func (p * btrfsPool ) removeVolume (root string ) error {
317
- return p .utils .SubvolumeRemove (context .Background (), root )
339
+ ctx := context .Background ()
340
+
341
+ info , err := p .utils .SubvolumeInfo (ctx , root )
342
+ if err != nil {
343
+ return err
344
+ }
345
+
346
+ if err := p .utils .SubvolumeRemove (ctx , root ); err != nil {
347
+ return err
348
+ }
349
+
350
+ qgroupID := fmt .Sprintf ("0/%d" , info .ID )
351
+ if err := p .utils .QGroupDestroy (ctx , qgroupID , p .Path ()); err != nil {
352
+ return errors .Wrapf (err , "failed to delete qgroup %s" , qgroupID )
353
+ }
354
+
355
+ return nil
318
356
}
319
357
320
358
func (p * btrfsPool ) RemoveVolume (name string ) error {
@@ -357,16 +395,6 @@ func (p *btrfsPool) Usage() (usage Usage, err error) {
357
395
return Usage {Size : totalSize / raidSizeDivisor [du .Data .Profile ], Used : uint64 (fsi [0 ].Used )}, nil
358
396
}
359
397
360
- // Limit on a pool is not supported yet
361
- func (p * btrfsPool ) Limit (size uint64 ) error {
362
- return fmt .Errorf ("not implemented" )
363
- }
364
-
365
- // FsType of the filesystem of this volume
366
- func (p * btrfsPool ) FsType () string {
367
- return "btrfs"
368
- }
369
-
370
398
// Type of the physical storage used for this pool
371
399
func (p * btrfsPool ) Type () pkg.DeviceType {
372
400
// We only create heterogenous pools for now
@@ -393,49 +421,71 @@ func (p *btrfsPool) Reserved() (uint64, error) {
393
421
return total , nil
394
422
}
395
423
424
+ func (p * btrfsPool ) Maintenance () error {
425
+ // this method cleans up all the unused
426
+ // qgroups that could exists on a filesystem
427
+
428
+ volumes , err := p .Volumes ()
429
+ if err != nil {
430
+ return err
431
+ }
432
+ subVolsIDs := map [string ]struct {}{}
433
+ for _ , volume := range volumes {
434
+ // use the 0/X notation to match the qgroup IDs format
435
+ subVolsIDs [fmt .Sprintf ("0/%d" , volume .ID ())] = struct {}{}
436
+ }
437
+
438
+ ctx := context .Background ()
439
+ qgroups , err := p .utils .QGroupList (ctx , p .Path ())
440
+ if err != nil {
441
+ return err
442
+ }
443
+
444
+ for qgroupID := range qgroups {
445
+ // for all qgroup that doesn't have an linked
446
+ // volume, delete the qgroup
447
+ _ , ok := subVolsIDs [qgroupID ]
448
+ if ! ok {
449
+ log .Debug ().Str ("id" , qgroupID ).Msg ("destroy qgroup" )
450
+ if err := p .utils .QGroupDestroy (ctx , qgroupID , p .Path ()); err != nil {
451
+ return err
452
+ }
453
+ }
454
+ }
455
+
456
+ return nil
457
+ }
458
+
396
459
type btrfsVolume struct {
460
+ id int
397
461
path string
398
462
utils * BtrfsUtil
399
463
}
400
464
401
- func newBtrfsVolume (path string , utils * BtrfsUtil ) * btrfsVolume {
465
+ func newBtrfsVolume (ID int , path string , utils * BtrfsUtil ) * btrfsVolume {
402
466
return & btrfsVolume {
467
+ id : ID ,
403
468
path : path ,
404
469
utils : utils ,
405
470
}
406
471
}
407
472
408
- func (v * btrfsVolume ) Path () string {
409
- return v .path
473
+ func (v * btrfsVolume ) ID () int {
474
+ return v .id
410
475
}
411
476
412
- func (v * btrfsVolume ) Volumes () ([]Volume , error ) {
413
- var volumes []Volume
414
-
415
- subs , err := v .utils .SubvolumeList (context .Background (), v .Path ())
416
- if err != nil {
417
- return nil , err
418
- }
419
-
420
- for _ , sub := range subs {
421
- volumes = append (volumes , newBtrfsVolume (filepath .Join (v .Path (), sub .Path ), v .utils ))
422
- }
423
-
424
- return volumes , nil
477
+ func (v * btrfsVolume ) Path () string {
478
+ return v .path
425
479
}
426
480
427
- func (v * btrfsVolume ) AddVolume (name string ) (Volume , error ) {
428
- mnt := filepath .Join (v .Path (), name )
429
- if err := v .utils .SubvolumeAdd (context .Background (), mnt ); err != nil {
430
- return nil , err
431
- }
432
-
433
- return newBtrfsVolume (mnt , v .utils ), nil
481
+ // Name of the filesystem
482
+ func (v * btrfsVolume ) Name () string {
483
+ return filepath .Base (v .Path ())
434
484
}
435
485
436
- func ( v * btrfsVolume ) RemoveVolume ( name string ) error {
437
- mnt := filepath . Join ( v . Path (), name )
438
- return v . utils . SubvolumeRemove ( context . Background (), mnt )
486
+ // FsType of the filesystem
487
+ func ( v * btrfsVolume ) FsType () string {
488
+ return "btrfs"
439
489
}
440
490
441
491
// Usage return the volume usage
@@ -470,13 +520,3 @@ func (v *btrfsVolume) Limit(size uint64) error {
470
520
471
521
return v .utils .QGroupLimit (ctx , size , v .Path ())
472
522
}
473
-
474
- // Name of the filesystem
475
- func (v * btrfsVolume ) Name () string {
476
- return filepath .Base (v .Path ())
477
- }
478
-
479
- // FsType of the filesystem
480
- func (v * btrfsVolume ) FsType () string {
481
- return "btrfs"
482
- }
0 commit comments