1月 132012
仕事で開発している組み込み機器のLinuxカーネルを、2.6.27系から2.6.32系にアップデートするために、久々にカーネルの再構築なんかやってて、ネットワークデバイスのリンク状態を監視するために自作したLKMがあったので、2.6.27.xで使っていたものをそのまま2.6.32.xにコピーしてコンパイルしたら通らなかったorz
error: ‘struct net_device’ has no member named ‘get_stats’ error: ‘struct net_device’ has no member named ‘do_ioctl’
net_device
構造体からget_stats()
とdo_ioctl()
がなくなったようだ。
とりあえず、どのバージョンでカーネルAPIが変更されたのかを確認するために、git.kernel.orgからソースツリーをダウンロードしておく。
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
net_device
構造体はinclude/linux/netdevice.h
で定義されているので、git diff
を見ながらget_stats()
とdo_ioctl()
が消えたブランチを探していく。
$ cd linux-stable/include/linux $ git diff v2.6.27.59 v2.6.32.1 netdevice.h $ git diff v2.6.27.59 v2.6.31.1 netdevice.h $ git diff v2.6.27.59 v2.6.30.1 netdevice.h
どうやらv2.6.27系からv2.6.30系に移るときに消えたようだ。
get_stats()
に関してはdev_get_stats()
というグローバル関数に置き換わったらしく、netdev: Introduce dev_get_stats()
というコミットログが見つかった。
v2.6.27系との互換性を保つため、get_stats()
をラップする関数を追加して解決。
static const struct net_device_stats *compat_get_stats(struct net_device *dev) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) return dev->get_stats ? dev->get_stats(dev) : NULL; #else return dev_get_stats(dev); #endif }
do_ioctl()
は、v2.6.30から登場したnet_device_ops
構造体にあるndo_do_ioctl()
が代替APIのように思える。カーネルソースツリーをgrep
して、v2.6.27系でdo_ioctl()
を使っていたモジュールがv2.6.30系でどう修正されたか探したら、net/wireless/wext.c
に行き着いた。
@@ -1055,8 +1062,8 @@ static int wireless_process_ioctl(struct net *net, struct return private(dev, iwr, cmd, info, handler); } /* Old driver API : call driver ioctl handler */ - if (dev->do_ioctl) - return dev->do_ioctl(dev, ifr, cmd); + if (dev->netdev_ops->ndo_do_ioctl) + return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); return -EOPNOTSUPP; }
get_stats()
と同様に、do_ioctl()
をラップする関数を追加して解決。
static int compat_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) return dev->do_ioctl(dev, ifr, cmd); #else return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); #endif }