Memo

共 16 条

time-warp-test.c: check TSC synchronity on x86 CPUs

time-warp-test.c: check TSC synchronity on x86 CPUs. Also detects gettimeofday()-level time warps.

/*
* Copyright (C) 2005, Ingo Molnar
*
* time-warp-test.c: check TSC synchronity on x86 CPUs. Also detects
*                   gettimeofday()-level time warps.
*
* Compile with: gcc -Wall -O2 -o time-warp-test time-warp-test.c -lrt
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
#include <linux/unistd.h>
#include <unistd.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <regex.h>
#include <fcntl.h>
#include <time.h>
#include <sys/mman.h>
#include <dlfcn.h>
//#include <popt.h>
#include <sys/socket.h>
#include <ctype.h>
#include <assert.h>
#include <sched.h>
#include <time.h>

#define TEST_TSC 1
#define TEST_TOD 1
#define TEST_CLOCK 1

#if !TEST_TSC && !TEST_TOD && !TEST_CLOCK
# error this setting makes no sense ...
#endif

#if DEBUG
# define Printf(x...) printf(x)
#else
# define Printf(x...) do { } while (0)
#endif

/*
 * Shared locks and variables between the test tasks:
 */
enum {
    SHARED_LOCK     = 0,
    SHARED_TSC      = 2,
    SHARED_TOD      = 4,
    SHARED_CLOCK        = 6,
    SHARED_WORST_TSC    = 8,
    SHARED_WORST_TOD    = 10,
    SHARED_WORST_CLOCK  = 12,
    SHARED_NR_TSC_LOOPS = 14,
    SHARED_NR_TSC_WARPS = 16,
    SHARED_NR_TOD_LOOPS = 18,
    SHARED_NR_TOD_WARPS = 20,
    SHARED_NR_CLOCK_LOOPS   = 22,
    SHARED_NR_CLOCK_WARPS   = 24,
    SHARED_END      = 26,
};

#define SHARED(x)   (*(shared + SHARED_##x))
#define SHARED_LL(x)    (*(long long *)(shared + SHARED_##x))

#define BUG_ON(c) assert(!(c))

typedef unsigned long long cycles_t;
typedef unsigned long long usecs_t;
typedef unsigned long long u64;

#ifdef __x86_64__
#define DECLARE_ARGS(val, low, high)    unsigned low, high
#define EAX_EDX_VAL(val, low, high)     ((low) | ((u64)(high) << 32))
#define EAX_EDX_ARGS(val, low, high)    "a" (low), "d" (high)
#define EAX_EDX_RET(val, low, high)     "=a" (low), "=d" (high)
#else
#define DECLARE_ARGS(val, low, high)    unsigned long long val
#define EAX_EDX_VAL(val, low, high)     (val)
#define EAX_EDX_ARGS(val, low, high)    "A" (val)
#define EAX_EDX_RET(val, low, high)     "=A" (val)
#endif

static inline unsigned long long __rdtscll(void)
{
    DECLARE_ARGS(val, low, high);

    asm volatile("cpuid; rdtsc" : EAX_EDX_RET(val, low, high));

    return EAX_EDX_VAL(val, low, high);
}

#define rdtscll(val) do { (val) = __rdtscll(); } while (0)

#define rdtod(val)                  \
    do {                            \
        struct timeval tv;              \
        \
        gettimeofday(&tv, NULL);            \
        (val) = tv.tv_sec * 1000000ULL + tv.tv_usec;    \
    } while (0)

#define rdclock(val)                    \
    do {                            \
        struct timespec ts;             \
        \
        clock_gettime(CLOCK_MONOTONIC, &ts);        \
        (val) = ts.tv_sec * 1000000000ULL + ts.tv_nsec; \
    } while (0)

static unsigned long *setup_shared_var(void)
{
    char zerobuff [4096] = { 0, };
    int ret, fd;
    unsigned long *buf;

    fd = creat(".tmp_mmap", 0700);
    BUG_ON(fd == -1);
    close(fd);

    fd = open(".tmp_mmap", O_RDWR|O_CREAT|O_TRUNC);
    BUG_ON(fd == -1);
    ret = write(fd, zerobuff, 4096);
    BUG_ON(ret != 4096);

    buf = (void *)mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    BUG_ON(buf == (void *)-1);

    close(fd);
    unlink(".tmp_mmap");

    return buf;
}

static inline void lock(unsigned long *flag)
{
#if 0
    __asm__ __volatile__(
            "1: lock; btsl $0,%0\n"
            "jc 1b\n"
            : "=g"(*flag) : : "memory");
#else
    __asm__ __volatile__(
            "1: lock; btsl $0,%0\n\t"
            "jnc 3f\n"
            "2: testl $1,%0\n\t"
            "je 1b\n\t"
            "rep ; nop\n\t"
            "jmp 2b\n"
            "3:"
            : "+m"(*flag) : : "memory");
#endif
}

static inline void unlock(unsigned long *flag)
{
#if 0
    __asm__ __volatile__(
            "lock; btrl $0,%0\n"
            : "=g"(*flag) :: "memory");
    __asm__ __volatile__("rep; nop");
#else
    __asm__ __volatile__("mov $0,%0; rep; nop" : "=g"(*flag) :: "memory");
#endif
}

static void print_status(unsigned long *shared)
{
    const char progress[] = "\\|/-";

    static unsigned long long sum_tsc_loops, sum_tod_loops, sum_clock_loops,
                         sum_tod;
    static unsigned int count1, count2;
    static usecs_t prev_tod;

    usecs_t tod;

    if (!prev_tod)
        rdtod(prev_tod);

    count1++;
    if (count1 < 1000)
        return;
    count1 = 0;

    rdtod(tod);
    if (abs(tod - prev_tod) < 100000ULL)
        return;

    sum_tod += tod - prev_tod;
    sum_tsc_loops += SHARED_LL(NR_TSC_LOOPS);
    sum_tod_loops += SHARED_LL(NR_TOD_LOOPS);
    sum_clock_loops += SHARED_LL(NR_CLOCK_LOOPS);
    SHARED_LL(NR_TSC_LOOPS) = 0;
    SHARED_LL(NR_TOD_LOOPS) = 0;
    SHARED_LL(NR_CLOCK_LOOPS) = 0;

    if (TEST_TSC)
        printf(" | TSC: %.2fus, fail:%ld",
                (double)sum_tod/(double)sum_tsc_loops,
                SHARED(NR_TSC_WARPS));

    if (TEST_TOD)
        printf(" | TOD: %.2fus, fail:%ld",
                (double)sum_tod/(double)sum_tod_loops,
                SHARED(NR_TOD_WARPS));

    if (TEST_CLOCK)
        printf(" | CLK: %.2fus, fail:%ld",
                (double)sum_tod/(double)sum_clock_loops,
                SHARED(NR_CLOCK_WARPS));

    prev_tod = tod;
    count2++;
    printf(" %c\r", progress[count2 & 3]);
    fflush(stdout);
}

static inline void test_TSC(unsigned long *shared)
{
#if TEST_TSC
    cycles_t t0, t1;
    long long delta;

    lock(&SHARED(LOCK));
    rdtscll(t1);
    t0 = SHARED_LL(TSC);
    SHARED_LL(TSC) = t1;
    SHARED_LL(NR_TSC_LOOPS)++;
    unlock(&SHARED(LOCK));

    delta = t1-t0;
    if (delta < 0) {
        lock(&SHARED(LOCK));
        SHARED(NR_TSC_WARPS)++;
        if (delta < SHARED_LL(WORST_TSC)) {
            SHARED_LL(WORST_TSC) = delta;
            fprintf(stderr, "\rnew TSC-warp maximum: %9Ld cycles, %016Lx -> %016Lx\n",
                    delta, t0, t1);
        }
        unlock(&SHARED(LOCK));
    }
    if (!((unsigned long)t0 & 31))
        asm volatile ("rep; nop");
#endif
}

static inline void test_TOD(unsigned long *shared)
{
#if TEST_TOD
    usecs_t T0, T1;
    long long delta;

    lock(&SHARED(LOCK));
    rdtod(T1);
    T0 = SHARED_LL(TOD);
    SHARED_LL(TOD) = T1;
    SHARED_LL(NR_TOD_LOOPS)++;
    unlock(&SHARED(LOCK));

    delta = T1-T0;
    if (delta < 0) {
        lock(&SHARED(LOCK));
        SHARED(NR_TOD_WARPS)++;
        if (delta < SHARED_LL(WORST_TOD)) {
            SHARED_LL(WORST_TOD) = delta;
            fprintf(stderr, "\rnew TOD-warp maximum: %9Ld usecs,  %016Lx -> %016Lx\n",
                    delta, T0, T1);
        }
        unlock(&SHARED(LOCK));
    }
#endif
}

static inline void test_CLOCK(unsigned long *shared)
{
#if TEST_CLOCK
    usecs_t T0, T1;
    long long delta;

    lock(&SHARED(LOCK));
    rdclock(T1);
    T0 = SHARED_LL(CLOCK);
    SHARED_LL(CLOCK) = T1;
    SHARED_LL(NR_CLOCK_LOOPS)++;
    unlock(&SHARED(LOCK));

    delta = T1-T0;
    if (delta < 0) {
        lock(&SHARED(LOCK));
        SHARED(NR_CLOCK_WARPS)++;
        if (delta < SHARED_LL(WORST_CLOCK)) {
            SHARED_LL(WORST_CLOCK) = delta;
            fprintf(stderr, "\rnew CLOCK-warp maximum: %9Ld nsecs,  %016Lx -> %016Lx\n",
                    delta, T0, T1);
        }
        unlock(&SHARED(LOCK));
    }
#endif
}

int main(int argc, char **argv)
{
    int i, parent, me;
    unsigned long *shared;
    unsigned long cpus, tasks;

    cpus = system("exit `grep ^processor /proc/cpuinfo  | wc -l`");
    cpus = WEXITSTATUS(cpus);

    if (argc > 2) {
usage:
        fprintf(stderr,
                "usage: tsc-sync-test <threads>\n");
        exit(-1);
    }
    if (argc == 2) {
        tasks = atol(argv[1]);
        if (!tasks)
            goto usage;
    } else
        tasks = cpus;

    printf("%ld CPUs, running %ld parallel test-tasks.\n", cpus, tasks);
    printf("checking for time-warps via:\n"
#if TEST_TSC
            "- read time stamp counter (RDTSC) instruction (cycle resolution)\n"
#endif
#if TEST_TOD
            "- gettimeofday (TOD) syscall (usec resolution)\n"
#endif
#if TEST_CLOCK
            "- clock_gettime(CLOCK_MONOTONIC) syscall (nsec resolution)\n"
#endif
            "\n"
          );
    shared = setup_shared_var();

    parent = getpid();

    for (i = 1; i < tasks; i++) {
        if (!fork())
            break;
    }
    me = getpid();

    while (1) {
        int i;

        for (i = 0; i < 10; i++)
            test_TSC(shared);
        for (i = 0; i < 10; i++)
            test_TOD(shared);
        for (i = 0; i < 10; i++)
            test_CLOCK(shared);

        if (me == parent)
            print_status(shared);
    }

    return 0;
}

通过 SSH 迁移 btrfs volumes

配置 SSH 免密:

ssh-copy-id -i ~/.ssh/id_ed25519.pub <user>@<host>

在目标端配置 sudo 免密:

https://serverfault.com/questions/160581/how-to-setup-passwordless-sudo-on-linux

%wheel ALL=(ALL:ALL) NOPASSWD: ALL

The key is to add it after the last line which says

#includedir /etc/sudoers.d

创建快照:

# sudo btrfs subvolume snapshot -r <fs-path> <snapshot-path>
sudo btrfs subvolume snapshot -r / /sysfs_ro

发送:

sudo pacman -S pv
# sudo btrfs send <snapshot-path> | pv | ssh <target-machine> "sudo btrfs receive <target-fs-path>"
sudo btrfs send /sysfs_ro | pv | ssh target-host "sudo btrfs receive /mnt/arc"

# 发送完成后,路径是 /mnt/arc/sysfs_ro

ArchLinux NVIDIA GPU 容器启动失败

ArchLinux (2025-09-06)启动 GPU 容器失败:

-> % docker run --rm --gpus=all nvidia/cuda:12.1.1-base-ubuntu22.04 nvidia-smi
Unable to find image 'nvidia/cuda:12.1.1-base-ubuntu22.04' locally
12.1.1-base-ubuntu22.04: Pulling from nvidia/cuda
aece8493d397: Already exists
dd4939a04761: Pull complete
b0d7cc89b769: Pull complete
1532d9024b9c: Pull complete
04fc8a31fa53: Pull complete
Digest: sha256:457a4076c56025f51217bff647ca631c7880ad3dbf546b03728ba98297ebbc22
Status: Downloaded newer image for nvidia/cuda:12.1.1-base-ubuntu22.04
docker: Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error running prestart hook #0: exit status 1, stdout: , stderr: Auto-detected mode as 'legacy'
nvidia-container-cli: ldcache error: process /sbin/ldconfig terminated with signal 9

解决办法:

System Update in Arch Linux, broked NVIDIA container. Open Source drivers

sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml
sudo nvidia-ctk config --in-place --set nvidia-container-runtime.mode=cdi
systemctl restart docker
# /etc/docker/daemon.json
  "default-runtime": "nvidia",
  "runtimes": {
    "nvidia": {
      "path": "/usr/bin/nvidia-container-runtime",
      "runtimeArgs": []
    }
  }

关闭侧信道攻击缓解,make Linux great again!

lscpu 会看到一些侧信道攻击缓解措施:

-> % lscpu
  ...
  Spec rstack overflow:      Mitigation; IBPB on VMEXIT only
  Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
  Spectre v1:                Mitigation; usercopy/swapgs barriers and __user pointer sanitization
  Spectre v2:                Mitigation; Enhanced / Automatic IBRS; IBPB conditional; STIBP always-on; PBRSB-eIBRS Not affected; BHI Not affected

Wikipedia - Spectre

但是关我屁事,我是物理机用户,又不是云上的虚拟机用户。

以前有人做了一个 make linux great again 网站,但是下线了。

而且实际上也不需要 那一堆 配置,你只需要 mitigations=off 就行了。

# ArchLinux
-> % cat /boot/loader/entries/2025-06-30_04-02-18_linux.conf
# Created by: archinstall
# Created on: 2025-06-30_04-02-18
title   Arch Linux (linux)
linux   /vmlinuz-linux
initrd  /initramfs-linux.img
options root=PARTUUID=<uuid> zswap.enabled=0 rw rootfstype=btrfs mitigations=off

在 options 最后加上重启就完事。

# Fedora
sudo grubby --update-kernel=ALL --args="mitigations=off selinux=0"

检查好不好使:

-> % cat /proc/cmdline
initrd=\initramfs-linux.img root=PARTUUID=<uuid> zswap.enabled=0 rw rootfstype=btrfs amd_iommu=on amdttm.pages_limit=27648000 amdttm.page_pool_size=27648000 mitigations=off
-> % lscpu
  ...
  Spec rstack overflow:      Vulnerable
  Spec store bypass:         Vulnerable
  Spectre v1:                Vulnerable: __user pointer sanitization and usercopy barriers only; no swapgs barriers
  Spectre v2:                Vulnerable; IBPB: disabled; STIBP: disabled; PBRSB-eIBRS: Not affected; BHI: Not affected

ArchLinux 编译 python-kornia-rs

安装 python-kornia-rs 失败,构建的时候 g 了。

直接一把梭搞定。

user@host [23:50:58] [~/.cache/yay/python-kornia-rs] [master *]
-> % makepkg -s
==> Making package: python-kornia-rs 0.1.9-5 (Thu 24 Jul 2025 11:51:05 PM CST)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
  -> Found kornia-rs-0.1.9.tar.gz
==> Validating source files with sha256sums...
    kornia-rs-0.1.9.tar.gz ... Passed
==> Extracting sources...
  -> Extracting kornia-rs-0.1.9.tar.gz with bsdtar
==> Removing existing $pkgdir/ directory...
==> Starting build()...
* Getting build dependencies for wheel...
* Building wheel...
Running `maturin pep517 build-wheel -i /usr/bin/python --compatibility off`
🔗 Found pyo3 bindings
💥 maturin failed
  Caused by: Python interpreter should be a kind of interpreter (e.g. 'python3.8' or 'pypy3.9') when cross-compiling, got path to interpreter: /usr/bin/python
Error: command ['maturin', 'pep517', 'build-wheel', '-i', '/usr/bin/python', '--compatibility', 'off'] returned non-zero exit status 1

ERROR Backend subprocess exited when trying to invoke build_wheel
==> ERROR: A failure occurred in build().
    Aborting...
export PYO3_CROSS_PYTHON_VERSION=3.13
export PYO3_CROSS_LIB_DIR=/usr/lib
export CARGO_BUILD_TARGET=x86_64-unknown-linux-gnu
makepkg -sf

-> % ls -lah
total 2.8M
drwxr-xr-x 1 user user  310 Jul 24 23:53 .
drwxr-xr-x 1 user user  358 Jul 24 23:17 ..
drwxr-xr-x 1 user user  140 Jul 24 23:49 .git
-rw-r--r-- 1 user user 235K Jul 24 23:17 kornia-rs-0.1.9.tar.gz
-rw-r--r-- 1 user user   96 Jul 24 23:17 .nvchecker.toml
drwxr-xr-x 1 user user   76 Jul 24 23:53 pkg
-rw-r--r-- 1 user user 1.1K Jul 24 23:52 PKGBUILD
-rw-r--r-- 1 user user 2.3M Jul 24 23:53 python-kornia-rs-0.1.9-5-x86_64.pkg.tar.zst
-rw-r--r-- 1 user user 252K Jul 24 23:53 python-kornia-rs-debug-0.1.9-5-x86_64.pkg.tar.zst
drwxr-xr-x 1 user user   74 Jul 24 23:52 src
-rw-r--r-- 1 user user  793 Jul 24 23:17 .SRCINFO

-> % sudo pacman -U python-kornia-rs-0.1.9-5-x86_64.pkg.tar.zst

把 ArchLinux 当成无线路由器用

刚进货一台新服务器,有两个有线网口,只有四个 PCIe,插一个无线网卡太浪费。那么就让他走到另一台有无线网卡的机器上网吧!

sudo pacman -S nftables
-> % cat /etc/nftables.conf
#!/usr/bin/nft -f
# vim:set ts=2 sw=2 et:

# IPv4/IPv6 Simple & Safe firewall ruleset.
# More examples in /usr/share/nftables/ and /usr/share/doc/nftables/examples/.

destroy table inet filter
table inet filter {
  chain input {
    type filter hook input priority 0; policy drop;

    ct state invalid drop comment "early drop of invalid connections"
    ct state {established, related} accept comment "allow tracked connections"
    iif lo accept comment "allow from loopback"
    ip protocol icmp accept comment "allow icmp"
    meta l4proto ipv6-icmp accept comment "allow icmp v6"
    tcp dport ssh accept comment "allow sshd"
    pkttype host limit rate 5/second counter reject with icmpx type admin-prohibited
    counter
  }

  chain forward {
    type filter hook forward priority 0; policy drop;
    iifname "enp2s0" oifname "wlo1" accept
    ct state established,related accept
  }

  chain output {
        type filter hook output priority 0; policy accept;
  }
}

table ip nat {
    chain prerouting {
        type nat hook prerouting priority 0; policy accept;
    }

    chain postrouting {
        type nat hook postrouting priority 100; policy accept;
        oifname "wlo1" masquerade
    }
}
-> % sudo systemctl enable --now nftables.service
-> % cat /etc/sysctl.d/30-ipforward.conf
net.ipv4.ip_forward=1

-> % sudo sysctl --system

解决 PostgreSQL `could not open shared memory segment` 错误

解决 PostgreSQL could not open shared memory segment 错误。

打开 journalctl -u postgresql.service 可以看到:

Jun 15 11:55:52 fanyang-legion postgres[322924]: 2025-06-15 11:55:52.856 CST [322924] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 11:56:52 fanyang-legion postgres[322973]: 2025-06-15 11:56:52.914 CST [322973] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 11:57:52 fanyang-legion postgres[323026]: 2025-06-15 11:57:52.975 CST [323026] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 11:58:53 fanyang-legion postgres[323076]: 2025-06-15 11:58:53.034 CST [323076] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 11:59:53 fanyang-legion postgres[323127]: 2025-06-15 11:59:53.042 CST [323127] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 12:00:53 fanyang-legion postgres[323181]: 2025-06-15 12:00:53.099 CST [323181] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 12:01:53 fanyang-legion postgres[323229]: 2025-06-15 12:01:53.155 CST [323229] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 12:02:53 fanyang-legion postgres[323286]: 2025-06-15 12:02:53.193 CST [323286] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 12:03:53 fanyang-legion postgres[323334]: 2025-06-15 12:03:53.219 CST [323334] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 12:04:53 fanyang-legion postgres[323385]: 2025-06-15 12:04:53.232 CST [323385] ERROR:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory
Jun 15 12:05:04 fanyang-legion postgres[323386]: 2025-06-15 12:05:04.501 CST [323386] FATAL:  could not open shared memory segment "/PostgreSQL.2816709408": No such file or directory

解决方法:

PostgreSQL 11 Shared Memory Error: could not open shared memory segment "/PostgreSQL.XXXXXXXX": No such file or directory

# sudo vim /etc/systemd/logind.conf
RemoveIPC=no
systemctl restart systemd-logind.service

vLLM 部署为 systemd 服务

配置 vLLM 环境,并且让他随着系统自启动

安装环境:

mkdir my-vllm
cd my-vllm

uv init
uv add vllm

编写 service 文件:

# vim /etc/systemd/system/vllm.service

[Unit]
Description=vLLM
After=network.target
Wants=network.target

[Service]
Type=simple
Environment=HF_ENDPOINT=https://hf-mirror.com
WorkingDirectory=/opt/vllm
ExecStart=uv run vllm serve "Qwen/Qwen3-Embedding-0.6B"
Restart=always
RestartSec=10
User=user
Group=user

[Install]
WantedBy=multi-user.target

vLLM,启动!

systemctl daemon-reload
systemctl enable --now vllm

默认端口

Oracle Linux Shell Script to Calculate Values Recommended Linux HugePages Configuration (Doc ID 401749.1)

Oracle Doc ID 401749.1 的脚本,自动配置 hugepage

#!/bin/bash
#
# hugepages_settings.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
# on Oracle Linux
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
#
# This script is provided by Doc ID 401749.1 from My Oracle Support
# http://support.oracle.com
# Welcome text
echo "
This script is provided by Doc ID 401749.1 from My Oracle Support
(http://support.oracle.com) where it is intended to compute values for
the recommended HugePages/HugeTLB configuration for the current shared
memory segments on Oracle Linux. Before proceeding with the execution please note following:
* For ASM instance, it needs to configure ASMM instead of AMM.
* The 'pga_aggregate_target' is outside the SGA and
 you should accommodate this while calculating the overall size.
* In case you changes the DB SGA size,
 as the new SGA will not fit in the previous HugePages configuration,
 it had better disable the whole HugePages,
 start the DB with new SGA size and run the script again.
And make sure that:
* Oracle Database instance(s) are up and running
* Oracle Database 11g Automatic Memory Management (AMM) is not setup
 (See Doc ID 749851.1)
* The shared memory segments can be listed by command:
 # ipcs -m
Press Enter to proceed..."
read
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
if [ -z "$HPG_SZ" ];then
 echo "The hugepages may not be supported in the system where the script is being
executed."
 exit 1
fi
# Initialize the counter
NUM_PG=0
# Cumulative number of pages required to handle the running shared memory segments
for SEG_BYTES in `ipcs -m | cut -c44-300 | awk '{print $1}' | grep "[0-9][0-9]*"`
do
 MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`
 if [ $MIN_PG -gt 0 ]; then
 NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`
 fi
done
RES_BYTES=`echo "$NUM_PG * $HPG_SZ * 1024" | bc -q`
# An SGA less than 100MB does not make sense
# Bail out if that is the case
if [ $RES_BYTES -lt 100000000 ]; then
 echo "***********"
 echo "** ERROR **"
 echo "***********"
 echo "Sorry! There are not enough total of shared memory segments allocated for
HugePages configuration. HugePages can only be used for shared memory segments
that you can list by command:
 # ipcs -m
of a size that can match an Oracle Database SGA. Please make sure that:
* Oracle Database instance is up and running
* Oracle Database 11g Automatic Memory Management (AMM) is not configured"
 exit 1
fi
# Finish with results
case $KERN in
 '2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;
 echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
 '2.6') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
 '3.8') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
 '3.10') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
 '4.1') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
 '4.14') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
 '4.18') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
 '5.4') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
 *) echo "Kernel version $KERN is not supported by this script (yet). Exiting." ;;
esac
# End

dm-delay 模拟慢速磁盘

速查

# 创建一个 10G 大小的 ram disk
sudo modprobe brd rd_nr=1 rd_size=1048576
sudo blockdev --getsize /dev/ram0

# 创建 delayed dm,延迟为 500ms
export RAM_SIZE=$(blockdev --getsize /dev/ram0)
echo "0 $RAM_SIZE delay /dev/ram0 0 500" | sudo dmsetup create delayed

# 重新加载参数
echo "0 $RAM_SIZE delay /dev/ram0 0 500" | sudo dmsetup reload delayed

delayed 参数

<device> <offset> <delay> [<write_device> <write_offset> <write_delay> [<flush_device> <flush_offset> <flush_delay>]]

暂停 I/O

sudo dmsetup suspend /dev/dm-0
sudo dmsetup resume  /dev/dm-0

检查 delayed 设备的 I/O 延迟

fio --name a --filename=/dev/dm-0 --bs=4k --rw=randread --ioengine=libaio --direct=1 --iodepth=1 --numjobs=1 --time_based=1 --runtime=10
fio --name a --filename=/dev/dm-0 --bs=4k --rw=randread --ioengine=sync --direct=1 --iodepth=1 --numjobs=1 --time_based=1 --runtime=10