mounts: introduce new plugin for mountpoints tuning
- currently supports only barrier handling
This commit is contained in:
parent
04e28bc088
commit
fbde16f16a
2 changed files with 145 additions and 2 deletions
|
|
@ -189,9 +189,9 @@ class Plugin(object):
|
|||
return value == "true" or value == "1"
|
||||
|
||||
def _config_bool(self, value, true_value="1", false_value="0"):
|
||||
if value == True or value == "1" or value.lower() == "true":
|
||||
if value == True or value == "1" or str(value).lower() == "true":
|
||||
return true_value
|
||||
elif value == False or value == "0" or value.lower() == "false":
|
||||
elif value == False or value == "0" or str(value).lower() == "false":
|
||||
return false_value
|
||||
else:
|
||||
return None
|
||||
|
|
|
|||
143
tuned/plugins/plugin_mounts.py
Normal file
143
tuned/plugins/plugin_mounts.py
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
import base
|
||||
from decorators import *
|
||||
from subprocess import Popen,PIPE
|
||||
import tuned.logs
|
||||
import tuned.utils.commands
|
||||
import glob
|
||||
|
||||
log = tuned.logs.get()
|
||||
|
||||
class MountsPlugin(base.Plugin):
|
||||
"""
|
||||
Plugin for tuning options of mount-points.
|
||||
"""
|
||||
|
||||
_mountpoint_topology = None
|
||||
|
||||
def _post_init(self):
|
||||
self._dynamic_tuning = False
|
||||
|
||||
@classmethod
|
||||
def _generate_mountpoint_topology(cls):
|
||||
mountpoint_topology = {}
|
||||
current_disk = None
|
||||
|
||||
stdout, stderr = Popen(["/usr/bin/lsblk", "-rno", "TYPE,RM,KNAME,FSTYPE,MOUNTPOINT"], stdout=PIPE, stderr=PIPE).communicate()
|
||||
for columns in map(lambda line: line.split(), stdout.splitlines()):
|
||||
device_type, device_removable, device_name = columns[:3]
|
||||
filesystem = columns[3] if len(columns) > 3 else None
|
||||
mountpoint = columns[4] if len(columns) > 4 else None
|
||||
|
||||
if device_type == "disk":
|
||||
current_disk = device_name
|
||||
continue
|
||||
|
||||
# skip removable, skip nonpartitions
|
||||
if device_removable == "1" or device_type not in ["part", "lvm"]:
|
||||
continue
|
||||
|
||||
if mountpoint is None or mountpoint == "[SWAP]":
|
||||
continue
|
||||
|
||||
mountpoint_topology.setdefault(mountpoint, {"disks": set(), "device_name": device_name, "filesystem": filesystem})
|
||||
mountpoint_topology[mountpoint]["disks"].add(current_disk)
|
||||
|
||||
cls._mountpoint_topology = mountpoint_topology
|
||||
|
||||
@classmethod
|
||||
def tunable_devices(cls):
|
||||
if cls._mountpoint_topology is None:
|
||||
cls._generate_mountpoint_topology()
|
||||
return set(cls._mountpoint_topology.keys())
|
||||
|
||||
@classmethod
|
||||
def _get_default_options(cls):
|
||||
return {
|
||||
"disable_barriers": None,
|
||||
}
|
||||
|
||||
def _get_device_cache_type(self, device):
|
||||
source_filenames = glob.glob("/sys/block/%s/device/scsi_disk/*/cache_type" % device)
|
||||
for source_filename in source_filenames:
|
||||
return tuned.utils.commands.read_file(source_filename).strip()
|
||||
return None
|
||||
|
||||
def _mountpoint_has_writeback_cache(self, mountpoint):
|
||||
for device in self._mountpoint_topology[mountpoint]["disks"]:
|
||||
if self._get_device_cache_type(device) == "write back":
|
||||
return True
|
||||
return False
|
||||
|
||||
def _mountpoint_has_barriers(self, mountpoint):
|
||||
with open("/proc/mounts") as mounts_file:
|
||||
for line in mounts_file:
|
||||
# device mountpoint filesystem options dump check
|
||||
columns = line.split()
|
||||
if columns[0][0] != "/":
|
||||
continue
|
||||
if columns[1] == mountpoint:
|
||||
option_list = columns[3]
|
||||
break
|
||||
else:
|
||||
return None
|
||||
|
||||
options = option_list.split(",")
|
||||
for option in options:
|
||||
(name, sep, value) = option.partition("=")
|
||||
# nobarrier barrier=0
|
||||
if name == "nobarrier" or (name == "barrier" and value == "0"):
|
||||
return False
|
||||
# barrier barrier=1
|
||||
elif name == "barrier":
|
||||
return True
|
||||
else:
|
||||
# default
|
||||
return True
|
||||
|
||||
def _remount_partition(self, partition, options):
|
||||
remount_command = ["/usr/bin/mount", partition, "-o", "remount,%s" % options]
|
||||
tuned.utils.commands.execute(remount_command)
|
||||
|
||||
@command_custom("disable_barriers", per_device=True)
|
||||
def _disable_barriers(self, start, value, mountpoint):
|
||||
storage_key = self._storage_key("disable_barriers", mountpoint)
|
||||
force = str(value).lower() == "force"
|
||||
value = force or self._config_bool(value)
|
||||
|
||||
if start:
|
||||
if not value:
|
||||
return
|
||||
|
||||
reject_reason = None
|
||||
|
||||
if not force:
|
||||
if mountpoint in ["/", "/boot"]:
|
||||
reject_reason = "system boot protection"
|
||||
elif not self._mountpoint_topology[mountpoint]["filesystem"].startswith("ext"):
|
||||
reject_reason = "filesystem not supported"
|
||||
elif self._mountpoint_has_writeback_cache(mountpoint):
|
||||
reject_reason = "device uses write back cache"
|
||||
|
||||
if reject_reason is None:
|
||||
original_value = self._mountpoint_has_barriers(mountpoint)
|
||||
if original_value is None:
|
||||
reject_reason = "unknown current setting"
|
||||
elif original_value == False:
|
||||
reject_reason = "barriers already disabled"
|
||||
|
||||
if reject_reason is not None:
|
||||
log.info("not disabling barriers on '%s' (%s)" % (mountpoint, reject_reason))
|
||||
return
|
||||
|
||||
self._storage.set(storage_key, original_value)
|
||||
log.info("disabling barriers on '%s'" % mountpoint)
|
||||
self._remount_partition(mountpoint, "barrier=0")
|
||||
|
||||
else:
|
||||
original_value = self._storage.get(storage_key)
|
||||
if original_value is None:
|
||||
return
|
||||
|
||||
log.info("enabling barriers on '%s'" % mountpoint)
|
||||
self._remount_partition(mountpoint, "barrier=1")
|
||||
self._storage.unset(storage_key)
|
||||
Loading…
Reference in a new issue