BUG_ON(!test_bit(B_IOLock, &b->flags));
lai = LAFSI(b->inode);
- if (!list_empty_careful(&b->lru)) {
- /* Someone is flushing this block before
- * checkpoint got to it - probably writepage.
- * Must remove it from the leaf lru
- */
- int onlru = 1;
- BUG_ON(test_bit(B_OnFree, &b->flags));
- spin_lock(&fs->lock);
- if (list_empty(&b->lru))
- onlru = 0;
- else
- list_del_init(&b->lru);
- spin_unlock(&fs->lock);
- if (onlru)
- putref(b, MKREF(leaf));
- }
- BUG_ON(!list_empty(&b->lru));
-
if (!test_bit(B_Valid, &b->flags)) {
lafs_iounlock_block(b, B_IOLock);
return wc->cluster_seq;
BUG_ON(!test_bit(B_Valid, &b->flags));
mutex_lock(&wc->lock);
+
+ /* The following check must be inside the mutex_lock
+ * to ensure exclusion between checkpoint and writepage.
+ * checkpoint must never see the block not on the
+ * leaf lru unless it is already in the cluster and so can
+ * be waited for.
+ */
+ if (!list_empty_careful(&b->lru)) {
+ /* Someone is flushing this block before
+ * checkpoint got to it - probably writepage.
+ * Must remove it from the leaf lru
+ */
+ int onlru = 1;
+ BUG_ON(test_bit(B_OnFree, &b->flags));
+ spin_lock(&fs->lock);
+ if (list_empty(&b->lru))
+ onlru = 0;
+ else
+ list_del_init(&b->lru);
+ spin_unlock(&fs->lock);
+ if (onlru)
+ putref(b, MKREF(leaf));
+ }
+
while (wc->remaining < 1) {
// printk("Call flush - remaining = %d\n", wc->remaining);
if (wc->slhead.b == NULL)
while (!list_empty(&wc->clhead)) {
int credits = 0;
b = list_entry(wc->clhead.next, struct block, lru);
- list_del_init(&b->lru);
if (test_bit(B_Phase1, &b->flags))
set_bit(B_WritePhase1, &b->flags);
else
}
}
spin_lock(&fs->lock);
- BUG_ON(!list_empty(&b->lru));
+ list_del(&b->lru);
list_add(&b->lru, &wc->pending_blocks[(wc->pending_next+3)%4]);
spin_unlock(&fs->lock);
lafs_write_block(fs, b, segend.dev, wc);