func (m *btrfsManager) SubvolQuota(cmd *pm.Command) (interface{}, error) {
	var args SubvolQuotaArgument
	if err := json.Unmarshal(*cmd.Arguments, &args); err != nil {
		return nil, err
	}
	if args.Path == "" || !strings.HasPrefix(args.Path, "/") {
		return nil, fmt.Errorf("invalid path=%v", args.Path)
	}
	_, err := m.btrfs("quota", "enable", args.Path)
	if err != nil {
		return nil, err
	}
	_, err = m.btrfs("qgroup", "limit", args.Limit, args.Path)
	if err != nil {
		return nil, err
	}
	return nil, nil
}
create quota for a subvolume
package btrfs
import (
	"encoding/json"
	"fmt"
	"regexp"
	"strconv"
	"strings"
	"github.com/zero-os/0-core/base/pm"
)
var (
	reBtrfsFilesystemDf = regexp.MustCompile(`(?m:(\w+),\s(\w+):\s+total=(\d+),\s+used=(\d+))`)
)
type btrfsManager struct{}
func init() {
	var m btrfsManager
	pm.RegisterBuiltIn("btrfs.list", m.List)
	pm.RegisterBuiltIn("btrfs.info", m.Info)
	pm.RegisterBuiltIn("btrfs.create", m.Create)
	pm.RegisterBuiltIn("btrfs.device_add", m.DeviceAdd)
	pm.RegisterBuiltIn("btrfs.device_remove", m.DeviceRemove)
	pm.RegisterBuiltIn("btrfs.subvol_create", m.SubvolCreate)
	pm.RegisterBuiltIn("btrfs.subvol_delete", m.SubvolDelete)
	pm.RegisterBuiltIn("btrfs.subvol_quota", m.SubvolQuota)
	pm.RegisterBuiltIn("btrfs.subvol_list", m.SubvolList)
	pm.RegisterBuiltIn("btrfs.subvol_snapshot", m.SubvolSnapshot)
}
type btrfsFS struct {
	Label        string        `json:"label"`
	UUID         string        `json:"uuid"`
	TotalDevices int           `json:"total_devices"`
	Used         int64         `json:"used"`
	Devices      []btrfsDevice `json:"devices"`
}
type btrfsDataInfo struct {
	Profile string `json:"profile"`
	Total   int64  `json:"total"`
	Used    int64  `json:"used"`
}
type btrfsFSInfo struct {
	btrfsFS
	Data          btrfsDataInfo `json:"data"`
	System        btrfsDataInfo `json:"system"`
	MetaData      btrfsDataInfo `json:"metadata"`
	GlobalReserve btrfsDataInfo `json:"globalreserve"`
}
type btrfsDevice struct {
	Missing bool   `json:"missing,omitempty"`
	DevID   int    `json:"dev_id"`
	Size    int64  `json:"size"`
	Used    int64  `json:"used"`
	Path    string `json:"path"`
}
type btrfsSubvol struct {
	ID       int
	Gen      int
	TopLevel int
	Path     string
}
var (
	Profiles = map[string]struct{}{
		"raid0":  struct{}{},
		"raid1":  struct{}{},
		"raid5":  struct{}{},
		"raid6":  struct{}{},
		"raid10": struct{}{},
		"dup":    struct{}{},
		"single": struct{}{},
		"":       struct{}{},
	}
)
type CreateArgument struct {
	Label     string   `json:"label"`
	Metadata  string   `json:"metadata"`
	Data      string   `json:"data"`
	Devices   []string `json:"devices"`
	Overwrite bool     `json:"overwrite"`
}
type InfoArgument struct {
	Mountpoint string `json:"mountpoint"`
}
type DeviceAddArgument struct {
	InfoArgument
	Devices []string `json:"devices"`
}
type SnapshotArgument struct {
	Source      string `json:"source"`
	Destination string `json:"destination"`
	Readonly    bool   `json:"read_only"`
}
func (arg CreateArgument) Validate() error {
	if len(arg.Devices) == 0 {
		return fmt.Errorf("need to specify devices to create btrfs")
	}
	if v, ok := Profiles[arg.Metadata]; !ok {
		return fmt.Errorf("invalid metadata profile:%v", v)
	}
	if v, ok := Profiles[arg.Data]; !ok {
		return fmt.Errorf("invalid data profile:%v", v)
	}
	return nil
}
func (m *btrfsManager) Create(cmd *pm.Command) (interface{}, error) {
	var args CreateArgument
	var opts []string
	if err := json.Unmarshal(*cmd.Arguments, &args); err != nil {
		return nil, err
	}
	if err := args.Validate(); err != nil {
		return nil, err
	}
	if args.Overwrite {
		opts = append(opts, "-f")
	}
	if args.Label != "" {
		opts = append(opts, "-L", args.Label)
	}
	if args.Metadata != "" {
		opts = append(opts, "-m", args.Metadata)
	}
	if args.Data != "" {
		opts = append(opts, "-d", args.Data)
	}
	opts = append(opts, args.Devices...)
	_, err := pm.System("mkfs.btrfs", opts...)
	if err != nil {
		return nil, err
	}
	return nil, nil
}
func (m *btrfsManager) DeviceAdd(cmd *pm.Command) (interface{}, error) {
	var args DeviceAddArgument
	if err := json.Unmarshal(*cmd.Arguments, &args); err != nil {
		return nil, err
	}
	cmdArgs := []string{"device", "add", "-K", "-f"}
	cmdArgs = append(cmdArgs, args.Devices...)
	cmdArgs = append(cmdArgs, args.Mountpoint)
	_, err := m.btrfs(cmdArgs...)
	if err != nil {
		return nil, err
	}
	return nil, nil
}
func (m *btrfsManager) DeviceRemove(cmd *pm.Command) (interface{}, error) {
	var args DeviceAddArgument
	if err := json.Unmarshal(*cmd.Arguments, &args); err != nil {
		return nil, err
	}
	cmdArgs := []string{"device", "remove"}
	cmdArgs = append(cmdArgs, args.Devices...)
	cmdArgs = append(cmdArgs, args.Mountpoint)
	_, err := m.btrfs(cmdArgs...)
	if err != nil {
		return nil, err
	}
	return nil, nil
}
func (m *btrfsManager) list(cmd *pm.Command, args []string) ([]btrfsFS, error) {
	defaultargs := []string{"filesystem", "show", "--raw"}
	defaultargs = append(defaultargs, args...)
	result, err := m.btrfs(defaultargs...)
	if err != nil {
		return nil, err
	}
	fss, err := m.parseList(result.Streams.Stdout())
	if err != nil {
		return nil, err
	}
	if fss == nil {
		fss = make([]btrfsFS, 0)
	}
	return fss, err
}
func (m *btrfsManager) List(cmd *pm.Command) (interface{}, error) {
	return m.list(cmd, []string{})
}
func (m *btrfsManager) Info(cmd *pm.Command) (interface{}, error) {
	var args InfoArgument
	if err := json.Unmarshal(*cmd.Arguments, &args); err != nil {
		return nil, err
	}
	fss, err := m.list(cmd, []string{args.Mountpoint})
	if err != nil {
		return nil, err
	}
	result, err := m.btrfs("filesystem", "df", "--raw", args.Mountpoint)
	if err != nil {
		return nil, err
	}
	fsinfo := btrfsFSInfo{
		btrfsFS: fss[0],
	}
	err = m.parseFilesystemDF(result.Streams.Stdout(), &fsinfo)
	return fsinfo, err
}
type SubvolArgument struct {
	Path string `json:"path"`
}
type SubvolQuotaArgument struct {
	SubvolArgument
	Limit string `json:"limit"`
}
func (m *btrfsManager) SubvolCreate(cmd *pm.Command) (interface{}, error) {
	var args SubvolArgument
	if err := json.Unmarshal(*cmd.Arguments, &args); err != nil {
		return nil, err
	}
	if args.Path == "" || !strings.HasPrefix(args.Path, "/") {
		return nil, fmt.Errorf("invalid path=%v", args.Path)
	}
	_, err := m.btrfs("subvolume", "create", args.Path)
	if err != nil {
		return nil, err
	}
	return nil, nil
}
func (m *btrfsManager) SubvolDelete(cmd *pm.Command) (interface{}, error) {
	var args SubvolArgument
	if err := json.Unmarshal(*cmd.Arguments, &args); err != nil {
		return nil, err
	}
	if args.Path == "" || !strings.HasPrefix(args.Path, "/") {
		return nil, fmt.Errorf("invalid path=%v", args.Path)
	}
	_, err := m.btrfs("subvolume", "delete", args.Path)
	if err != nil {
		return nil, err
	}
	return nil, nil
}