やるきなし

2017/07/16 23:56 / Linux 4.12.0 -> 4.13-rc1

4.13-rc1が出ているので .config がどう変更されるのか見てみた.ターゲットは VMware on Windows 上の Guest で CPU は i7-3687U.以下 - は削除されたもの,+ は追加されたもの m->n 等は値の変化を示す.

Related articles

2017/07/03 12:39 / dax: Could not allocate 8192 bytes percpu data on Linux 4.12

Kernel を 4.12 に上げたら dax (手元では device-mapper が依存)が modprobe に失敗するようになった.

percpu: allocation failed, size=8192 align=4096 atomic=0, alloc from reserved chunk failed
CPU: 4 PID: 3257 Comm: modprobe Tainted: P           O    4.12.0-(snip)
Hardware name: (snip)
Call Trace:
 ? dump_stack+0x5c/0x7a
 ? pcpu_alloc+0x601/0x640
 ? load_module+0x7bf/0x2af0
 ? kernel_read_file+0x19d/0x1c0
 ? SyS_finit_module+0xa5/0xe0
 ? SyS_finit_module+0xa5/0xe0
 ? entry_SYSCALL_64_fastpath+0x1e/0xa9
dax: Could not allocate 8192 bytes percpu data

mm/percpu.cpcpu_allocでコケているようなのだが(8192 byteが大きいということ?),percpu_testのkernel moduleを作ってみても以下のような感じでうまく動かず.

% sudo modprobe percpu_test
modprobe: ERROR: could not insert 'percpu_test': Resource temporarily unavailable

ということで,これ以上は追えず.とりあえずはCONFIG_DAX=mCONFIG_DAX=yにすれば解決する.

2017/07/03 12:32 / nvidia-legacy-340xx-kernel-dkms 340.102-1 on Linux 4.12

Kernel を 4.12 に上げたら nvidia-legacy-340xx-kernel-dkms の compile でコケるようになった.treewide: move set_memory_* functions away from cacheflush.hの影響でset_memory_uc()他がasm/cacheflush.hから<asm/set_memory.h>に移動した影響.

以下 nvidia-legacy-340xx-kernel-dkms 向けやるきなしなしパッチ.4.12 以前では動かない.

--- a/conftest.sh
+++ b/conftest.sh
@@ -372,6 +372,7 @@ compile_test() {
             #
             CODE="
             #include <asm/cacheflush.h>
+            #include <asm/set_memory.h>
             void conftest_set_memory_uc(void) {
                 set_memory_uc();
             }"
@@ -385,6 +386,7 @@ compile_test() {
             #
             CODE="
             #include <asm/cacheflush.h>
+            #include <asm/set_memory.h>
             void conftest_set_memory_array_uc(void) {
                 set_memory_array_uc();
             }"
@@ -398,6 +400,7 @@ compile_test() {
             #
             CODE="
             #include <asm/cacheflush.h>
+            #include <asm/set_memory.h>
             void conftest_set_pages_uc(void) {
                 set_pages_uc();
             }"
--- a/nv-linux.h
+++ b/nv-linux.h
@@ -194,6 +194,7 @@ RM_STATUS nvos_forward_error_to_cray(struct pci_dev *, NvU32,
 #if defined(NV_SET_MEMORY_UC_PRESENT)
 #undef NV_SET_PAGES_UC_PRESENT
 #undef NV_CHANGE_PAGE_ATTR_PRESENT
+#include <asm/set_memory.h>
 #elif defined(NV_SET_PAGES_UC_PRESENT)
 #undef NV_CHANGE_PAGE_ATTR_PRESENT
 #endif

Related articles

2017/06/28 11:30 / nfsroot + squashfs + overlayfs

良くあるDiskless Clientの構成法だと思われるが,あまり情報がないので自分用メモ.

ということを overlayfs で squashfs に tmpfs を overlay して実現する,という話.

ざっくりと設定手順は以下のとおり.サーバ・クライアントは Debian GNU/Linux stretch を想定.

DHCP Server の設定

isc-dhcp-server をインストールして,/etc/dhcp/dhcpd.confを以下のような感じで設定.groupを使うと記述が少なくて済む(global parameter として next-server と filename を書いても良い).

group {
  next-server 10.0.0.2;
  filename "/client/pxelinux.0";
  host megane {
    hardware ethernet xx:xx:xx:xx:xx:xx;
    fixed-address 10.0.0.71;
    option host-name "megane";
  }
  ### 他のホストの設定多数
}

10.0.0.2はTFTP ServerのIP Address,filenameでTFTPのパスを指定.

TFTP Server の設定

tftpd-hpa をインストール(tftpd は Tftpd is not suitable for use with the PXE bootloader(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=401288) とのことで PXE boot 向けではないとのこと).

/etc/default/tftpd-hpaTFTP_DIRECTORY="/srv/tftp"とあって,つまりサーバの/srv/tftpがTFTPの/になる.

PXE netboot 用のファイルを /srv/tftp/client (dhcpd.confで指定したパス)に配置する.network boot の Debian installerを細工する形で置くが簡単.

/srv/tftp/client/pxelinux.cfg/defaultに設定ファイルを置く.私の場合は以下.

default syslinux/vesamenu.c32
    prompt 0
    menu title Diskless clients
    MENU AUTOBOOT Starting the default kernel in # seconds

include syslinux/stdmenu.cfg

label Linux 4.11.7-diskless-01+
    menu label Linux 4.11.7-diskless-01+ (stretch)
    menu default
    timeout 100
    kernel boot/vmlinuz-4.11.7-diskless-01+
    append initrd=boot/initrd.img-4.11.7-diskless-01+ root=/dev/nfs nfsroot=10.0.0.2:/export/diskless,ro ip=:::::eth0:dhcp

label Linux 4.11.6-diskless-01+
    menu label Linux 4.11.6-diskless-01+ (stretch)
    kernel boot/vmlinuz-4.11.6-diskless-01+
    append initrd=boot/initrd.img-4.11.6-diskless-01+ root=/dev/nfs nfsroot=10.0.0.2:/export/diskless,ro ip=:::::eth0:dhcp

boot/は実際には/srv/tftp/client/boot/が対応し,ここに後の手順で作成する root のイメージから,vmlinuz と initrd を copy する.10.0.0.2:/export/disklessはNFSで mount する際の source.

syslinux/以下のファイルはDebian installerから流用(若干調整が必要).

NFS Server の設定

nfs-kernel-server をインストール./export/disklessがNFSでクライアントからマウント可能なように/etc/exportsを設定する.See man exportfs.

root (/) イメージ作成

debootstrap を利用する.debootstrapをインストールしておく.

sudo debootstrap --verbose --arch amd64 stretch stable http://ftp.jp.debian.org/debian/

で,stable/ 以下に root (/) のファイルが配置される.あとは

sudo chroot stable /bin/sh

stable// とみなした shell が起動するので,そこで apt-get で必要なパッケージを入れまくる(/etc以下や password 等も設定).

ただし /proc 等が存在しないので,chroot の前に以下で mount しておくのが無難.

sudo mount -t devpts devpts stable/dev/pts
sudo mount -t proc proc stable/proc
sudo mount -t binfmt_misc binfmt_misc stable/proc/sys/fs/binfmt_misc
sudo mount -t sysfs sysfs stable/sys
sudo mount -t tmpfs tmpfs stable/sys/fs/cgroup

この段階で,別途 make-kpkg でカスタム linux-image package を作成し,それを chroot 環境で dpkg -i する.kernel 再構築の際,使う NIC の Driver や NFS 等は module (m)ではなくkernelに組み込んでおく(y)必要がある.また,initrd に細工する必要があるが,これはまた後ほど.

あと,ホスト毎に処理を変えたい部分については /etc/rc.local に書いておく.ssh server の鍵をホスト毎に変えたくなる(かつ永続性も確保したい)が,これについてはたとえば以下のようなファイルを用意しておき,

[/etc/init.d/ssh-pre]
#! /bin/sh

### BEGIN INIT INFO
# Provides:             ssh-pre
# Required-Start:       $remote_fs $syslog
# Required-Stop:        $remote_fs $syslog
# X-Start-Before:       sshd
# Default-Start:        2 3 4 5
# Default-Stop:         
# Short-Description:    Prepare ssh host keys
### END INIT INFO

# `hostname` に応じてどこかから鍵を /etc/ssh/ に copy する

chroot環境でinsserv ssh-preを実行して,起動時に実行されるようにしておく.

好みの感じに仕上がった stable/ を squashfs 化する.

sudo rsync -avzL --exclude=... stable/ stable-tmp/
sudo mksquashfs stable-tmp stable.img

上のように無駄なファイルを squashfs に入れても仕方がないので rsync で一旦フィルタする.mksquashfs の -ef option でも exclude できるが,容量が大きくテストが煩雑になるので,rsync で exclude するようにした.手元の script では例えば以下のように exclude している.

     --exclude='/tmp/*'                                 \
     --exclude='/opt/*'                                 \
     --exclude='/proc/*'                                \
     --exclude='/sys/*'                                 \
     --exclude='/dev/*'                                 \
     --exclude='/var/cache/apt/archives/*'              \
     --exclude='/var/tmp/*'                             \
     --include='/var/log/*/'                            \
     --exclude='/var/log/*'                             \
     --exclude='/var/log/*/*'                           \

initrd の細工

initrd から squashfs を mount (ro)して,それに対して tmpfs (rw) を overlay して diskless client の / とする,という設定を行う.今から思えばhttps://github.com/chesty/overlayrootとほぼ同じ.

以下の2つのファイルを用意する.

[/usr/share/initramfs-tools/hooks/overlayroot]
#!/bin/sh
set -e

. /usr/share/initramfs-tools/hook-functions

manual_add_modules overlay
manual_add_modules squashfs
manual_add_modules loop

hooks/* は kernel module や initrd で必要な実行ファイルを initrd に含める設定を書く箇所.overlay や squashfs が initrd に含まれるようにする.

[/usr/share/initramfs-tools/scripts/init-bottom/overlayroot]
#!/bin/sh

if [ ! -d /root/dev ] ; then
    exit 0
fi

modprobe overlay
modprobe squashfs
modprobe loop

mkdir -p /over
mount -t tmpfs -o size=1g tmpfs /over

mkdir -p /over/rw
mkdir -p /over/ro
mkdir -p /over/sq
mkdir -p /over/work

mount -o remount,ro /root
ro=/over/ro

file=`ls /root/*.img | tail -1`
if test -f $file ; then
    mount -t squashfs $file /over/sq
    ro=/over/sq
fi

mount --move /root /over/ro

mount -t overlay -o upperdir=/over/rw,lowerdir=$ro,workdir=/over/work overlay /root

touch /root/var/log/wtmp /root/var/log/btmp /root/var/log/lastlog

mkdir -p /root/over
mount --move /over /root/over

if command -v nuke >/dev/null; then
    nuke /over
fi

scripts/init-bottom/overlayroot/usr/share/initramfs-tools/init (/init)から起動されることになるファイル.scripts/init-bottom/udev も存在すると思われるが,それより先に実行される(ファイル名で sort した順).やっていることは以下のとおり.

あとは chroot 環境で以下で initrd を作り直す.initrd は /boot/initrd*に生成される.

# update-initramfs -u -k all

NFSROOT の設置

NFS server の /export/diskless に squashfs のイメージ stable.img を置く.また,/export/diskless/dev/ 等は一時的に mount point となるので,以下を mkdir しておく(中身は空).

テスト

いちいち実機でテストするのは面倒なので同一ネットワーク内の別ホストで kvm を用いてテストすると簡便.たとえば以下(DHCP サーバに接続するため要ブリッジの設定).

% qemu-img create -f qcow2 debian.qcow 20G
% kvm -vnc :0 -hda debian.qcow -smp 8 -net bridge -net nic,model=e1000 -m 8000 &
% vncviewer :0 &

Related articles

2017/06/21 19:50 / Debian GNU/Linux stretch の NVIDIA Driver

Kernel は 4.11.6 の自前パッケージ.ドライバのソースは以下の2種類を試した.

Linux 4.11.6 + nvidia-kernel-dkms 375.66-1

嵌ったのは,以下のような2つのファイルを混同してしまう点.conftest.sh でことごとく error がでる.

/usr/src/linux-headers-4.11.6-<version>/include/asm/ をまるごと削除して解決させた.ソースコードの修正は不要.

Linux 4.11.6 + nvidia-legacy-340xx-kernel-dkms 340.102-1

手元に GeForce 8600 (古い)があって,これは最新のドライバではダメで,legacy ドライバを利用する必要がある.ということで仕方なくコンパイル.以下の対応する変更が必要.

以下パッチ.

--- a/conftest.sh
+++ b/conftest.sh
@@ -1579,6 +1579,7 @@ compile_test() {
             #
             CODE="
             #include <linux/sched.h>
+            #include <linux/sched/signal.h>
             void conftest_fatal_signal_pending(void) {
                 fatal_signal_pending();
             }"
--- a/nv-drm.c
+++ b/nv-drm.c
@@ -48,7 +48,7 @@ static int nv_drm_load(
     return -ENODEV;
 }
 
-static int nv_drm_unload(
+static void nv_drm_unload(
     struct drm_device *dev
 )
 {
@@ -64,7 +64,7 @@ static int nv_drm_unload(
         }
     }
 
-    return -ENODEV;
+    return;
 }
 
 static void nv_gem_free(
diff --git a/uvm/nvidia_uvm_linux.h b/uvm/nvidia_uvm_linux.h
index f69c107..3d21a47 100644
--- a/uvm/nvidia_uvm_linux.h
+++ b/uvm/nvidia_uvm_linux.h
@@ -189,6 +189,9 @@
 #include <linux/ratelimit.h>
 #endif
 
+#include <linux/signal.h>
+#include <linux/sched/signal.h>
+
 #if !defined(no_printk)
 //
 // TODO: bug 1329255: instead of this heavy-handed approach, use conftest to
diff --git a/uvm/nvidia_uvm_lite.c b/uvm/nvidia_uvm_lite.c
index 71bebe3..3685dc6 100644
--- a/uvm/nvidia_uvm_lite.c
+++ b/uvm/nvidia_uvm_lite.c
@@ -818,7 +818,7 @@ done:
 }
 
 #if defined(NV_VM_OPERATIONS_STRUCT_HAS_FAULT)
-int _fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+int _fault(struct vm_fault *vmf)
 {
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0)
     unsigned long vaddr = (unsigned long)vmf->virtual_address;
@@ -828,7 +828,7 @@ int _fault(struct vm_area_struct *vma, struct vm_fault *vmf)
     struct page *page = NULL;
     int retval;
 
-    retval = _fault_common(vma, vaddr, &page, vmf->flags);
+    retval = _fault_common(vmf->vma, vaddr, &page, vmf->flags);
 
     vmf->page = page;
 
@@ -866,7 +866,7 @@ static struct vm_operations_struct uvmlite_vma_ops =
 // it's dealing with anonymous mapping (see handle_pte_fault).
 //
 #if defined(NV_VM_OPERATIONS_STRUCT_HAS_FAULT)
-int _sigbus_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+int _sigbus_fault(struct vm_fault *vmf)
 {
     vmf->page = NULL;
     return VM_FAULT_SIGBUS;

Related articles