diff --git a/Makefile b/Makefile index 091b235..b0af91b 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ archive: clean cp tuned.py tuned.spec tuned.service tuned.tmpfiles Makefile tuned-adm.py \ tuned.bash dbus.conf recommend.conf tuned-main.conf $(VERSIONED_NAME) - cp -a doc experiments man profiles systemtap tuned $(VERSIONED_NAME) + cp -a doc experiments libexec man profiles systemtap tuned $(VERSIONED_NAME) tar cjf $(VERSIONED_NAME).tar.bz2 $(VERSIONED_NAME) @@ -94,6 +94,12 @@ install: cp -a doc/* $(DESTDIR)/usr/share/doc/$(VERSIONED_NAME) cp AUTHORS COPYING README $(DESTDIR)/usr/share/doc/$(VERSIONED_NAME) + # Install libexec scripts + install -m 0755 -Dd $(DESTDIR)/usr/libexec/tuned + for file in libexec/*; do \ + install -m 0755 $$file $(DESTDIR)/usr/libexec/tuned; \ + done + clean: find -name "*.pyc" | xargs rm -f rm -rf $(VERSIONED_NAME) rpm-build-dir diff --git a/libexec/pmqos-static.py b/libexec/pmqos-static.py new file mode 100755 index 0000000..f0efafc --- /dev/null +++ b/libexec/pmqos-static.py @@ -0,0 +1,158 @@ +#!/usr/bin/python +# +# pmqos-static.py: Simple daemon for setting static PM QoS values. It is a part +# of 'tuned' and it should not be called manually. +# +# Copyright (C) 2011 Red Hat, Inc. +# Authors: Jan Vcelak +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# + +import os +import signal +import struct +import sys +import time + +# Used interface is described in Linux kernel documentation: +# Documentation/power/pm_qos_interface.txt + +ALLOWED_INTERFACES = [ "cpu_dma_latency", "network_latency", "network_throughput" ] +PIDFILE = "/var/run/tuned/pmqos-static.pid" + +def do_fork(): + pid = os.fork() + if pid > 0: + sys.exit(0) + +def close_fds(): + s_in = file('/dev/null', 'r') + s_out = file('/dev/null', 'a+') + s_err = file('/dev/null', 'a+', 0) + os.dup2(s_in.fileno(), sys.stdin.fileno()) + os.dup2(s_out.fileno(), sys.stdout.fileno()) + os.dup2(s_err.fileno(), sys.stderr.fileno()) + +def write_pidfile(): + f = os.open(PIDFILE, os.O_CREAT | os.O_TRUNC | os.O_WRONLY, 0644) + os.write(f, "%d" % os.getpid()) + os.close(f) + +def daemonize(): + do_fork() + os.chdir("/") + os.setsid() + os.umask(0) + do_fork() + close_fds() + +def set_pmqos(name, value): + filename = "/dev/%s" % name + bin_value = struct.pack("i", int(value)) + fd = os.open(filename, os.O_WRONLY) + os.write(fd, bin_value) + return fd + +def sleep_forever(): + while True: + time.sleep(86400) + +def sigterm_handler(signum, frame): + global pmqos_fds + if type(pmqos_fds) is list: + for fd in pmqos_fds: + os.close(fd) + sys.exit(0) + +def run_daemon(options): + try: + daemonize() + write_pidfile() + signal.signal(signal.SIGTERM, sigterm_handler) + except Exception, e: + print >>sys.stderr, "Cannot daemonize (%s)." % e + return False + + global pmqos_fds + pmqos_fds = [] + + for (name, value) in options.items(): + try: + new_fd = set_pmqos(name, value) + pmqos_fds.append(new_fd) + except: + # we are daemonized + pass + + if len(pmqos_fds) > 0: + sleep_forever() + else: + return False + +def kill_daemon(force = False): + try: + with open(PIDFILE, "r") as pidfile: + daemon_pid = int(pidfile.read()) + except IOError, e: + if not force: print >>sys.stderr, "Cannot open PID file (%s)." % e + return False + + try: + os.kill(daemon_pid, signal.SIGTERM) + except OSError, e: + if not force: print >>sys.stderr, "Cannot terminate the daemon (%s)." % e + return False + + try: + os.unlink(PIDFILE) + except OSError, e: + if not force: print >>sys.stderr, "Cannot delete the PID file (%s)." % e + return False + + return True + +if __name__ == "__main__": + + disable = False + options = {} + + for option in sys.argv[1:]: + if option == "disable": + disable = True + break + + try: + (name, value) = option.split("=") + except ValueError: + name = option + value = None + + if name in ALLOWED_INTERFACES and len(value) > 0: + options[name] = value + else: + print >>sys.stderr, "Invalid option (%s)." % option + + + if disable: + sys.exit(0 if kill_daemon() else 1) + + if len(options) == 0: + print >>sys.stderr, "No options set. Not starting." + sys.exit(1) + + kill_daemon(True) + run_daemon(options) + sys.exit(1) diff --git a/tuned.spec b/tuned.spec index bb917ad..a02f6d4 100644 --- a/tuned.spec +++ b/tuned.spec @@ -26,8 +26,8 @@ Summary: Various tuned utilities Requires: powertop %description utils -This package contains utilities that can help you to fine tune your -system and manage tuned profiles. +This package contains utilities that can help you to fine tune and +debug your system and manage tuned profiles. %package utils-systemtap Summary: Disk and net statistic monitoring systemtap scripts @@ -124,6 +124,7 @@ sed -i 's|.*/\([^/]\+\)/[^\.]\+\.conf|\1|' /etc/tuned/active_profile %defattr(-,root,root,-) %doc COPYING %{_bindir}/powertop2tuned +%{_libexecdir}/tuned/ %files utils-systemtap %defattr(-,root,root,-)