if (!RB_EMPTY(&vp->v_rbdirty_tree)) {
if ((error = VOP_FSYNC(vp, MNT_WAIT, 0)) != 0)
goto done;
-
+#if 0
/*
* Dirty bufs may be left or generated via races
* in circumstances where vinvalbuf() is called on
!RB_EMPTY(&vp->v_rbdirty_tree))) {
panic("vinvalbuf: dirty bufs");
}
+#endif
}
}
info.slptimeo = slptimeo;
info.vp = vp;
/*
- * Flush the buffer cache until nothing is left.
+ * Flush the buffer cache until nothing is left, wait for all I/O
+ * to complete. At least one pass is required. We might block
+ * in the pip code so we have to re-check. Order is important.
*/
- while (!RB_EMPTY(&vp->v_rbclean_tree) ||
- !RB_EMPTY(&vp->v_rbdirty_tree)) {
- info.clean = 1;
- error = RB_SCAN(buf_rb_tree, &vp->v_rbclean_tree, NULL,
- vinvalbuf_bp, &info);
- if (error == 0) {
+ do {
+ /*
+ * Flush buffer cache
+ */
+ if (!RB_EMPTY(&vp->v_rbclean_tree)) {
+ info.clean = 1;
+ error = RB_SCAN(buf_rb_tree, &vp->v_rbclean_tree,
+ NULL, vinvalbuf_bp, &info);
+ }
+ if (!RB_EMPTY(&vp->v_rbdirty_tree)) {
info.clean = 0;
- error = RB_SCAN(buf_rb_tree, &vp->v_rbdirty_tree, NULL,
- vinvalbuf_bp, &info);
+ error = RB_SCAN(buf_rb_tree, &vp->v_rbdirty_tree,
+ NULL, vinvalbuf_bp, &info);
}
- }
- /*
- * Wait for I/O completion. We may block in the pip code so we have
- * to re-check.
- */
- do {
+ /*
+ * Wait for I/O completion.
+ */
bio_track_wait(&vp->v_track_write, 0, 0);
- if ((object = vp->v_object) != NULL) {
+ if ((object = vp->v_object) != NULL)
refcount_wait(&object->paging_in_progress, "vnvlbx");
- }
- } while (bio_track_active(&vp->v_track_write));
+ } while (bio_track_active(&vp->v_track_write) ||
+ !RB_EMPTY(&vp->v_rbclean_tree) ||
+ !RB_EMPTY(&vp->v_rbdirty_tree));
/*
* Destroy the copy in the VM cache, too.