Files
reniced/ionice_linux.go
2024-04-29 20:42:23 +03:00

81 lines
2.1 KiB
Go

//go:build linux
// +build linux
package main
import (
"fmt"
"log"
"syscall"
proc "github.com/shirou/gopsutil/v3/process"
)
// GetIOPriority достаёт приоритет вводв-вывода для укаанного процесса.
func GetIOPriority(which int, who int) (uint32, error) {
var (
err error
r0, _, e1 = syscall.Syscall(syscall.SYS_IOPRIO_GET, uintptr(which), uintptr(who), 0)
prio = uint32(r0)
)
if e1 != 0 {
err = fmt.Errorf(fmt.Sprintf("Received error number %v", e1))
}
return prio, err
}
// GetIOPriority ставит приоритет вводв-вывода для укаанного процесса.
func SetIOPriority(which int, who int, prio uint32) error {
var (
err error
_, _, e1 = syscall.Syscall(syscall.SYS_IOPRIO_SET, uintptr(which), uintptr(who), uintptr(prio))
)
if e1 != 0 {
err = fmt.Errorf(fmt.Sprintf("Received error number %v", e1))
}
return err
}
// IORenice выставляет процессу приоритет для операций ввода-вывода.
func IORenice(cnf Config, p *proc.Process, processName string) {
if currentIOPrioLevel, err := GetIOPriority(IOPRIO_WHO_PROCESS, int(p.Pid)); err == nil {
currentClass, currentClassdata := PrioToClassAndClassdata(currentIOPrioLevel)
class := ioreniceClass[processName]
classdata := ioreniceClassdata[processName]
if class == currentClass && classdata == currentClassdata {
if cnf.Debug && currentIOPrioLevel != 0 { // 0 - это дефолтный уровень io niceness.
log.Printf(
"IONiceness for %s(%d) already set to %d %d",
processName,
p.Pid,
currentClass,
currentClassdata,
)
}
} else {
iopriority := ClassAndClassdataToPrio(class, classdata)
_ = SetIOPriority(IOPRIO_WHO_PROCESS, int(p.Pid), iopriority)
if cnf.Debug {
log.Printf(
"Set ioniceness for %s(%d) to %d %d (was %d %d)",
processName,
p.Pid,
class,
classdata,
currentClass,
currentClassdata,
)
}
}
} else {
log.Printf("Unable to get ioprio for %s(%d)", processName, p.Pid)
}
}