After adding pressure to application which will write tremendous data into ext4 file system, we see many “ext4-dio-unwrit” kernel threads in “top” screen. Many guys say this is a normal phenomenon, so I check the source code of ext4 in 2.6.32 linux kernel.

The beginning of writing a file in kernel is write-back kernel thread, it will call generic_writepages() and then ext4_write_page():

ext4_write_page()
    --> ext4_set_bh_endio()
        --> ext4_end_io_buffer_write()
            --> ext4_add_complete_io()

Let’s look at ext4_add_complete_io():

/* Add the io_end to per-inode completed end_io list. */
void ext4_add_complete_io(ext4_io_end_t *io_end)
{
    struct ext4_inode_info *ei = EXT4_I(io_end->inode);
    struct workqueue_struct *wq;
    unsigned long flags;

    BUG_ON(!(io_end->flag & DIO_AIO_UNWRITTEN));
    wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq;

    spin_lock_irqsave(&ei->i_completed_io_lock, flags);
    if (list_empty(&ei->i_aio_dio_complete_list)) {
        io_end->flag |= DIO_AIO_QUEUED;
        queue_work(wq, &io_end->work);
    }
    list_add_tail(&io_end->list, &ei->i_aio_dio_complete_list);
    spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
}

It will put “io_end” into the work queue “dio_unwritten_wq” which is in the ext4_sb_info. But where does the “dio_unwritten_wq” come from ? In the fs/ext4/super.c:

static int ext4_fill_super(struct super_block *sb, void *data, int silent) 
{
......
    EXT4_SB(sb)->dio_unwritten_wq = create_workqueue("ext4-dio-unwritten");        
    if (!EXT4_SB(sb)->dio_unwritten_wq) {
        printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n");              
        goto failed_mount_wq;                                                      
    } 
......

Oh, it is the “ext4-dio-unwritten” kernel thread! So, the problem is solved: the application dirty the page of file system cache, then the write-back kernel thread will write these dirty pages into specific file system (ext4 in this article), finally ext4 will put io into the work queue “ext4-dio-unwritten” and wait to convert unwritten-extent into written extent of ext4.
Therefore, if we don’t have unwritten-extent in ext4 (just using system-call write() to appending a normal file),the “ext4-dio-unwritten” kernel threads will exist but not using any CPU.