1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #29835 from yongtang/29810-btrfs-rescan

Run btrfs rescan only if userDiskQuota is enabled
This commit is contained in:
Brian Goff 2017-01-26 15:55:51 -08:00 committed by GitHub
commit 93e322f5be

View file

@ -35,11 +35,6 @@ func init() {
graphdriver.Register("btrfs", Init) graphdriver.Register("btrfs", Init)
} }
var (
quotaEnabled = false
userDiskQuota = false
)
type btrfsOptions struct { type btrfsOptions struct {
minSpace uint64 minSpace uint64
size uint64 size uint64
@ -70,18 +65,11 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
return nil, err return nil, err
} }
opt, err := parseOptions(options) opt, userDiskQuota, err := parseOptions(options)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if userDiskQuota {
if err := subvolEnableQuota(home); err != nil {
return nil, err
}
quotaEnabled = true
}
driver := &Driver{ driver := &Driver{
home: home, home: home,
uidMaps: uidMaps, uidMaps: uidMaps,
@ -89,30 +77,37 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
options: opt, options: opt,
} }
if userDiskQuota {
if err := driver.subvolEnableQuota(); err != nil {
return nil, err
}
}
return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil
} }
func parseOptions(opt []string) (btrfsOptions, error) { func parseOptions(opt []string) (btrfsOptions, bool, error) {
var options btrfsOptions var options btrfsOptions
userDiskQuota := false
for _, option := range opt { for _, option := range opt {
key, val, err := parsers.ParseKeyValueOpt(option) key, val, err := parsers.ParseKeyValueOpt(option)
if err != nil { if err != nil {
return options, err return options, userDiskQuota, err
} }
key = strings.ToLower(key) key = strings.ToLower(key)
switch key { switch key {
case "btrfs.min_space": case "btrfs.min_space":
minSpace, err := units.RAMInBytes(val) minSpace, err := units.RAMInBytes(val)
if err != nil { if err != nil {
return options, err return options, userDiskQuota, err
} }
userDiskQuota = true userDiskQuota = true
options.minSpace = uint64(minSpace) options.minSpace = uint64(minSpace)
default: default:
return options, fmt.Errorf("Unknown option %s", key) return options, userDiskQuota, fmt.Errorf("Unknown option %s", key)
} }
} }
return options, nil return options, userDiskQuota, nil
} }
// Driver contains information about the filesystem mounted. // Driver contains information about the filesystem mounted.
@ -122,6 +117,7 @@ type Driver struct {
uidMaps []idtools.IDMap uidMaps []idtools.IDMap
gidMaps []idtools.IDMap gidMaps []idtools.IDMap
options btrfsOptions options btrfsOptions
quotaEnabled bool
} }
// String prints the name of the driver (btrfs). // String prints the name of the driver (btrfs).
@ -150,11 +146,9 @@ func (d *Driver) GetMetadata(id string) (map[string]string, error) {
// Cleanup unmounts the home directory. // Cleanup unmounts the home directory.
func (d *Driver) Cleanup() error { func (d *Driver) Cleanup() error {
if quotaEnabled { if err := d.subvolDisableQuota(); err != nil {
if err := subvolDisableQuota(d.home); err != nil {
return err return err
} }
}
return mount.Unmount(d.home) return mount.Unmount(d.home)
} }
@ -294,8 +288,17 @@ func subvolDelete(dirpath, name string) error {
return nil return nil
} }
func subvolEnableQuota(path string) error { func (d *Driver) subvolEnableQuota() error {
dir, err := openDir(path) if d.quotaEnabled {
return nil
}
// In case quotaEnabled is not set, check qgroup and update quotaEnabled as needed
if _, err := subvolLookupQgroup(d.home); err == nil {
d.quotaEnabled = true
return nil
}
dir, err := openDir(d.home)
if err != nil { if err != nil {
return err return err
} }
@ -309,11 +312,22 @@ func subvolEnableQuota(path string) error {
return fmt.Errorf("Failed to enable btrfs quota for %s: %v", dir, errno.Error()) return fmt.Errorf("Failed to enable btrfs quota for %s: %v", dir, errno.Error())
} }
d.quotaEnabled = true
return nil return nil
} }
func subvolDisableQuota(path string) error { func (d *Driver) subvolDisableQuota() error {
dir, err := openDir(path) if !d.quotaEnabled {
// In case quotaEnabled is not set, check qgroup and update quotaEnabled as needed
if _, err := subvolLookupQgroup(d.home); err != nil {
// quota is still not enabled
return nil
}
d.quotaEnabled = true
}
dir, err := openDir(d.home)
if err != nil { if err != nil {
return err return err
} }
@ -327,11 +341,22 @@ func subvolDisableQuota(path string) error {
return fmt.Errorf("Failed to disable btrfs quota for %s: %v", dir, errno.Error()) return fmt.Errorf("Failed to disable btrfs quota for %s: %v", dir, errno.Error())
} }
d.quotaEnabled = false
return nil return nil
} }
func subvolRescanQuota(path string) error { func (d *Driver) subvolRescanQuota() error {
dir, err := openDir(path) if !d.quotaEnabled {
// In case quotaEnabled is not set, check qgroup and update quotaEnabled as needed
if _, err := subvolLookupQgroup(d.home); err != nil {
// quota is still not enabled
return nil
}
d.quotaEnabled = true
}
dir, err := openDir(d.home)
if err != nil { if err != nil {
return err return err
} }
@ -366,6 +391,28 @@ func subvolLimitQgroup(path string, size uint64) error {
return nil return nil
} }
func subvolLookupQgroup(path string) (uint64, error) {
dir, err := openDir(path)
if err != nil {
return 0, err
}
defer closeDir(dir)
var args C.struct_btrfs_ioctl_ino_lookup_args
args.objectid = C.BTRFS_FIRST_FREE_OBJECTID
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, getDirFd(dir), C.BTRFS_IOC_INO_LOOKUP,
uintptr(unsafe.Pointer(&args)))
if errno != 0 {
return 0, fmt.Errorf("Failed to lookup qgroup for %s: %v", dir, errno.Error())
}
if args.treeid == 0 {
return 0, fmt.Errorf("Invalid qgroup id for %s: 0", dir)
}
return uint64(args.treeid), nil
}
func (d *Driver) subvolumesDir() string { func (d *Driver) subvolumesDir() string {
return path.Join(d.home, "subvolumes") return path.Join(d.home, "subvolumes")
} }
@ -468,12 +515,9 @@ func (d *Driver) setStorageSize(dir string, driver *Driver) error {
return fmt.Errorf("btrfs: storage size cannot be less than %s", units.HumanSize(float64(d.options.minSpace))) return fmt.Errorf("btrfs: storage size cannot be less than %s", units.HumanSize(float64(d.options.minSpace)))
} }
if !quotaEnabled { if err := d.subvolEnableQuota(); err != nil {
if err := subvolEnableQuota(d.home); err != nil {
return err return err
} }
quotaEnabled = true
}
if err := subvolLimitQgroup(dir, driver.options.size); err != nil { if err := subvolLimitQgroup(dir, driver.options.size); err != nil {
return err return err
@ -494,7 +538,7 @@ func (d *Driver) Remove(id string) error {
if err := os.RemoveAll(dir); err != nil && !os.IsNotExist(err) { if err := os.RemoveAll(dir); err != nil && !os.IsNotExist(err) {
return err return err
} }
if err := subvolRescanQuota(d.home); err != nil { if err := d.subvolRescanQuota(); err != nil {
return err return err
} }
return nil return nil