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 коммит произвёл GitHub
Родитель 5706d8206b b36e613d9f
Коммит 93e322f5be
1 изменённых файлов: 82 добавлений и 38 удалений

Просмотреть файл

@ -35,11 +35,6 @@ func init() {
graphdriver.Register("btrfs", Init)
}
var (
quotaEnabled = false
userDiskQuota = false
)
type btrfsOptions struct {
minSpace uint64
size uint64
@ -70,18 +65,11 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
return nil, err
}
opt, err := parseOptions(options)
opt, userDiskQuota, err := parseOptions(options)
if err != nil {
return nil, err
}
if userDiskQuota {
if err := subvolEnableQuota(home); err != nil {
return nil, err
}
quotaEnabled = true
}
driver := &Driver{
home: home,
uidMaps: uidMaps,
@ -89,30 +77,37 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
options: opt,
}
if userDiskQuota {
if err := driver.subvolEnableQuota(); err != nil {
return nil, err
}
}
return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil
}
func parseOptions(opt []string) (btrfsOptions, error) {
func parseOptions(opt []string) (btrfsOptions, bool, error) {
var options btrfsOptions
userDiskQuota := false
for _, option := range opt {
key, val, err := parsers.ParseKeyValueOpt(option)
if err != nil {
return options, err
return options, userDiskQuota, err
}
key = strings.ToLower(key)
switch key {
case "btrfs.min_space":
minSpace, err := units.RAMInBytes(val)
if err != nil {
return options, err
return options, userDiskQuota, err
}
userDiskQuota = true
options.minSpace = uint64(minSpace)
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.
@ -122,6 +117,7 @@ type Driver struct {
uidMaps []idtools.IDMap
gidMaps []idtools.IDMap
options btrfsOptions
quotaEnabled bool
}
// 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.
func (d *Driver) Cleanup() error {
if quotaEnabled {
if err := subvolDisableQuota(d.home); err != nil {
if err := d.subvolDisableQuota(); err != nil {
return err
}
}
return mount.Unmount(d.home)
}
@ -294,8 +288,17 @@ func subvolDelete(dirpath, name string) error {
return nil
}
func subvolEnableQuota(path string) error {
dir, err := openDir(path)
func (d *Driver) subvolEnableQuota() error {
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 {
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())
}
d.quotaEnabled = true
return nil
}
func subvolDisableQuota(path string) error {
dir, err := openDir(path)
func (d *Driver) subvolDisableQuota() error {
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 {
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())
}
d.quotaEnabled = false
return nil
}
func subvolRescanQuota(path string) error {
dir, err := openDir(path)
func (d *Driver) subvolRescanQuota() error {
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 {
return err
}
@ -366,6 +391,28 @@ func subvolLimitQgroup(path string, size uint64) error {
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 {
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)))
}
if !quotaEnabled {
if err := subvolEnableQuota(d.home); err != nil {
if err := d.subvolEnableQuota(); err != nil {
return err
}
quotaEnabled = true
}
if err := subvolLimitQgroup(dir, driver.options.size); err != nil {
return err
@ -494,7 +538,7 @@ func (d *Driver) Remove(id string) error {
if err := os.RemoveAll(dir); err != nil && !os.IsNotExist(err) {
return err
}
if err := subvolRescanQuota(d.home); err != nil {
if err := d.subvolRescanQuota(); err != nil {
return err
}
return nil