免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 14399 | 回复: 8
打印 上一主题 下一主题

请教 scheduling while atomic [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-19 18:14 |只看该作者 |倒序浏览
我在下面的vmdk_transfer中进行IO操作 可是出现scheduling while atomic ,下面是主要的代码,还有系统打出来的log
我觉得问题出在这里:
bio_for_each_segment(bvec, bio, i) {
                char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);
                vmdk_transfer(dev, sector, bio_cur_sectors(bio),
                                buffer, bio_data_dir(bio) == WRITE);//4.我想问的是这里不能引发调度么?
                sector += bio_cur_sectors(bio);
                __bio_kunmap_atomic(bio, KM_USER0);
难道上面__bio_kmap_atomic和__bio_kunmap_atomic不允许调度么?
还是bio_for_each_segment 不允许调度呢 还是问题不出在这里 ?

static void vmdk_transfer(struct vmdk_dev *dev, unsigned long sector,
                unsigned long nsect, char *buffer, int write)

{
        unsigned long offset = sector*KERNEL_SECTOR_SIZE;
        unsigned long nbytes = nsect*KERNEL_SECTOR_SIZE;
        struct file *f = dev->fvmdk;
        mm_segment_t old_fs;
        if ((offset + nbytes) > dev->size) {
                printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
                return;
        }
       
        old_fs = get_fs();
        set_fs(KERNEL_DS);
       
        if (write){
                f->f_pos = offset;
                f->f_op->write(f, buffer, nbytes, &f->f_pos);
        }
        else{
                f->f_pos = offset;
                f->f_op->read(f, buffer, nbytes, &f->f_pos);//3.但是在这里会出现 schedule while atomic
        }
               
        set_fs(old_fs);
}
static int vmdk_handle_bio(struct vmdk_dev *dev, struct bio *bio)
{
        int i;
        struct bio_vec *bvec;
        sector_t sector = bio->bi_sector;

        /* Do each segment independently. */
        bio_for_each_segment(bvec, bio, i) {
                char *buffer = __bio_kmap_atomic(bio, i, KM_USER0);
                vmdk_transfer(dev, sector, bio_cur_sectors(bio),
                                buffer, bio_data_dir(bio) == WRITE);//4.我想问的是这里不能引发调度么?
                sector += bio_cur_sectors(bio);
                __bio_kunmap_atomic(bio, KM_USER0);
        }
        return 0;
}

static int vmdk_rw_thread(void *data) //1. 这里是开启的一个内核线程 使用kthread_create创建的
{
        struct vmdk_dev *dev = data;
        struct bio *bio;
        int status;

        set_user_nice(current, -20);
        while (!kthread_should_stop() || !bio_list_empty(&dev->vmdk_bio_list)) {
                wait_event_interruptible(dev->vmdk_event,
                                !bio_list_empty(&dev->vmdk_bio_list) ||
                                kthread_should_stop());
                if (bio_list_empty(&dev->vmdk_bio_list))
                        continue;
                spin_lock_irq(&dev->vmdk_lock);
                bio = vmdk_get_bio(dev);
                spin_unlock_irq(&dev->vmdk_lock);

                BUG_ON(!bio);
                status = vmdk_handle_bio(dev, bio); //2.在这里进行io操作
                bio_endio(bio, status);
        }
        return 0;
}



log:
[ 2895.303346]  vmdka: vmdka1
[ 2895.405414] BUG: scheduling while atomic: vmdk0/7293/0x10000001
[ 2895.405425] Modules linked in: vmdk_1 isofs udf crc_itu_t binfmt_misc bridge stp bnep video output input_polldev nfsd auth_rpcgss exportfs nfs lockd nfs_acl sunrpc lp ppdev snd_ens1371 gameport snd_ac97_codec ac97_bus snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device psmouse serio_raw snd pcspkr soundcore snd_page_alloc i2c_piix4 parport_pc parport intel_agp shpchp agpgart pcnet32 mii mptspi mptscsih mptbase scsi_transport_spi floppy fbcon tileblit font bitblit softcursor [last unloaded: vmdk_1]
[ 2895.405580] Pid: 7293, comm: vmdk0 Not tainted 2.6.28-11-generic #42-Ubuntu
[ 2895.405590] Call Trace:
[ 2895.405614]  [<c0500ac6>] ? printk+0x18/0x1a
[ 2895.405637]  [<c012f991>] __schedule_bug+0x61/0x70
[ 2895.405648]  [<c050115d>] schedule+0x52d/0x710
[ 2895.405654]  [<c0127c8d>] ? update_curr+0x8d/0x1e0
[ 2895.405659]  [<c0132f4b>] __cond_resched+0x1b/0x40
[ 2895.405664]  [<c0501415>] _cond_resched+0x35/0x50
[ 2895.405675]  [<c018feac>] do_generic_file_read+0x8c/0x4c0
[ 2895.405682]  [<c0190383>] generic_file_aio_read+0xa3/0x210
[ 2895.405690]  [<c018e4b0>] ? file_read_actor+0x0/0xe0
[ 2895.405696]  [<c01bd531>] do_sync_read+0xd1/0x110
[ 2895.405701]  [<c0128ea0>] ? __wake_up_common+0x40/0x70
[ 2895.405708]  [<c014ecb0>] ? autoremove_wake_function+0x0/0x50
[ 2895.405713]  [<c0191147>] ? mempool_free+0x77/0x80
[ 2895.405722]  [<c01e254d>] ? bio_free+0x3d/0x50
[ 2895.405727]  [<c0127453>] ? kmap_atomic_prot+0x43/0xe0
[ 2895.405732]  [<c01e0de3>] ? bio_put+0x33/0x50
[ 2895.405740]  [<d9b26343>] vmdk_rw_thread+0x1e3/0x2e0 [vmdk_1]
[ 2895.405745]  [<c050104a>] ? schedule+0x41a/0x710
[ 2895.405750]  [<c014ecb0>] ? autoremove_wake_function+0x0/0x50
[ 2895.405756]  [<d9b26160>] ? vmdk_rw_thread+0x0/0x2e0 [vmdk_1]
[ 2895.405760]  [<c014e90c>] kthread+0x3c/0x70
[ 2895.405765]  [<c014e8d0>] ? kthread+0x0/0x70
[ 2895.405771]  [<c0105477>] kernel_thread_helper+0x7/0x10
[ 2895.448450] BUG: scheduling while atomic: vmdk0/7293/0x10000001
[ 2895.448460] Modules linked in: vmdk_1 isofs udf crc_itu_t binfmt_misc bridge stp bnep video output input_polldev nfsd auth_rpcgss exportfs nfs lockd nfs_acl sunrpc lp ppdev snd_ens1371 gameport snd_ac97_codec ac97_bus snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy snd_seq_oss snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device psmouse serio_raw snd pcspkr soundcore snd_page_alloc i2c_piix4 parport_pc parport intel_agp shpchp agpgart pcnet32 mii mptspi mptscsih mptbase scsi_transport_spi floppy fbcon tileblit font bitblit softcursor [last unloaded: vmdk_1]
[ 2895.448532] Pid: 7293, comm: vmdk0 Not tainted 2.6.28-11-generic #42-Ubuntu
[ 2895.448535] Call Trace:
[ 2895.448549]  [<c0500ac6>] ? printk+0x18/0x1a
[ 2895.448559]  [<c012f991>] __schedule_bug+0x61/0x70
[ 2895.448565]  [<c050115d>] schedule+0x52d/0x710
[ 2895.448571]  [<c0127c8d>] ? update_curr+0x8d/0x1e0
[ 2895.448576]  [<c0132f4b>] __cond_resched+0x1b/0x40
[ 2895.448581]  [<c0501415>] _cond_resched+0x35/0x50
[ 2895.448587]  [<c018feac>] do_generic_file_read+0x8c/0x4c0
[ 2895.448593]  [<c0190383>] generic_file_aio_read+0xa3/0x210
[ 2895.448601]  [<c018e4b0>] ? file_read_actor+0x0/0xe0
[ 2895.448607]  [<c01bd531>] do_sync_read+0xd1/0x110
[ 2895.448615]  [<c014ecb0>] ? autoremove_wake_function+0x0/0x50
[ 2895.448620]  [<c0191147>] ? mempool_free+0x77/0x80
[ 2895.448627]  [<c01e254d>] ? bio_free+0x3d/0x50
[ 2895.448632]  [<c0127453>] ? kmap_atomic_prot+0x43/0xe0
[ 2895.448637]  [<c01e0de3>] ? bio_put+0x33/0x50
[ 2895.448645]  [<d9b26343>] vmdk_rw_thread+0x1e3/0x2e0 [vmdk_1]
[ 2895.448650]  [<c050104a>] ? schedule+0x41a/0x710
[ 2895.448656]  [<c014ecb0>] ? autoremove_wake_function+0x0/0x50
[ 2895.448662]  [<d9b26160>] ? vmdk_rw_thread+0x0/0x2e0 [vmdk_1]
[ 2895.448667]  [<c014e90c>] kthread+0x3c/0x70
[ 2895.448672]  [<c014e8d0>] ? kthread+0x0/0x70
[ 2895.448678]  [<c0105477>] kernel_thread_helper+0x7/0x10

论坛徽章:
0
2 [报告]
发表于 2010-01-20 08:41 |只看该作者

UP 一下

在ldd3的内存映射一章中又这样一段话:
“kmap_atomic是kmap的高性能版本。要注意的是原子的kmap必须被原子地处理,也就是说在拥有它的时候,代码不能进入睡眠状态。
但是在实际情况中,对原子的kmap的争夺并不会引起什么问题。”
中间省略了几个字   不知这样是不是说上面的代码那样写不会出问题呢  我在两台电脑上测试 都能正常运行

为什么没有人回答呢

论坛徽章:
0
3 [报告]
发表于 2010-01-20 16:41 |只看该作者
可能不在这一层,你还锝深入跟踪一下。

肯定有引起调度的。

逐步的注释掉一些试试

论坛徽章:
0
4 [报告]
发表于 2010-01-21 08:34 |只看该作者

回复 #3 emmoblin 的帖子

不太明白 你是说在kmap_atomic和kunmap_atomic之间可以进行调度而我遇到的问题不出在这里?是我程序中其它地方的问题?

但是我把kmap_atomic改为kmap后 加载驱动就不会出现上面的bug了。
但是这样修改会不会对内核运行的效率产生不好的影响。
上面的在内核中是这样定义的
#define __bio_kmap_atomic(bio, idx, kmtype)                                \
        (kmap_atomic(bio_iovec_idx((bio), (idx))->bv_page, kmtype) +        \
                bio_iovec_idx((bio), (idx))->bv_offset)
#define __bio_kunmap_atomic(addr, kmtype) kunmap_atomic(addr, kmtype)

论坛徽章:
0
5 [报告]
发表于 2010-01-21 09:36 |只看该作者
原帖由 1226ehziy 于 2010-1-21 08:34 发表
不太明白 你是说在kmap_atomic和kunmap_atomic之间可以进行调度而我遇到的问题不出在这里?是我程序中其它地方的问题?

但是我把kmap_atomic改为kmap后 加载驱动就不会出现上面的bug了。
但是这样修改会不会 ...


顾名思义,kmap_atomic和kunmap_atmoic之间是不允许调度的,而f_op->read()是有可能引起调度的。一旦发生调度的话就可能发生问题:
scheduling while atomic有几种case,比如:
1. 如果你抓了一把spinlock,然后被调度出去了,就可能会引起死锁的问题。
2. 就kmap_atomic和kunmap_atomic之间,不允许被调度出去,防止别的process也去调用kmap_atomic,如果交叉调用的话,就会出现问题了。

kernel打出warning只是提醒你,这样做可能会有问题,但是问题不一定现在就会发生。。。

[ 本帖最后由 eexplorer 于 2010-1-21 09:38 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2010-01-22 08:40 |只看该作者

回复 #5 eexplorer 的帖子

但是《深入理解linux内核》上说kmap_atomic 会禁止内核抢占。

论坛徽章:
0
7 [报告]
发表于 2010-01-22 09:44 |只看该作者
原帖由 1226ehziy 于 2010-1-22 08:40 发表
但是《深入理解linux内核》上说kmap_atomic 会禁止内核抢占。


禁止内核抢占是指内核不会主动的抢占你的process,但是现在是你在自己的程序中主动call schedule(),kernel并不能阻止你这么作。

论坛徽章:
0
8 [报告]
发表于 2010-01-22 10:57 |只看该作者
原帖由 eexplorer 于 2010-1-21 09:36 发表

顾名思义,kmap_atomic和kunmap_atmoic之间是不允许调度的,而f_op->read()是有可能引起调度的。一旦发生调度的话就可能发生问题:
scheduling while atomic有几种case,比如:
1. 如果你抓了一把spinloc ...


每次看eexplorer兄的发言都会有所收获,

论坛徽章:
0
9 [报告]
发表于 2010-01-22 12:12 |只看该作者

回复 #7 eexplorer 的帖子

thanks  我把改为kmap和kunmap就没有bug提示了
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP