net_device構造体のAPIが消えていた | Inhale n’ Exhale仕事で開発している組み込み機器の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()
をラップする関数を追加して解決。
1 | static const struct net_device_stats *compat_get_stats( struct net_device *dev) |
3 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) |
4 | return dev->get_stats ? dev->get_stats(dev) : NULL; |
6 | return dev_get_stats(dev); |
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
に行き着いた。
1 | @@ -1055,8 +1062,8 @@ static int wireless_process_ioctl(struct net *net, struct |
2 | return private(dev, iwr, cmd, info, handler); |
4 | /* Old driver API : call driver ioctl handler */ |
7 | + if (dev->netdev_ops->ndo_do_ioctl) |
8 | + return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); |
get_stats()
と同様に、do_ioctl()
をラップする関数を追加して解決。
1 | static int compat_do_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd) |
3 | #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) |
4 | return dev->do_ioctl(dev, ifr, cmd); |
6 | return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd); |