diff --git a/pkg/hostman/hostinfo/hostinfo.go b/pkg/hostman/hostinfo/hostinfo.go index 8f8a41d013..4c6859d3ce 100644 --- a/pkg/hostman/hostinfo/hostinfo.go +++ b/pkg/hostman/hostinfo/hostinfo.go @@ -399,6 +399,42 @@ func (h *SHostInfo) parseConfig() error { return nil } +func (h *SHostInfo) getIoSchedulerSupported(scheduler string, supportedSchedulers []string) (string, map[string]string) { + // IoScheduler default to none scheduler + ioParams := make(map[string]string, 0) + switch scheduler { + case "deadline": + if utils.IsInStringArray("mq-deadline", supportedSchedulers) { + scheduler = "mq-deadline" + } else if utils.IsInStringArray("deadline", supportedSchedulers) { + scheduler = "deadline" + } else { + scheduler = "none" + } + case "cfq": + if utils.IsInStringArray("bfq", supportedSchedulers) { + scheduler = "bfq" + } else if utils.IsInStringArray("cfq", supportedSchedulers) { + scheduler = "cfq" + } else { + scheduler = "none" + } + default: + if !utils.IsInStringArray(scheduler, supportedSchedulers) { + scheduler = "none" + } + } + ioParams["queue/scheduler"] = scheduler + switch scheduler { + case "cfq": + ioParams["queue/iosched/group_isolation"] = "1" + ioParams["queue/iosched/slice_idle"] = "0" + ioParams["queue/iosched/group_idle"] = "0" + ioParams["queue/iosched/quantum"] = "32" + } + return scheduler, ioParams +} + func (h *SHostInfo) prepareEnv() error { if err := h.fixPathEnv(); err != nil { return errors.Wrap(err, "Fix path environment") @@ -430,44 +466,21 @@ func (h *SHostInfo) prepareEnv() error { } supportedSchedulers, _ := fileutils2.GetAllBlkdevsIoSchedulers() - // IoScheduler default to none scheduler - ioParams := make(map[string]string, 0) - switch options.HostOptions.BlockIoScheduler { - case "deadline": - if utils.IsInStringArray("mq-deadline", supportedSchedulers) { - h.IoScheduler = "mq-deadline" - } else if utils.IsInStringArray("deadline", supportedSchedulers) { - h.IoScheduler = "deadline" - } else { - h.IoScheduler = "none" - } - case "cfq": - if utils.IsInStringArray("bfq", supportedSchedulers) { - h.IoScheduler = "bfq" - } else if utils.IsInStringArray("cfq", supportedSchedulers) { - h.IoScheduler = "cfq" - } else { - h.IoScheduler = "none" - } - default: - if utils.IsInStringArray(options.HostOptions.BlockIoScheduler, supportedSchedulers) { - h.IoScheduler = options.HostOptions.BlockIoScheduler - } else { - h.IoScheduler = "none" - } + log.Infof("supported io schedulers %v", supportedSchedulers) + // set hdd block devices io scheduler + { + hddIoScheduler, ioParams := h.getIoSchedulerSupported(options.HostOptions.BlockIoScheduler, supportedSchedulers) + log.Infof("HDD I/O Scheduler switch to %s", hddIoScheduler) + fileutils2.ChangeHddBlkdevsParams(ioParams) + h.IoScheduler = hddIoScheduler + } + // set ssd block devices io scheduler + { + ssdIoScheduler, ioParams := h.getIoSchedulerSupported(options.HostOptions.SsdBlockIoScheduler, supportedSchedulers) + log.Infof("SSD I/O Scheduler switch to %s", ssdIoScheduler) + fileutils2.ChangeSsdBlkdevsParams(ioParams) } - log.Infof("I/O Scheduler switch to %s", h.IoScheduler) - - ioParams["queue/scheduler"] = h.IoScheduler - switch h.IoScheduler { - case "cfq": - ioParams["queue/iosched/group_isolation"] = "1" - ioParams["queue/iosched/slice_idle"] = "0" - ioParams["queue/iosched/group_idle"] = "0" - ioParams["queue/iosched/quantum"] = "32" - } - fileutils2.ChangeAllBlkdevsParams(ioParams) _, err = procutils.NewRemoteCommandAsFarAsPossible("modprobe", "tun").Output() if err != nil { return errors.Wrap(err, "Failed to activate tun/tap device") diff --git a/pkg/hostman/options/options.go b/pkg/hostman/options/options.go index 02dcb65158..0b985b3b2d 100644 --- a/pkg/hostman/options/options.go +++ b/pkg/hostman/options/options.go @@ -105,10 +105,11 @@ type SHostOptions struct { LinuxDefaultRootUser bool `help:"Default account for linux system is root"` WindowsDefaultAdminUser bool `default:"true" help:"Default account for Windows system is Administrator"` - BlockIoScheduler string `help:"Block IO scheduler, deadline or cfq" default:"deadline"` - EnableKsm bool `help:"Enable Kernel Same Page Merging"` - HugepagesOption string `help:"Hugepages option: disable|native|transparent" default:"transparent"` - HugepageSizeMb int `help:"hugepage size mb default 1G" default:"1024"` + BlockIoScheduler string `help:"HDD Block IO scheduler, deadline or cfq" default:"deadline"` + SsdBlockIoScheduler string `help:"SSD Block IO scheduler, none deadline or cfq" default:"none"` + EnableKsm bool `help:"Enable Kernel Same Page Merging"` + HugepagesOption string `help:"Hugepages option: disable|native|transparent" default:"transparent"` + HugepageSizeMb int `help:"hugepage size mb default 1G" default:"1024"` // PrivatePrefixes []string `help:"IPv4 private prefixes"` LocalImagePath []string `help:"Local image storage paths"` diff --git a/pkg/util/fileutils2/fileutils.go b/pkg/util/fileutils2/fileutils.go index 0fb95776bd..30e81e019a 100644 --- a/pkg/util/fileutils2/fileutils.go +++ b/pkg/util/fileutils2/fileutils.go @@ -152,6 +152,10 @@ func GetAllBlkdevsIoSchedulers() ([]string, error) { return nil, errors.Wrap(err, "ioutil.ReadDir(/sys/block)") } for _, b := range blockDevs { + // check is a block device + if !Exists(path.Join("/sys/block", b.Name(), "device")) { + continue + } if IsBlockDevMounted(b.Name()) { conf, err := GetBlkdevConfig(b.Name(), "queue/scheduler") if err != nil { @@ -186,10 +190,63 @@ func ChangeAllBlkdevsParams(params map[string]string) { return } for _, b := range blockDevs { - if IsBlockDevMounted(b.Name()) { - for k, v := range params { - ChangeBlkdevParameter(b.Name(), k, v) - } + if !Exists(path.Join("/sys/block", b.Name(), "device")) { + continue + } + for k, v := range params { + ChangeBlkdevParameter(b.Name(), k, v) + } + } + } +} + +func BlockDevIsSsd(dev string) bool { + rotational := path.Join("/sys/block", dev, "queue", "rotational") + res, err := FileGetContents(rotational) + if err != nil { + log.Errorf("FileGetContents fail %s %s", rotational, err) + return false + } + return strings.TrimSpace(res) == "0" +} + +func ChangeSsdBlkdevsParams(params map[string]string) { + if _, err := os.Stat("/sys/block"); !os.IsNotExist(err) { + blockDevs, err := ioutil.ReadDir("/sys/block") + if err != nil { + log.Errorf("ReadDir /sys/block error: %s", err) + return + } + for _, b := range blockDevs { + if !Exists(path.Join("/sys/block", b.Name(), "device")) { + continue + } + if !BlockDevIsSsd(b.Name()) { + continue + } + for k, v := range params { + ChangeBlkdevParameter(b.Name(), k, v) + } + } + } +} + +func ChangeHddBlkdevsParams(params map[string]string) { + if _, err := os.Stat("/sys/block"); !os.IsNotExist(err) { + blockDevs, err := ioutil.ReadDir("/sys/block") + if err != nil { + log.Errorf("ReadDir /sys/block error: %s", err) + return + } + for _, b := range blockDevs { + if !Exists(path.Join("/sys/block", b.Name(), "device")) { + continue + } + if BlockDevIsSsd(b.Name()) { + continue + } + for k, v := range params { + ChangeBlkdevParameter(b.Name(), k, v) } } }