読者です 読者をやめる 読者になる 読者になる

linuxのbugzillaを見てて調べてみたバグ報告。

linux

2.6.29.1で/proc/sys/kernel/pid_maxに40000とかを書き込むとエラーになって書き込めないというバグ報告。
返信のコメントではx86_64では問題ないとあったので、メインのx86_64とeeepcの両方で試してみた。
試したカーネルは、x86が2.6.26、2.6.29、2.6.30-rc2+α、x86_64が2.6.29と2.6.30-rc2+α。.26と.29はDebianカーネル
結果的にはx86_64は問題なくてx86はダメ。x86で設定できる最大値は32768だった。
printkを入れて調べてみたらkernel/sysctl.cにある__do_proc_dointvec()ないの以下の文で0以外の値が返ってきているのが根本的な理由っぽい。

                        if (conv(&neg, &lval, i, 1, data))
                                break;

このconv()は関数ポインタでproc_dointvec_minmax()がdo_proc_dointvec()を呼ぶときにdo_proc_dointvec_minmax_conv()を指定。
ようは入力された値が、最小値 <= x <= 最大値かを調べて結果を返す関数。

kernel/sysctl.cでは、読み書き時に呼ばれる関数とか最小・最大値などを設定してる。

.ctl_name       = KERN_PIDMAX,
.procname       = "pid_max",
.data           = &pid_max,
.maxlen         = sizeof (int),
.mode           = 0644,
.proc_handler   = &proc_dointvec_minmax,
.strategy       = sysctl_intvec,
.extra1         = &pid_max_min,
.extra2         = &pid_max_max,

pid_max_maxが最大値っぽいので、これを追ってみるとこの値はkernel/pid.cで定義。

int pid_max_max = PID_MAX_LIMIT;

んで、PID_MAX_LIMITはどこにあるかというとlinux/threads.hにあって

#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)

#define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
        (sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))

CONFIG_BASE_SMALLはカーネルコンフィグファイルにあるよ。
Debianの(それ以外も?)デフォルトだと0だった。コンフィグメニューのどっかに設定する箇所はあると思うけど、
どこにあるのかは調べてない・・
PID_MAX_LIMITはCONFIG_BASE_SMALL==0ならPID_MAX_DEFAULTを使って、CONFIG_BASE_SMALLは0なので、0x8000がpid_maxの最大値。
0x8000は10進で32768なので、pid_maxに40000とかを書けなかったということっぽい(´ー`)y-~~