diff --git a/include/swap-default.conf b/include/swap-default.conf index f3e99c7..60ba3b4 100644 --- a/include/swap-default.conf +++ b/include/swap-default.conf @@ -17,7 +17,7 @@ zswap_enabled=1 zswap_compressor=zstd # lzo lz4 zstd lzo-rle lz4hc zswap_max_pool_percent=25 # 1-99 -zswap_zpool=z3fold # zbud z3fold (note z3fold requires kernel 4.8+) +zswap_zpool=zsmalloc # zbud z3fold (note z3fold requires kernel 4.8+, deprecated since 6.12) zsmalloc ################################################################################ # ZRam diff --git a/include/systemd-swap.service b/include/systemd-swap.service index e0ba5bc..ab8c04b 100644 --- a/include/systemd-swap.service +++ b/include/systemd-swap.service @@ -1,7 +1,7 @@ [Unit] Description=Manage swap spaces on zram, files and partitions. -Wants=modprobe@zram.service -After=modprobe@zram.service +Wants=modprobe@zram.service modprobe@z3fold.service modprobe@zbud.service +After=modprobe@zram.service modprobe@z3fold.service modprobe@zbud.service [Service] Type=notify diff --git a/man/swap.conf.5 b/man/swap.conf.5 index 78cb198..8ab1d61 100644 --- a/man/swap.conf.5 +++ b/man/swap.conf.5 @@ -49,7 +49,7 @@ and Percentage of ram that can be compressed. .I .IP zswap_zpool= -Set wich compressed memory pool to use, if unsure use z3fold. +Set wich compressed memory pool to use, if unsure use zsmalloc. .PP The following options are available in the "zram" section: .I diff --git a/src/systemd-swap.py b/src/systemd-swap.py index eaf7895..2d0770a 100755 --- a/src/systemd-swap.py +++ b/src/systemd-swap.py @@ -37,7 +37,7 @@ def get_mem_stats(fields: List[str]) -> Dict[str, int]: stats[key] = int(items[1]) * 1024 if not fields: break - assert len(fields) == 0 + assert len(fields) <= 1 return stats @@ -57,8 +57,8 @@ def get_mem_stats(fields: List[str]) -> Dict[str, int]: ) WORK_DIR = "/run/systemd/swap" LOCK_STARTED = f"{WORK_DIR}/.started" -ZSWAP_M = "/sys/module/zswap" -ZSWAP_M_P = "/sys/module/zswap/parameters" +MODULE_PATH = "/sys/module" +ZSWAP_M_P = f"{MODULE_PATH}/zswap/parameters" KMAJOR, KMINOR = [int(v) for v in os.uname().release.split(".")[0:2]] IS_DEBUG = False sigterm_event = threading.Event() @@ -423,8 +423,12 @@ def destroy_swapfile(self) -> None: @staticmethod def get_free_ram_perc() -> int: - ram_stats = get_mem_stats(["MemTotal", "MemFree"]) - return round((ram_stats["MemFree"] * 100) / ram_stats["MemTotal"]) + ram_stats = get_mem_stats(["MemTotal", "MemFree", "MemAvailable"]) + if "MemAvailable" in ram_stats: + free_ram = ram_stats["MemAvailable"] + else: + free_ram = ram_stats["MemFree"] + return round((free_ram * 100) / ram_stats["MemTotal"]) @staticmethod def get_free_swap_perc() -> int: @@ -432,6 +436,9 @@ def get_free_swap_perc() -> int: # Minimum for total is 1 to prevent divide by zero. return round((swap_stats["SwapFree"] * 100) / max(swap_stats["SwapTotal"], 1)) +def module_loaded(module_name) -> bool: + return os.path.isdir(f"/sys/module/{module_name}") + def debug(msg: str) -> None: if IS_DEBUG: @@ -468,8 +475,11 @@ def relative_symlink(target: str, link_name: str) -> None: def write(data: str, file: str) -> None: - with open(file, "w") as f: - f.write(data) + try: + with open(file, "w") as f: + f.write(data) + except: + warn(f"Failed writing {data} to file {file}") def read(file: str) -> str: @@ -625,8 +635,12 @@ def start_swapd() -> None: def start_zswap() -> None: systemd.daemon.notify("STATUS=Setting up Zswap...") - if not os.path.isdir(ZSWAP_M): - error("Zswap - not supported on current kernel") + info("Zswap: check module availability") + if module_loaded("zswap"): + info("Zswap: module loaded") + else: + error("Zswap: module not available") + info("Zswap: backup current configuration: start") makedirs(f"{WORK_DIR}/zswap") for file in os.listdir(ZSWAP_M_P): @@ -640,19 +654,30 @@ def start_zswap() -> None: f'{config.get("zswap_max_pool_percent")}, Zpool: ' f'{config.get("zswap_zpool")}' ) + + zpool_allocator = config.get("zswap_zpool") + if (zpool_allocator != "zsmalloc") and (not module_loaded(zpool_allocator)): + warn(f"Zswap: Desired Zpool allocator {zpool_allocator} not available") + if zswap_parameters[f"{ZSWAP_M_P}/zpool"]: + zpool_allocator = zswap_parameters[f"{ZSWAP_M_P}/zpool"] + warn(f"Zswap: Keeping current {zpool_allocator}") + else: + zpool_allocator = "zsmalloc" + warn("Zswap: Defaulting to zsmalloc") + write(config.get("zswap_enabled"), f"{ZSWAP_M_P}/enabled") write(config.get("zswap_compressor"), f"{ZSWAP_M_P}/compressor") write(config.get("zswap_max_pool_percent"), f"{ZSWAP_M_P}/max_pool_percent") - write(config.get("zswap_zpool"), f"{ZSWAP_M_P}/zpool") + write(zpool_allocator, f"{ZSWAP_M_P}/zpool") info("Zswap: set new parameters: complete") def start_zram() -> None: systemd.daemon.notify("STATUS=Setting up Zram...") info("Zram: check module availability") - if not os.path.isdir("/sys/module/zram"): - error("Zram: module not availible") + if module_loaded("zram"): + info("Zram: module loaded") else: - info("Zram: module found!") + error("Zram: module not available") def zram_init() -> None: info("Zram: trying to initialize free device")