linux vfs cache,VFS 缓冲区缓存Buffer Cache实现原理剖析 续

由于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缓冲区的状态正确,则进一步判断缓冲区是否不为脏,或者是为第三编循环(在第三编循环中,即使遇到脏缓冲区,也不

================

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值