writeback机制源码分析
发布时间:2016-09-20 02:05:00 所属栏目: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; } (编辑:滁州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |