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:
commit
93e322f5be
1 changed files with 82 additions and 38 deletions
|
@ -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,39 +77,47 @@ 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.
|
||||||
type Driver struct {
|
type Driver struct {
|
||||||
//root of the file system
|
//root of the file system
|
||||||
home string
|
home string
|
||||||
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,10 +146,8 @@ 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,11 +515,8 @@ 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 {
|
||||||
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue