加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

writeback机制源码分析

发布时间:2016-05-25 00:58:33 所属栏目:Linux 来源:网络整理
导读:writeback相关数据结构 与writeback相关的数据结构主要有: 1,backing_dev_info,该数据结构描述了backing_dev的所有信息,通常块设备的request queue中会包含

writeback线程管理程序分析如下:

static int bdi_forker_thread(void *ptr)  
{  
    struct bdi_writeback *me = ptr;  
     
    current->flags |= PF_SWAPWRITE;  
    set_freezable();  
     
    /*  
     * Our parent may run at a different priority, just set us to normal  
     */
    set_user_nice(current, 0);  
     
    for (;;) {  
        struct task_struct *task = NULL;  
        struct backing_dev_info *bdi;  
        enum {  
            NO_ACTION,   /* Nothing to do */
            FORK_THREAD, /* Fork bdi thread */
            KILL_THREAD, /* Kill inactive bdi thread */
        } action = NO_ACTION;  
     
        /*  
         * Temporary measure, we want to make sure we don't see  
         * dirty data on the default backing_dev_info  
         */
        if (wb_has_dirty_io(me) || !list_empty(&me->bdi->work_list)) {  
            del_timer(&me->wakeup_timer);  
            wb_do_writeback(me, 0);  
        }  
     
        spin_lock_bh(&bdi_lock);  
        /*  
         * In the following loop we are going to check whether we have  
         * some work to do without any synchronization with tasks  
         * waking us up to do work for them. Set the task state here  
         * so that we don't miss wakeups after verifying conditions.  
         */
        set_current_state(TASK_INTERRUPTIBLE);  
        /* 遍历所有的bdi对象,检查这些bdi是否存在脏数据,如果有脏数据,那么需要为其fork线程,然后做writeback操作 */
        list_for_each_entry(bdi, &bdi_list, bdi_list) {  
            bool have_dirty_io;  
     
            if (!bdi_cap_writeback_dirty(bdi) ||  
                 bdi_cap_flush_forker(bdi))  
                continue;  
     
            WARN(!test_bit(BDI_registered, &bdi->state),  
                 "bdi %p/%s is not registered!n", bdi, bdi->name);  
            /* 检查是否存在脏数据 */
            have_dirty_io = !list_empty(&bdi->work_list) ||  
                    wb_has_dirty_io(&bdi->wb);  
     
            /*  
             * If the bdi has work to do, but the thread does not  
             * exist - create it.  
             */
            if (!bdi->wb.task && have_dirty_io) {  
                /*  
                 * Set the pending bit - if someone will try to  
                 * unregister this bdi - it'll wait on this bit.  
                 */
                /* 如果有脏数据,并且不存在线程,那么接下来做线程的FORK操作 */
                set_bit(BDI_pending, &bdi->state);  
                action = FORK_THREAD;  
                break;  
            }  
     
            spin_lock(&bdi->wb_lock);  
     
            /*  
             * If there is no work to do and the bdi thread was  
             * inactive long enough - kill it. The wb_lock is taken  
             * to make sure no-one adds more work to this bdi and  
             * wakes the bdi thread up.  
             */
            /* 如果一个bdi长时间没有脏数据,那么执行线程的KILL操作,结束掉该bdi对应的writeback线程 */
            if (bdi->wb.task && !have_dirty_io &&  
                time_after(jiffies, bdi->wb.last_active +  
                        bdi_longest_inactive())) {  
                task = bdi->wb.task;  
                bdi->wb.task = NULL;  
                spin_unlock(&bdi->wb_lock);  
                set_bit(BDI_pending, &bdi->state);  
                action = KILL_THREAD;  
                break;  
            }  
            spin_unlock(&bdi->wb_lock);  
        }  
        spin_unlock_bh(&bdi_lock);  
     
        /* Keep working if default bdi still has things to do */
        if (!list_empty(&me->bdi->work_list))  
            __set_current_state(TASK_RUNNING);  
        /* 执行线程的FORK和KILL操作 */
        switch (action) {  
        case FORK_THREAD:  
            /* FORK一个bdi_writeback_thread线程,该线程的名字为flush-major:minor */
            __set_current_state(TASK_RUNNING);  
            task = kthread_create(bdi_writeback_thread, &bdi->wb,  
                          "flush-%s", dev_name(bdi->dev));  
            if (IS_ERR(task)) {  
                /*  
                 * If thread creation fails, force writeout of  
                 * the bdi from the thread. Hopefully 1024 is  
                 * large enough for efficient IO.  
                 */
                writeback_inodes_wb(&bdi->wb, 1024,  
                            WB_REASON_FORKER_THREAD);  
            } else {  
                /*  
                 * The spinlock makes sure we do not lose  
                 * wake-ups when racing with 'bdi_queue_work()'.  
                 * And as soon as the bdi thread is visible, we  
                 * can start it.  
                 */
                spin_lock_bh(&bdi->wb_lock);  
                bdi->wb.task = task;  
                spin_unlock_bh(&bdi->wb_lock);  
                wake_up_process(task);  
            }  
            bdi_clear_pending(bdi);  
            break;  
     
        case KILL_THREAD:  
            /* KILL一个线程 */
            __set_current_state(TASK_RUNNING);  
            kthread_stop(task);  
            bdi_clear_pending(bdi);  
            break;  
     
        case NO_ACTION:  
            /* 如果没有可执行的动作,那么调度本线程睡眠一段时间 */
            if (!wb_has_dirty_io(me) || !dirty_writeback_interval)  
                /*  
                 * There are no dirty data. The only thing we  
                 * should now care about is checking for  
                 * inactive bdi threads and killing them. Thus,  
                 * let's sleep for longer time, save energy and  
                 * be friendly for battery-driven devices.  
                 */
                schedule_timeout(bdi_longest_inactive());  
            else
                schedule_timeout(msecs_to_jiffies(dirty_writeback_interval * 10));  
            try_to_freeze();  
            break;  
        }  
    }  
     
    return 0;  
}

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读