@@ -483,15 +483,20 @@ func (d *Driver) CreateFromTemplate(id, template string, templateIDMappings *idt
483483// CreateReadWrite creates a layer that is writable for use as a container
484484// file system.
485485func (d * Driver ) CreateReadWrite (id , parent string , opts * graphdriver.CreateOpts ) error {
486- return d .create (id , parent , opts , true )
486+ return d .create (id , parent , opts , false )
487487}
488488
489489// Create the filesystem with given id.
490490func (d * Driver ) Create (id , parent string , opts * graphdriver.CreateOpts ) error {
491- return d .create (id , parent , opts , false )
491+ return d .create (id , parent , opts , true )
492492}
493493
494- func (d * Driver ) create (id , parent string , opts * graphdriver.CreateOpts , applyDriverDefaultQuota bool ) error {
494+ func (d * Driver ) create (id , parent string , opts * graphdriver.CreateOpts , readOnly bool ) error {
495+ quota , err := d .parseStorageOpt (opts , readOnly )
496+ if err != nil {
497+ return err
498+ }
499+
495500 quotas := d .quotasDir ()
496501 subvolumes := d .subvolumesDir ()
497502 if err := os .MkdirAll (subvolumes , 0o700 ); err != nil {
@@ -518,34 +523,14 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, applyDr
518523 }
519524 }
520525
521- var storageOpt map [string ]string
522- if opts != nil {
523- storageOpt = opts .StorageOpt
524- }
525-
526- var quotaSize uint64
527- var needQuota bool
528- if _ , ok := storageOpt ["size" ]; ok {
529- driver := & Driver {}
530- if err := d .parseStorageOpt (storageOpt , driver ); err != nil {
531- return err
532- }
533- quotaSize = driver .options .size
534- needQuota = true
535- }
536- if ! needQuota && applyDriverDefaultQuota && d .options .size > 0 {
537- quotaSize = d .options .size
538- needQuota = true
539- }
540- if needQuota {
541- layerDriver := & Driver {options : btrfsOptions {size : quotaSize }}
542- if err := d .setStorageSize (path .Join (subvolumes , id ), layerDriver ); err != nil {
526+ if quota != nil {
527+ if err := d .setStorageSize (path .Join (subvolumes , id ), * quota ); err != nil {
543528 return err
544529 }
545530 if err := os .MkdirAll (quotas , 0o700 ); err != nil {
546531 return err
547532 }
548- if err := os .WriteFile (path .Join (quotas , id ), []byte (fmt .Sprint (quotaSize )), 0o644 ); err != nil {
533+ if err := os .WriteFile (path .Join (quotas , id ), []byte (fmt .Sprint (quota . size )), 0o644 ); err != nil {
549534 return err
550535 }
551536 }
@@ -558,40 +543,63 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts, applyDr
558543 return label .Relabel (path .Join (subvolumes , id ), mountLabel , false )
559544}
560545
561- // Parse btrfs storage options
562- func (d * Driver ) parseStorageOpt (storageOpt map [string ]string , driver * Driver ) error {
546+ // layerQuota contains per-layer quota settings.
547+ type layerQuota struct {
548+ size uint64
549+ }
550+
551+ // parseStorageOpt parses CreateOpts.StorageOpt.
552+ // Returns a *layerQuota if a quota should be applied, nil otherwise.
553+ func (d * Driver ) parseStorageOpt (opts * graphdriver.CreateOpts , readOnly bool ) (* layerQuota , error ) {
554+ var storageOpt map [string ]string = nil // Iterating over a nil map is safe
555+ if opts != nil {
556+ storageOpt = opts .StorageOpt
557+ }
558+
559+ res := layerQuota {}
560+ needQuota := false
561+
562+ if ! readOnly && d .options .size > 0 {
563+ res .size = d .options .size
564+ needQuota = true
565+ }
566+
563567 // Read size to change the subvolume disk quota per container
564568 for key , val := range storageOpt {
565569 key := strings .ToLower (key )
566570 switch key {
567571 case "size" :
568572 size , err := units .RAMInBytes (val )
569573 if err != nil {
570- return err
574+ return nil , err
571575 }
572- driver .options .size = uint64 (size )
576+ res .size = uint64 (size )
577+ needQuota = true
573578 default :
574- return fmt .Errorf ("unknown option %s (%q)" , key , storageOpt )
579+ return nil , fmt .Errorf ("unknown option %s (%q)" , key , storageOpt )
575580 }
576581 }
577582
578- return nil
583+ if needQuota {
584+ return & res , nil
585+ }
586+ return nil , nil
579587}
580588
581589// Set btrfs storage size
582- func (d * Driver ) setStorageSize (dir string , driver * Driver ) error {
583- if driver . options .size <= 0 {
584- return fmt .Errorf ("btrfs: invalid storage size: %s" , units .HumanSize (float64 (driver . options .size )))
590+ func (d * Driver ) setStorageSize (dir string , quota layerQuota ) error {
591+ if quota .size <= 0 {
592+ return fmt .Errorf ("btrfs: invalid storage size: %s" , units .HumanSize (float64 (quota .size )))
585593 }
586- if d .options .minSpace > 0 && driver . options .size < d .options .minSpace {
594+ if d .options .minSpace > 0 && quota .size < d .options .minSpace {
587595 return fmt .Errorf ("btrfs: storage size cannot be less than %s" , units .HumanSize (float64 (d .options .minSpace )))
588596 }
589597
590598 if err := d .enableQuota (); err != nil {
591599 return err
592600 }
593601
594- if err := subvolLimitQgroup (dir , driver . options .size ); err != nil {
602+ if err := subvolLimitQgroup (dir , quota .size ); err != nil {
595603 return err
596604 }
597605
0 commit comments