2013-03-16 3 views
1

I/O 요청이 별도의 작업자 스레드로 넘겨지는 방식으로 블록 장치 드라이버를 작성하려고합니다. 작업자 스레드는 요청을 기다리고 실제 I/O를 수행합니다.cpu가 insmod에서 멈춤

저는 작업자 스레드와 전송 요청 기능 간의 동기화를 위해 완전한 구조를 사용하고 있습니다. 작업자 스레드는 요청을 진행하기 전에 wait_for_completion을 수행하고 전송 요청이 요청을 받으면 깨어납니다.

그러나 insmod를 시도 할 때 내 시스템이 정지됩니다. 이는 역 추적 각 CPU

[ 152.036031] BUG: soft lockup - CPU#0 stuck for 22s! [mount:1752] 
[ 152.036046] CPU 0 
[ 152.036046] Call Trace: 
[ 152.036046] [<ffffffff8108d3e3>] smp_call_function+0x33/0x60 
[ 152.036046] [<ffffffff8108d443>] on_each_cpu+0x33/0xa0 
[ 152.036046] [<ffffffff81189e95>] __blkdev_put+0x185/0x1f0 
[ 152.036046] [<ffffffff8115570a>] __fput+0xaa/0x200 
[ 152.036046] [<ffffffff81151f3f>] filp_close+0x5f/0x90 
[ 152.036046] [<ffffffff8115201d>] sys_close+0xad/0x120 
[ 152.036046] [<ffffffff815a7312>] system_call_fastpath+0x16/0x1b 

[ 158.233026] INFO: rcu_preempt_state detected stalls on CPUs/tasks: { 2} (detected by 0, t=60002 jiffies) 
[ 158.233031] sending NMI to all CPUs: 

[ 158.233031] NMI backtrace for cpu 0 
[ 158.233031] CPU 0 
[ 158.233031] Call Trace: 
[ 158.233031] [<ffffffff8102018f>] arch_trigger_all_cpu_backtrace+0x4f/0x90 
[ 158.233031] [<ffffffff810ca429>] print_other_cpu_stall+0x159/0x1c0 
[ 158.233031] [<ffffffff810cb5e1>] __rcu_pending+0x31/0x180 
[ 158.233031] [<ffffffff810cbb4a>] rcu_check_callbacks+0x11a/0x190 
[ 158.233031] [<ffffffff8106505f>] update_process_times+0x3f/0x80 
[ 158.233031] [<ffffffff8108772b>] tick_sched_timer+0x5b/0xc0 
[ 158.233031] [<ffffffff8107a2ce>] __run_hrtimer+0x6e/0x240 
[ 158.233031] [<ffffffff8107acf5>] hrtimer_interrupt+0xe5/0x200 
[ 158.233031] [<ffffffff8101efb3>] smp_apic_timer_interrupt+0x63/0xa0 
[ 158.233031] [<ffffffff815a7e5e>] apic_timer_interrupt+0x6e/0x80 
[ 158.233031] [<ffffffff8108d30e>] smp_call_function_many+0x1fe/0x2a0 
[ 158.233031] [<ffffffff8108d3e3>] smp_call_function+0x33/0x60 
[ 158.233031] [<ffffffff8108d443>] on_each_cpu+0x33/0xa0 
[ 158.233031] [<ffffffff81189e95>] __blkdev_put+0x185/0x1f0 
[ 158.233031] [<ffffffff8115570a>] __fput+0xaa/0x200 
[ 158.233031] [<ffffffff81151f3f>] filp_close+0x5f/0x90 
[ 158.233031] [<ffffffff8115201d>] sys_close+0xad/0x120 
[ 158.233031] [<ffffffff815a7312>] system_call_fastpath+0x16/0x1b 

[ 158.233291] CPU 3 and CPU 1 
[ 158.233347] Call Trace: 
[ 158.233352] [<ffffffff8101eb68>] lapic_next_event+0x18/0x20 
[ 158.233356] [<ffffffff81087288>] tick_dev_program_event+0x38/0x100 
[ 158.233360] [<ffffffff8107ad2d>] hrtimer_interrupt+0x11d/0x200 
[ 158.233363] [<ffffffff8101efb3>] smp_apic_timer_interrupt+0x63/0xa0 
[ 158.233366] [<ffffffff815a7e5e>] apic_timer_interrupt+0x6e/0x80 
[ 158.233371] [<ffffffff81029aa2>] native_safe_halt+0x2/0x10 
[ 158.233374] [<ffffffff8100a67d>] default_idle+0x4d/0x2a0 
[ 158.233378] [<ffffffff810011a6>] cpu_idle+0x86/0xd0 

[ 137.645911] CPU 2 
[ 137.645911] Call Trace: 
[ 137.645911] [<ffffffff8159d766>] wait_for_common+0x26/0x150 
[ 137.645911] [<ffffffffa01674e2>] tsdd_worker_thread+0x72/0x1b0 [tsdd] 
[ 137.645911] [<ffffffff81075eee>] kthread+0x7e/0x90 
[ 137.645911] [<ffffffff815a94f4>] kernel_thread_helper+0x4/0x10` 

... 결국 시스템 중단에 보이는 방법이다.

여기에 무슨 일이 일어나고 있는지 나는 모호하게 이해합니다. (tsdd) 작업자 스레드가 CPU 2에서 실행 중이며 wait_for_completion()을 기다리고 있습니다. CPU0에 가까운 시스템 호출이 있습니다. 다른 모든 CPU의 응답을 기다리는 것 같습니다. 그것은 CPU2를 제외한 모든 응답을받습니다. 그것은 너무 오래 기다리고 있습니다. (BUG : 소프트 락업 - CPU # 0이 22 초 동안 멈췄습니다!) 타이머 인터럽트가 있습니다.

이제이 인터럽트는 모든 CPU로 브로드 캐스트됩니다. wait_for_completion() 함수는 completion_done까지 CPU2의 스레드를 대기시킵니다. 인터럽트가 발생하더라도 스레드를 깨우지 않습니다. 이 경우처럼 타이머 인터럽트가 발생하면 인터럽트는 우리 스레드가 wait_for_completion()에 멈춘 CPU2를 포함한 모든 CPU로 전송됩니다. 인터럽트를 서비스 할 수 없게되고 결국 시스템이 중단됩니다.

이 관찰이 맞습니까, 아니면 계속 진행되고 있습니까?

static struct request *sch_req = NULL; //global 
static struct complete *comp = NULL; // initialized in module_init 

void transfer_req(req_queue) { 
    req = blk_fetch_request(req_queue); 
    served = 0; 
    while (!served) { 
     if (completion_done(comp)) 
      continue; 
     sch_req = req; 
     sch_queue = req_queue; 
     complete(comp); 
     served = 1; 
    } 
} 

void worker_thread() { 
    while (!kthread_should_stop()) { 
     if (wait_for_completion(comp)) 
      continue; 
     while (sch_req) { 
      perform_IO(sch_req); 
      sch_req = blk_fetch_req(sch_queue); 
     } 
     init_completion(comp); 
    } 
} 

누군가의 도움이 여기에 무엇이 잘못되었는지 파악하기 위해 수 : 아래

간단한 의사인가? 또한이 문제를 해결하는 방법에 대한 통찰력을 얻고 싶습니다. 나는 심지어 wait_for_completion_interruptible을 사용해 보았지만 문제를 해결하지는 못했다.

감사합니다.

P. - 긴 게시물을 유감스럽게 생각합니다 (로그 파일을 첨부 할 수있는 방법이 없습니다)

답변

1

CSD 잠금 대기 중 CPU0이 멈춘 것처럼 보입니다. CPU 사이에 IPI 인터럽트가 없는지 확인 했습니까?