LINUX.ORG.RU

Ошибка: BUG: scheduling while atomic:


0

1

Проблема появляется при вызове функции wait_event_interruptible() в доморощенной функции read_wbuffs() при работе с tcp протоколом. Передача идет по защищенному каналу ipsec.
Функция wait_event_interruptible() используется для синхронизации с приемным буфером.

static ssize_t read_wbuffs(char *buf, size_t count,  int fuser)
{
    int flags;
    printk(KERN_INFO "======myrnd_read================\n");
    if(!atomic_read(&(buff_data.buff_full)))
    {
        printk(KERN_ERR "sizeBuf empty wait\n");
        if(wait_event_interruptible(buff_data.waitQueue,atomic_read(& (buff_data.rsrc))))
        {
            atomic_set(&(buff_data.rsrc),0);
            return -ERESTARTSYS; // signal (tell to handle it)
        }
        atomic_set(&(buff_data.rsrc),0);
    }
    memcpy(buf, data_wbuf, count);
    atomic_set(&(buff_data.buff_full),0);
    atomic_set(&(buff_data.wsrc),1);
    wake_up_interruptible_all(&(buff_data.waitQueue));
    wake_up_interruptible(&msk_sleep);
    return count;
}

Проявляется при работе с tcp протоколом, с udp всё ок!
На передающей стороне (проблемная) запускаю команду:
#nc -q1 10.1.101.125 6789 < ./text_out (стек вызовов tcp см. ниже), которая по протоколу tcp передает файл text_out
на приемной стороне, команда записывает его в файл text_in:
#nc -l -p 6789 > ./text_in
С udp:
#nc -u -q1 10.1.101.125 6789 < ./text_out (стек вызовов udp см. ниже).
#nc -u -l -p 6789 > ./text_in

[  124.220724] Call Trace:
[  124.217139] ===========myrnd_read========================
[  124.217143] sizeBuf empty wait
[  124.218839] BUG: scheduling while atomic: nc/2271/0x00000200
[  124.220640] Modules linked in: my myiv myrndm loop snd_hda_codec_realtek snd_hda_intel snd_hda_codec i915 drm_kms_helper snd_hwdep drm snd_pcm snd_timer i2c_algo_bit i2c_i801 psmouse snd parport_pc evdev i2c_core serio_raw pcspkr parport soundcore rng_core video button processor snd_page_alloc output ext3 jbd mbcache sd_mod crc_t10dif ata_generic 8139too r8169 uhci_hcd ata_piix 8139cp ehci_hcd thermal mii libata scsi_mod usbcore nls_base thermal_sys [last unloaded: scsi_wait_scan]
[  124.220719] Pid: 2271, comm: nc Not tainted 2.6.32-debug #2
[  124.220724] Call Trace:
[  124.220737]  [<c102ab3a>] ? printk+0x18/0x1a
[  124.220746]  [<c1023492>] __schedule_bug+0x58/0x5e
[  124.220755]  [<c12c4559>] schedule+0x44/0x3f4
[  124.220766]  [<f80fe2ca>] read_wbuffs+0x8b/0x11b [myrndm]
[  124.220775]  [<c104045d>] ? autoremove_wake_function+0x0/0x3d
[  124.220784]  [<f80fe3b8>] my_rndg+0x2a/0x34 [myrndm]
[  124.220793]  [<f81d11fc>] myiv_aead_givencrypt+0xe0/0x139 [myiv]
[  124.220803]  [<c1267c33>] esp_output+0x2a1/0x2db
[  124.220812]  [<c127587c>] xfrm_output_resume+0x249/0x2d6
[  124.220822]  [<c1220f91>] ? sch_direct_xmit+0x45/0x12c
[  124.220830]  [<c1275916>] xfrm_output2+0xd/0xf
[  124.220837]  [<c12759bc>] xfrm_output+0xa4/0xb8
[  124.220845]  [<c126c7f0>] xfrm4_output_finish+0x24/0x26
[  124.220852]  [<c126c8ef>] xfrm4_output+0x59/0x6a
[  124.220859]  [<c126f8c5>] ? xfrm_dst_check+0x12/0x28
[  124.220867]  [<c12347fb>] ip_local_out+0x18/0x1b
[  124.220874]  [<c1234a83>] ip_queue_xmit+0x285/0x2fb
[  124.220883]  [<c10b68d2>] ? __slab_free+0x4d/0x20b
[  124.220892]  [<c1231877>] ? ip_local_deliver+0x78/0x7e
[  124.220900]  [<c1248b5b>] ? tcp_v4_md5_lookup+0xe/0x10
[  124.220909]  [<c124641f>] tcp_transmit_skb+0x5a8/0x5e8
[  124.220917]  [<c1246f61>] tcp_write_xmit+0x73c/0x81b
[  124.220926]  [<c12470a6>] __tcp_push_pending_frames+0x30/0x81
[  124.220934]  [<c12447ee>] tcp_rcv_established+0xe6/0x660
[  124.220943]  [<c124a842>] tcp_v4_do_rcv+0x154/0x2e5
[  124.220953]  [<c1202ae3>] release_sock+0x3a/0x99
[  124.220960]  [<c123c6f4>] tcp_sendmsg+0x85b/0x923
[  124.220969]  [<c1146fd8>] ? __generic_unplug_device+0x26/0x29
[  124.220979]  [<c101c472>] ? kmap_atomic_prot+0xa8/0xc8
[  124.220988]  [<c11ffe9d>] sock_aio_write+0xfc/0x10b
[  124.220996]  [<c10bb0f1>] do_sync_write+0xaf/0xeb
[  124.221004]  [<c12012d1>] ? sys_connect+0x88/0xc3
[  124.221013]  [<c1047664>] ? ktime_get+0x6b/0xdf
[  124.221021]  [<c104045d>] ? autoremove_wake_function+0x0/0x3d
[  124.221029]  [<c11136b0>] ? security_file_permission+0xf/0x11
[  124.221037]  [<c10bb412>] ? rw_verify_area+0xb0/0xe4
[  124.221044]  [<c10bb6ef>] vfs_write+0xa0/0x174
[  124.221052]  [<c10bb9d2>] sys_write+0x38/0x63
[  124.221060]  [<c100343b>] sysenter_do_call+0x12/0x28

Стек вызовов для UDP:

sys_write
vfs_write
do_sync_write 
sock_aio_write
do_sock_write
__sock_sendmsg
inet_sendmsg
udp_sendmsg
release_sock
udp_push_pending_frames
ip_push_pending_frames
ip_local_out 
dst_output
xfrm4_output
xfrm4_output_finish
xfrm_output
xfrm_output2
xfrm_output_one
esp_output
myiv_aead_givencrypt
my_rndg
read_wbuffs
Стек для TCP:
sys_write
vfs_write
do_sync_write 
sock_aio_write
do_sock_write
__sock_sendmsg
tcp_sendmsg
release_sock
__release_sock
sk_backlog_rcv
tcp_v4_do_rcv 
tcp_rcv_established
tcp_data_snd_check
tcp_push_pending_frames
_tcp_push_pending_frames
tcp_write_xmit
tcp_transmit_skb
ip_queue_xmit
ip_local_out
dst_output
xfrm4_output
xfrm4_output_finish
xfrm_output
xfrm_output2
xfrm_output_resume
xfrm_output_one
esp_output
myiv_aead_givencrypt
my_rndg
read_wbuff
В чём может быть проблема, bug в tcp, не освобождается где-то блокировка в tcp? Или другое?

«Scheduling while atomic» indicates that you've tried to sleep somewhere that you shouldn't - like within a spinlock-protected critical section or an interrupt handler.

алсо, телепаты в отпуске. ну ты понел

ckotinko ☆☆☆
()

фигасе ведро сложное, 30 уровней вызовов функций

Harald ★★★★★
()
Ответ на: комментарий от oliva13

а вообще, просто пропатч preempt_disable чтоб оно в per_cpu переменную сохраняло адрес стека. и дампь эту переменную. там и будет написано кто отключил музыку

ckotinko ☆☆☆
()

Мой магический кристалл говорит мне, что ты обращаешься к пользовательской памяти из обработчика прерывания.

tailgunner ★★★★★
()
Ответ на: комментарий от ckotinko
struct wpipe 
{
   wait_queue_head_t waitQueue;
   atomic_t wsrc;
   atomic_t rsrc;
   atomic_t buff_full;
};

struct wpipe buff_data;
#define NTBLOCK_SIZE  4
char    data_wbuf[NTBLOCK_SIZE];

void winit(struct wpipe *dev)
{
   atomic_set(&(dev->wsrc), 0);
   atomic_set(&(dev->rsrc), 0);
   atomic_set(&(dev->buff_full), 0);
   init_waitqueue_head(&(dev->waitQueue));
}

int myrnd_init(void)
{
   int ret = 0;
   ............................
   winit(&buff_data);
   return ret;
}
oliva13
() автор топика
Ответ на: комментарий от oliva13

создай тупо percpu void * и туда забубень адрес последнего вызыватора прямо в функции. он доступен через gcc шную __builtin-функцию

как упадет, сразу смотри, кто вызывал preempt_disable. в ней будет его адрес сидеть

ckotinko ☆☆☆
()

Нельзя спать в ip_queue_xmit. Тело этой функции защищено критической секцией RCU. См. rcu_read_lock/rcu_read_unlock

nocomer
()

Ты вызываешь wait_event_interruptible, когда нельзя спать.

Текст myiv_aead_givencryp и my_rndg — в студию

ttnl ★★★★★
()
Ответ на: комментарий от ttnl
static int myiv_aead_givencrypt(struct aead_givcrypt_request *req)
{
	struct crypto_aead *geniv = aead_givcrypt_reqtfm(req);
	struct myiv_ctx *ctx = crypto_aead_ctx(geniv);
	struct aead_request *areq = &req->areq;
	struct aead_request *subreq = aead_givcrypt_reqctx(req);
	crypto_completion_t complete;
	int i = 0;
	void *data;
	u8 *info, *pre_info;
	unsigned int ivsize;
	int err = 0;
	printk (KERN_INFO "\nmyiv_aead_givencrypt\n");

	aead_request_set_tfm(subreq, aead_geniv_base(geniv));
	
	complete = areq->base.complete;
	data = areq->base.data;
	info = areq->iv;

	ivsize = crypto_aead_ivsize(geniv);

	if (unlikely(!IS_ALIGNED((unsigned long)info, crypto_aead_alignmask(geniv) + 1))) 
	{
		info = kmalloc(ivsize, GFP_KERNEL);
//		areq->base.flags &
//							   CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
//							   GFP_ATOMIC);
		if (!info)
			return -ENOMEM;

		complete = myiv_aead_complete;
		data = req;
	}

	aead_request_set_callback(subreq, areq->base.flags, complete, data);
	aead_request_set_crypt(subreq, areq->src, areq->dst, areq->cryptlen, info);
	aead_request_set_assoc(subreq, areq->assoc, areq->assoclen);

//    Work!!! 
//	strcpy(info, "myiv");

	memset(swbuf, 0, ivsize);

	my_rndg(swbuf, ivsize);
	
	memcpy(info, swbuf, ivsize);
	
	spin_lock_bh(&ctx->lock);
	
	memcpy(req->giv, info, ivsize);

	spin_unlock_bh(&ctx->lock);
	
	err = crypto_aead_encrypt(subreq);

	if (unlikely(info != areq->iv))
		myiv_aead_complete2(req, err);
	
	return err;
}
oliva13
() автор топика
Ответ на: комментарий от ttnl
int my_rndg(char *buf, size_t count)
{
   int res = 0;
   printk(KERN_INFO "************my_rndg**********\n");
   res = read_wbuffs(buf, count, KERNEL_SPACE);
   return res;
}	
oliva13
() автор топика
Ответ на: комментарий от oliva13

Не знаю. Не разбираюсь в реализации Ipsec.

Посмотрите, может, можно возвращать -EINPROGRESS, если приходится спать.

А лучше спросите у кого-нибудь другого.

nocomer
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.