[dm-devel] Question about work queues

Wood, Brian J brian.j.wood at intel.com
Fri Nov 16 19:11:05 UTC 2007


Hi all, 

I'm working on the dm-stripe.c driver, adding in the workqueue calls to setup eventing for use with dmeventd. I'm hitting a strange problem though, its dumping a call trace in the workqueue.c file at line 166 where it checks the work->entry list to see if its empty:

Nov 14 20:26:20 dmraid-devhost kernel: ------------[ cut here ]------------
Nov 14 20:26:20 dmraid-devhost kernel: kernel BUG at kernel/workqueue.c:166!
Nov 14 20:26:20 dmraid-devhost kernel: invalid opcode: 0000 [1] SMP 
Nov 14 20:26:20 dmraid-devhost kernel: CPU 1 
Nov 14 20:26:20 dmraid-devhost kernel: Modules linked in: autofs4 hidp rfcomm l2cap bluetooth sunrpc e1000 nf_conntrack_netbios_ns ipt_REJECT nf_conntrack_ipv4 xt_state nf_conntrack nfnetlink iptable_filter ip_tables xt_tcpudp ip6t_REJECT ip6table_filter ip6_tables x_tables cpufreq_ondemand acpi_cpufreq dm_mirror dm_multipath dm_mod sbs dock battery ac radeon drm ipv6 floppy snd_hda_intel snd_seq_dummy snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd sr_mod e100 button cdrom parport_pc soundcore mii parport rtc_cmos ata_generic snd_page_alloc serio_raw i2c_i801 i2c_core sg ahci libata sd_mod scsi_mod ext3 jbd mbcache ehci_hcd ohci_hcd uhci_hcd
Nov 14 20:26:20 dmraid-devhost kernel: Pid: 3462, comm: dmraid Not tainted 2.6.23-rc9 #12
Nov 14 20:26:20 dmraid-devhost kernel: RIP: 0010:[<ffffffff81045064>]  [<ffffffff81045064>] queue_work+0x1b/0x40
Nov 14 20:26:20 dmraid-devhost kernel: RSP: 0000:ffff81001c5a3c28  EFLAGS: 00010283
Nov 14 20:26:20 dmraid-devhost kernel: RAX: ffff81003a0d63b0 RBX: ffff81003a0d63a8 RCX: 00000000ffffffff
Nov 14 20:26:20 dmraid-devhost kernel: RDX: 0000000000000000 RSI: ffff81003a0d63a8 RDI: ffff8100280ae2c0
Nov 14 20:26:20 dmraid-devhost kernel: RBP: 0000000000000000 R08: ffff81003d266000 R09: ffffffff812653a0
Nov 14 20:26:20 dmraid-devhost kernel: R10: 0000000000000000 R11: ffff81003d198970 R12: ffffc2000073a080
Nov 14 20:26:20 dmraid-devhost kernel: R13: 0000000000000002 R14: ffff810027a04820 R15: 0000000000000002
Nov 14 20:26:20 dmraid-devhost kernel: FS:  00002b7923cabb40(0000) GS:ffff810037ce1300(0000) knlGS:0000000000000000
Nov 14 20:26:20 dmraid-devhost kernel: CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
Nov 14 20:26:20 dmraid-devhost kernel: CR2: 00007fffa78d13a0 CR3: 000000001c61a000 CR4: 00000000000006e0
Nov 14 20:26:20 dmraid-devhost kernel: DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
Nov 14 20:26:20 dmraid-devhost kernel: DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Nov 14 20:26:20 dmraid-devhost kernel: Process dmraid (pid: 3462, threadinfo ffff81001c5a2000, task ffff81001c40e810)
Nov 14 20:26:20 dmraid-devhost kernel: Stack:  ffff81003a0d6380 ffffffff882d23d0 000000001d1c4500 0000000000000002
Nov 14 20:26:20 dmraid-devhost kernel:  0000000000000002 ffff810027a04c00 0000000000000000 ffffc20000735165
Nov 14 20:26:20 dmraid-devhost kernel:  0000000000000000 000000003a388a00 ffffc2000073a080 ffff810027a04c00
Nov 14 20:26:20 dmraid-devhost kernel: Call Trace:
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff882d23d0>] :dm_mod:stripe_ctr+0x2c1/0x2d2
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff882d1607>] :dm_mod:dm_table_add_target+0x152/0x29f
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff882d2f9e>] :dm_mod:table_load+0xfb/0x1c9
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff882d2ea3>] :dm_mod:table_load+0x0/0x1c9
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff882d3a5f>] :dm_mod:ctl_ioctl+0x223/0x26e
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff81097ef5>] do_ioctl+0x55/0x6b
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff8109814e>] vfs_ioctl+0x243/0x25c
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff810981c0>] sys_ioctl+0x59/0x79
Nov 14 20:26:20 dmraid-devhost kernel:  [<ffffffff8100bd7c>] tracesys+0xdc/0xe1
Nov 14 20:26:20 dmraid-devhost kernel: 
Nov 14 20:26:20 dmraid-devhost kernel: 
Nov 14 20:26:20 dmraid-devhost kernel: Code: 0f 0b eb fe 65 8b 34 25 24 00 00 00 e8 a6 f9 ff ff 48 89 de 
Nov 14 20:26:20 dmraid-devhost kernel: RIP  [<ffffffff81045064>] queue_work+0x1b/0x40
Nov 14 20:26:20 dmraid-devhost kernel:  RSP <ffff81001c5a3c28>

Have I forgot something in initializing my work_struct? Below is what I've added to the driver for using the workqueue model:

I've added the work_struct to the stripe_c structure and the calls to workqueue and trigger_event function like multipath
(I also added a dm_target struct pointer to record the target table for later use in the dm_table_event() call):

struct stripe_c {
      uint32_t stripes;

      /* The size of this target / num. stripes */
      sector_t stripe_width;

      /* stripe chunk size */
      uint32_t chunk_shift;
      sector_t chunk_mask;

      struct stripe stripe[0];
      
      /* Needed for handling events */
      struct dm_target *ti;
      
      /* New work_queue setup for triggering events*/
      struct work_struct trigger_event;

};

struct workqueue_struct *kstriped;
static void trigger_event(struct work_struct *work);

/*
 * An event is triggered whenever a drive drops out of a 
 * stripe volume.
 */
static void trigger_event(struct work_struct *work)
{
      struct stripe_c *sc = container_of(work, struct stripe_c, trigger_event);

      dm_table_event(sc->ti->table);
}

Added the calls to stripe_ctr() for Initialization and creation of the struct & queue:

      /* Create the workqueue */
      kstriped = create_singlethread_workqueue("kstriped");
      if (!kstriped) {
             DMERR("failed to create workqueue kstriped");
             return -ENOMEM;
      }
      /* Initialize the work_struct */
      INIT_WORK(&sc->trigger_event, trigger_event);
      /* Set pointer to dm target; used in trigger_event */
      sc->ti = ti;
      
In the stripe_dtr() function I put the flush and destroy workqueue:

      flush_workqueue(kstriped);
      destroy_workqueue(kstriped);
      kfree(sc);

And for my test of all this to make sure its setup correctly I added a test call of queue_work() in the stripe_ctr() function at the bottom before the "return 0;"

      queue_work(kstriped, &sc->trigger_event);

It's when it hits this call that it is generating the error above; saying the &work->entry is empty (as if it didn't get initialized)? I thought that the INIT_WORK() call sets this list pointer? Do I need a call to INIT_LIST_HEAD()? I've tried reading up some in my "Kernel Driver" O'reilly book and my "Understanding the Linux Kernel" Book and I can't find what is missing. 

Any help would be appreciated, thanks everyone.



Brian Wood
Software Engineer
Intel Corp., Manageability & Platform Software Division
brian.j.wood at intel.com




More information about the dm-devel mailing list