仕事で開発している組み込み機器の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
}