summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_default.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/vfs_default.c')
-rw-r--r--sys/kern/vfs_default.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index f629b19..feecc3d 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -708,6 +708,95 @@ vop_stdbmap(ap)
return (0);
}
+int
+vop_stdfsync(ap)
+ struct vop_fsync_args /* {
+ struct vnode *a_vp;
+ struct ucred *a_cred;
+ int a_waitfor;
+ struct thread *a_td;
+ } */ *ap;
+{
+ struct vnode *vp = ap->a_vp;
+ struct buf *bp;
+ struct buf *nbp;
+ int s, error = 0;
+ int maxretry = 100; /* large, arbitrarily chosen */
+
+ VI_LOCK(vp);
+loop1:
+ /*
+ * MARK/SCAN initialization to avoid infinite loops.
+ */
+ s = splbio();
+ TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
+ bp->b_vflags &= ~BV_SCANNED;
+ bp->b_error = 0;
+ }
+ splx(s);
+
+ /*
+ * Flush all dirty buffers associated with a block device.
+ */
+loop2:
+ s = splbio();
+ for (bp = TAILQ_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) {
+ nbp = TAILQ_NEXT(bp, b_vnbufs);
+ if ((bp->b_vflags & BV_SCANNED) != 0)
+ continue;
+ bp->b_vflags |= BV_SCANNED;
+ if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT))
+ continue;
+ VI_UNLOCK(vp);
+ if ((bp->b_flags & B_DELWRI) == 0)
+ panic("spec_fsync: not dirty");
+ if ((vp->v_vflag & VV_OBJBUF) && (bp->b_flags & B_CLUSTEROK)) {
+ BUF_UNLOCK(bp);
+ vfs_bio_awrite(bp);
+ splx(s);
+ } else {
+ bremfree(bp);
+ splx(s);
+ bawrite(bp);
+ }
+ VI_LOCK(vp);
+ goto loop2;
+ }
+
+ /*
+ * If synchronous the caller expects us to completely resolve all
+ * dirty buffers in the system. Wait for in-progress I/O to
+ * complete (which could include background bitmap writes), then
+ * retry if dirty blocks still exist.
+ */
+ if (ap->a_waitfor == MNT_WAIT) {
+ while (vp->v_numoutput) {
+ vp->v_iflag |= VI_BWAIT;
+ msleep((caddr_t)&vp->v_numoutput, VI_MTX(vp),
+ PRIBIO + 1, "spfsyn", 0);
+ }
+ if (!TAILQ_EMPTY(&vp->v_dirtyblkhd)) {
+ /*
+ * If we are unable to write any of these buffers
+ * then we fail now rather than trying endlessly
+ * to write them out.
+ */
+ TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs)
+ if ((error = bp->b_error) == 0)
+ continue;
+ if (error == 0 && --maxretry >= 0) {
+ splx(s);
+ goto loop1;
+ }
+ vprint("fsync: giving up on dirty", vp);
+ error = EAGAIN;
+ }
+ }
+ VI_UNLOCK(vp);
+ splx(s);
+
+ return (error);
+}
/* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */
int
vop_stdgetpages(ap)
OpenPOWER on IntegriCloud