由于BUF_DIRTY链表是一个双向循环链表for (i = nr_buffers_type[BUF_DIRTY]*2 ; i-- > 0 ; bh = next) {
next = bh->b_next_free;
if (!lru_list[BUF_DIRTY])
break;
if (dev && bh->b_dev != dev)
continue;
if (buffer_locked(bh)) {
/* Buffer is locked; skip it unless wait is
* requested AND pass > 0.
*/
if (!wait || !pass) {
retry = 1;
continue;
}
atomic_inc(&bh->b_count);
spin_unlock(&lru_list_lock);
wait_on_buffer (bh);
atomic_dec(&bh->b_count);
goto repeat;
}
/* If an unlocked buffer is not uptodate, there has
* been an IO error. Skip it.
*/
if (wait && buffer_req(bh) && !buffer_locked(bh) &&
!buffer_dirty(bh) && !buffer_uptodate(bh)) {
err = -EIO;
continue;
}
/* Don't write clean buffers. Don't write ANY buffers
* on the third pass.
*/
if (!buffer_dirty(bh) || pass >= 2)
continue;
atomic_inc(&bh->b_count);
spin_unlock(&lru_list_lock);
ll_rw_block(WRITE, 1, &bh);
atomic_dec(&bh->b_count);
retry = 1;
goto repeat;
}
repeat2:
bh = lru_list[BUF_LOCKED];
if (!bh) {
spin_unlock(&lru_list_lock);
break;
}
for (i = nr_buffers_type[BUF_LOCKED]*2 ; i-- > 0 ; bh = next) {
next = bh->b_next_free;
if (!lru_list[BUF_LOCKED])
break;
if (dev && bh->b_dev != dev)
continue;
if (buffer_locked(bh)) {
/* Buffer is locked; skip it unless wait is
* requested AND pass > 0.
*/
if (!wait || !pass) {
retry = 1;
continue;
}
atomic_inc(&bh->b_count);
spin_unlock(&lru_list_lock);
wait_on_buffer (bh);
spin_lock(&lru_list_lock);
atomic_dec(&bh->b_count);
goto repeat2;
}
}
spin_unlock(&lru_list_lock);
/* If we are waiting for the sync to succeed, and if any dirty
* blocks were written, then repeat; on the second pass, only
* wait for buffers being written (do not pass to write any
* more buffers on the second pass).
*/
} while (wait && retry && ++pass<=2);
return err;
}对该函数的详细注释如下: (1)函数的主体就是一个do{}while循环,并依据wait的值决定循环次数(1or3)。 (2)首先,通过一个for循环来扫瞄BUF_DIRTY链表。For循环的循环次数是I=nr_buffers_type〔BUF_DIRTY〕×2。由于BUF_DIRTY链表是一个双向循环链表,因此for循环将链表扫瞄两次(why? I don』t know^_^ If you know, please tell me.)对于每一次被扫瞄的缓冲区,循环体将作如下处理: n首先判断lru_list[BUF_DIRTY]链表是否为空。如果为NULL,则终止扫瞄过程。因为每一个被安排回写的脏缓冲区都会被移到BUF_LOCKED链表中,从而使BUF_DIRTY链表中的元素会越来越少。因此这里在开始处理之前有必要进行一下判断。 n如果参数dev非0,则进一步判断当前被扫瞄的缓冲区是否属于指定的块设备。如果不是,则扫瞄量表中的下一个元素。当dev=0时,sync_buffers()函数同步所有脏缓冲区(不论它是属于哪个块设备)。 n通过buffer_locked()宏判断被扫瞄的缓冲区是否已经被加锁(是否以被选中去做回写操作)。如果是,则进一步判断wait和pass的值。如果wait=0或pass=0(即第一遍do{}while循环),则不等待该缓冲区的回写操作完成,而是继续扫瞄链表中的下一个元素。否则(wait!=0且pass!=0)就调用wait_on_buffer()函数等待该缓冲区被解锁,然后执行goto repeat语句,重新从链表的开头开始扫瞄(原因如前所述)。 n否则就检查这个unlocked缓冲区的状态是否正确。如果不正确,就忽略它,继续扫瞄下一个链表元素。 n如果这个unlocked缓冲区的状态正确,则进一步判断缓冲区是否不为脏,或者是为第三编循环(在第三编循环中,即使遇到脏缓冲区,也不
================