int                     error;
        int                     flags;
 
-       if (unlikely(sb->s_frozen == SB_FREEZE_WRITE))
-               flags = SYNC_QUIESCE;
-       else
+       if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) {
+               /*
+                * First stage of freeze - no more writers will make progress
+                * now we are here, so we flush delwri and delalloc buffers
+                * here, then wait for all I/O to complete.  Data is frozen at
+                * that point. Metadata is not frozen, transactions can still
+                * occur here so don't bother flushing the buftarg (i.e
+                * SYNC_QUIESCE) because it'll just get dirty again.
+                */
+               flags = SYNC_FSDATA | SYNC_DELWRI | SYNC_WAIT | SYNC_DIO_WAIT;
+       } else
                flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0);
 
        error = bhv_vfs_sync(vfsp, flags, NULL);
 
 #define SYNC_REFCACHE          0x0040  /* prune some of the nfs ref cache */
 #define SYNC_REMOUNT           0x0080  /* remount readonly, no dummy LRs */
 #define SYNC_QUIESCE           0x0100  /* quiesce fileystem for a snapshot */
+#define SYNC_DIO_WAIT          0x0200  /* wait for direct I/O to complete */
 
 #define SHUTDOWN_META_IO_ERROR 0x0001  /* write attempt to metadata failed */
 #define SHUTDOWN_LOG_IO_ERROR  0x0002  /* write attempt to the log failed */
 
  *                    this by simply making sure the log gets flushed
  *                    if SYNC_BDFLUSH is set, and by actually writing it
  *                    out otherwise.
+ *     SYNC_DIO_WAIT - The caller wants us to wait for all direct I/Os
+ *                    as well to ensure all data I/O completes before we
+ *                    return. Forms the drain side of the write barrier needed
+ *                    to safely quiesce the filesystem.
  *
  */
 /*ARGSUSED*/
 {
        xfs_mount_t     *mp = XFS_BHVTOM(bdp);
 
-       if (unlikely(flags == SYNC_QUIESCE))
-               return xfs_quiesce_fs(mp);
-       else
-               return xfs_syncsub(mp, flags, NULL);
+       return xfs_syncsub(mp, flags, NULL);
 }
 
 /*
                        }
 
                }
+               /*
+                * When freezing, we need to wait ensure direct I/O is complete
+                * as well to ensure all data modification is complete here
+                */
+               if (flags & SYNC_DIO_WAIT)
+                       vn_iowait(vp);
 
                if (flags & SYNC_BDFLUSH) {
                        if ((flags & SYNC_ATTR) &&
        return 0;
 }
 
+/*
+ * Second stage of a freeze. The data is already frozen, now we have to take
+ * care of the metadata. New transactions are already blocked, so we need to
+ * wait for any remaining transactions to drain out before proceding.
+ */
 STATIC void
 xfs_freeze(
        bhv_desc_t      *bdp)
 {
        xfs_mount_t     *mp = XFS_BHVTOM(bdp);
 
+       /* wait for all modifications to complete */
        while (atomic_read(&mp->m_active_trans) > 0)
                delay(100);
 
+       /* flush inodes and push all remaining buffers out to disk */
+       xfs_quiesce_fs(mp);
+
+       BUG_ON(atomic_read(&mp->m_active_trans) > 0);
+
        /* Push the superblock and write an unmount record */
        xfs_log_unmount_write(mp);
        xfs_unmountfs_writesb(mp);