Index: sys/dev/acpica/acpi.c =================================================================== --- sys/dev/acpica/acpi.c +++ sys/dev/acpica/acpi.c @@ -33,6 +33,7 @@ #include "opt_acpi.h" #include +#include #include #include #include @@ -3070,6 +3071,11 @@ EVENTHANDLER_INVOKE(power_suspend_early); stop_all_proc(); + /* + * Sync all buffers to disk and give them a chance to drain before + * proceeding. + */ + bufsyncwait(10, true); EVENTHANDLER_INVOKE(power_suspend); #ifdef EARLY_AP_STARTUP Index: sys/kern/vfs_bio.c =================================================================== --- sys/kern/vfs_bio.c +++ sys/kern/vfs_bio.c @@ -1323,12 +1323,11 @@ } /* - * Shutdown the system cleanly to prepare for reboot, halt, or power off. + * Sync the filesystems and wait a while for all buffers to be flushed. */ -void -bufshutdown(int show_busybufs) +bool +bufsyncwait(int maxiter, bool first_buf_printf) { - static int first_buf_printf = 1; struct buf *bp; int iter, nbusy, pbusy; #ifndef PREEMPTION @@ -1336,17 +1335,16 @@ #endif /* - * Sync filesystems for shutdown + * Sync filesystems for suspend / shutdown */ wdog_kern_pat(WD_LASTVAL); kern_sync(curthread); /* - * With soft updates, some buffers that are - * written will be remarked as dirty until other - * buffers are written. + * With soft updates, some buffers that are written will be + * remarked as dirty until other buffers are written. */ - for (iter = pbusy = 0; iter < 20; iter++) { + for (iter = pbusy = 0; iter < maxiter; iter++) { nbusy = 0; for (bp = &buf[nbuf]; --bp >= buf; ) if (isbufbusy(bp)) @@ -1358,7 +1356,7 @@ } if (first_buf_printf) { printf("Syncing disks, buffers remaining... "); - first_buf_printf = 0; + first_buf_printf = false; } printf("%d ", nbusy); if (nbusy < pbusy) @@ -1386,6 +1384,25 @@ #endif } printf("\n"); + return (first_buf_printf); +} + +/* + * Shutdown the system cleanly to prepare for reboot, halt, or power off. + */ +void +bufshutdown(int show_busybufs) +{ + static bool first_buf_printf = true; + struct buf *bp; + int nbusy; + + /* + * Try to clean all the buffers by repeatedly calling kern_sync() when dirty buffers + * remain after the attempt. + */ + first_buf_printf = bufsyncwait(20, first_buf_printf); + /* * Count only busy local buffers to prevent forcing * a fsck if we're just a client of a wedged NFS server Index: sys/sys/buf.h =================================================================== --- sys/sys/buf.h +++ sys/sys/buf.h @@ -520,6 +520,7 @@ caddr_t kern_vfs_bio_buffer_alloc(caddr_t v, long physmem_est); void bufinit(void); void bufshutdown(int); +bool bufsyncwait(int maxiter, bool first_buf_printf); void bdata2bio(struct buf *bp, struct bio *bip); void bwillwrite(void); int buf_dirty_count_severe(void);