+/*
+ * Ifile and meta data blocks are not marked busy, so segment writes MUST be
+ * single threaded. Currently, there are two paths into lfs_segwrite, sync()
+ * and getnewbuf(). They both mark the file system busy. Lfs_vflush()
+ * explicitly marks the file system busy. So lfs_segwrite is safe. I think.
+ */
+
+int
+lfs_vflush(vp)
+ struct vnode *vp;
+{
+ struct inode *ip;
+ struct lfs *fs;
+ struct mount *mp;
+ struct segment *sp;
+ int error, s;
+
+#ifdef VERBOSE
+ printf("lfs_vflush\n");
+#endif
+ mp = vp->v_mount;
+ fs = VFSTOUFS(mp)->um_lfs;
+
+ /*
+ * XXX
+ * check flags?
+ * mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY) ||
+ */
+ if (vfs_busy(mp))
+ return (0);
+
+ /*
+ * Allocate a segment structure and enough space to hold pointers to
+ * the maximum possible number of buffers which can be described in a
+ * single summary block.
+ */
+ sp = malloc(sizeof(struct segment), M_SEGMENT, M_WAITOK);
+ sp->bpp = malloc(((LFS_SUMMARY_SIZE - sizeof(SEGSUM)) /
+ sizeof(daddr_t) + 1) * sizeof(struct buf *), M_SEGMENT, M_WAITOK);
+ sp->seg_flags = SEGM_CKP;
+ lfs_initseg(fs, sp);
+
+ /*
+ * Keep a cumulative count of the outstanding I/O operations. If the
+ * disk drive catches up with us it could go to zero before we finish,
+ * so we artificially increment it by one until we've scheduled all of
+ * the writes we intend to do.
+ */
+ s = splbio();
+ ++fs->lfs_iocount;
+ splx(s);
+
+ if (vp->v_dirtyblkhd != NULL)
+ lfs_writefile(fs, sp, vp);
+ ip = VTOI(vp);
+ lfs_writeinode(fs, sp, ip);
+ ip->i_flags &= ~(IMOD | IACC | IUPD | ICHG);
+
+ lfs_writeseg(fs, sp);
+
+ /*
+ * If the I/O count is non-zero, sleep until it reaches zero. At the
+ * moment, the user's process hangs around so we can sleep.
+ */
+ s = splbio();
+ if (--fs->lfs_iocount && (error =
+ tsleep(&fs->lfs_iocount, PRIBIO + 1, "lfs vflush", 0)))
+ return (error);
+ splx(s);
+ vfs_unbusy(mp);
+
+ free(sp->bpp, M_SEGMENT);
+ free(sp, M_SEGMENT);
+
+ return (0);
+}
+