1. [35088.250898] Call Trace:
  2. [35088.255869] [<8101883c>] show_stack+0x54/0x88
  3. [35088.264678] [<811e3dfc>] dump_stack+0x94/0xcc
  4. [35088.273469] [<810b0dc4>] warn_alloc_failed+0xf8/0x11c
  5. [35088.283646] [<810b3780>] __alloc_pages_nodemask+0x750/0x84c
  6. [35088.294884] [<810218d0>] mips_dma_alloc_coherent+0x168/0x20c
  7. [35088.306291] [<812b0738>] mtk_open+0x4d8/0x55c
  8. [35088.315069] [<812f9c0c>] __dev_open+0xd4/0x154
  9. [35088.324036] [<812f9f3c>] __dev_change_flags+0xc0/0x17c
  10. [35088.334373] [<812fa020>] dev_change_flags+0x28/0x70
  11. [35088.344200] [<81310e10>] dev_ifsioc+0xf8/0x33c
  12. [35088.353155] [<81311528>] dev_ioctl+0x4d4/0x5e4
  13. [35088.362117] [<810fd580>] do_vfs_ioctl+0x5d4/0x63c
  14. [35088.371590] [<810fd638>] SyS_ioctl+0x50/0x94
  15. [35088.380208] [<810078d8>] syscall_common+0x30/0x54

问题原因

首先抛出问题原因:
这个宕机,是由于ifconfig up过程中,没有能够申请到连续的内存导致的

ifconfig的调用过程

ifconig up和ifconfig down调用的函数如下

  1. static int set_if_up(char *ifname, short flags)
  2. {
  3. return set_if_flags(ifname ,flags | IFF_UP);
  4. }
  5. static int set_if_down(char *ifname, short flags)
  6. {
  7. return set_if_flags(ifname ,flags & ~IFF_UP);
  8. }

其实up和down都是执行了set_if_flags

  1. static int set_if_flags(char *ifname, short flags)
  2. {
  3. struct ifreq ifr;
  4. int res = 0;
  5. ifr.ifr_flags = flags;
  6. strncpy(ifr.ifr_name, ifname, IFNAMSIZ); //ifr.ifr_name="eth0"
  7. res = ioctl(skfd, SIOCSIFFLAGS, &ifr); //通过ioctl()向内核socket传递命令SIOCSIFFLAGS和ifr变量
  8. if (res < 0) {
  9. saved_errno = errno;
  10. v_print("Interface '%s': Error: SIOCSIFFLAGS failed: %s\n",
  11. ifname, strerror(saved_errno));
  12. } else {
  13. v_print("Interface '%s': flags set to %04X.\n", ifname, flags);
  14. }
  15. return res;
  16. }

SIOCSIFFLAGS是干嘛的?

  1. int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
  2. {
  3. struct ifreq ifr;
  4. int ret;
  5. char *colon;
  6. //… …
  7. switch (cmd) {
  8. //… …
  9. case SIOCSIFFLAGS: //设置标志,比如ifconfig up/down
  10. case SIOCSIFMETRIC:
  11. case SIOCSIFMTU: //设置MUT长度
  12. case SIOCSIFHWADDR: //设置mac物理地址
  13. //… …
  14. dev_load(net, ifr.ifr_name); //通过ifr.ifr_name(eth0)名字来加载网卡
  15. rtnl_lock(); //对net_device进行加锁,避免与运行冲突
  16. ret = dev_ifsioc(net, &ifr, cmd); //最终调用该函数
  17. rtnl_unlock();
  18. return ret;
  19. }

dev_ioctl会调用dev_ifsioc->dev_change_flags->dev_chang_flags->然后根据IFF_UP标志位,判断调用dev_open还是__dev_close;

现在面临的问题:

  1. [35088.250898] Call Trace:
  2. [35088.255869] [<8101883c>] show_stack+0x54/0x88
  3. [35088.264678] [<811e3dfc>] dump_stack+0x94/0xcc
  4. [35088.273469] [<810b0dc4>] warn_alloc_failed+0xf8/0x11c
  5. [35088.283646] [<810b3780>] __alloc_pages_nodemask+0x750/0x84c
  6. [35088.294884] [<810218d0>] mips_dma_alloc_coherent+0x168/0x20c
  7. [35088.306291] [<812b0738>] mtk_open+0x4d8/0x55c
  8. [35088.315069] [<812f9c0c>] __dev_open+0xd4/0x154
  9. [35088.324036] [<812f9f3c>] __dev_change_flags+0xc0/0x17c
  10. [35088.334373] [<812fa020>] dev_change_flags+0x28/0x70
  11. [35088.344200] [<81310e10>] dev_ifsioc+0xf8/0x33c
  12. [35088.353155] [<81311528>] dev_ioctl+0x4d4/0x5e4
  13. [35088.362117] [<810fd580>] do_vfs_ioctl+0x5d4/0x63c
  14. [35088.371590] [<810fd638>] SyS_ioctl+0x50/0x94
  15. [35088.380208] [<810078d8>] syscall_common+0x30/0x54

这里在粘贴一遍call trace方便观看..
call trace展示的调用过程是从下到上的,dev_open这条调用之前的调用linux系统大致都一样,但是dev_open上面的,就和具体网卡有关系了
现在的症结在于,mtk的驱动打开interface的时候,由于没有申请到连续的内存空间而失败 warn_alloc_failed