From owner-svn-src-all@freebsd.org Thu Nov 5 20:52:51 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 2FC272D0F89; Thu, 5 Nov 2020 20:52:51 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4CRwhM0gbjz3P9Z; Thu, 5 Nov 2020 20:52:51 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 07E1E19AF0; Thu, 5 Nov 2020 20:52:51 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 0A5Kqocs050367; Thu, 5 Nov 2020 20:52:50 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 0A5KqoXi050364; Thu, 5 Nov 2020 20:52:50 GMT (envelope-from kib@FreeBSD.org) Message-Id: <202011052052.0A5KqoXi050364@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Thu, 5 Nov 2020 20:52:50 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r367398 - in head/sys: dev/acpica dev/xen/control kern sys X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: in head/sys: dev/acpica dev/xen/control kern sys X-SVN-Commit-Revision: 367398 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 05 Nov 2020 20:52:51 -0000 Author: kib Date: Thu Nov 5 20:52:49 2020 New Revision: 367398 URL: https://svnweb.freebsd.org/changeset/base/367398 Log: Suspend all writeable local filesystems on power suspend. This ensures that no writes are pending in memory, either metadata or user data, but not including dirty pages not yet converted to fs writes. Only filesystems declared local are suspended. Note that this does not guarantee absence of the metadata errors or leaks if resume is not done: for instance, on UFS unlinked but opened inodes are leaked and require fsck to gc. Reviewed by: markj Discussed with: imp Tested by: imp (previous version), pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D27054 Modified: head/sys/dev/acpica/acpi.c head/sys/dev/xen/control/control.c head/sys/kern/vfs_mount.c head/sys/sys/mount.h Modified: head/sys/dev/acpica/acpi.c ============================================================================== --- head/sys/dev/acpica/acpi.c Thu Nov 5 20:18:00 2020 (r367397) +++ head/sys/dev/acpica/acpi.c Thu Nov 5 20:52:49 2020 (r367398) @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -3081,6 +3082,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state) EVENTHANDLER_INVOKE(power_suspend_early); stop_all_proc(); + suspend_all_fs(); EVENTHANDLER_INVOKE(power_suspend); #ifdef EARLY_AP_STARTUP @@ -3240,6 +3242,7 @@ backout: } #endif + resume_all_fs(); resume_all_proc(); EVENTHANDLER_INVOKE(power_resume); Modified: head/sys/dev/xen/control/control.c ============================================================================== --- head/sys/dev/xen/control/control.c Thu Nov 5 20:18:00 2020 (r367397) +++ head/sys/dev/xen/control/control.c Thu Nov 5 20:52:49 2020 (r367398) @@ -113,6 +113,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -204,6 +205,7 @@ xctrl_suspend() xs_lock(); stop_all_proc(); xs_unlock(); + suspend_all_fs(); EVENTHANDLER_INVOKE(power_suspend); #ifdef EARLY_AP_STARTUP @@ -317,6 +319,7 @@ xctrl_suspend() } #endif + resume_all_fs(); resume_all_proc(); EVENTHANDLER_INVOKE(power_resume); Modified: head/sys/kern/vfs_mount.c ============================================================================== --- head/sys/kern/vfs_mount.c Thu Nov 5 20:18:00 2020 (r367397) +++ head/sys/kern/vfs_mount.c Thu Nov 5 20:52:49 2020 (r367398) @@ -2507,3 +2507,67 @@ mount_devctl_event(const char *type, struct mount *mp, sbuf_delete(&sb); free(buf, M_MOUNT); } + +/* + * Suspend write operations on all local writeable filesystems. Does + * full sync of them in the process. + * + * Iterate over the mount points in reverse order, suspending most + * recently mounted filesystems first. It handles a case where a + * filesystem mounted from a md(4) vnode-backed device should be + * suspended before the filesystem that owns the vnode. + */ +void +suspend_all_fs(void) +{ + struct mount *mp; + int error; + + mtx_lock(&mountlist_mtx); + TAILQ_FOREACH_REVERSE(mp, &mountlist, mntlist, mnt_list) { + error = vfs_busy(mp, MBF_MNTLSTLOCK | MBF_NOWAIT); + if (error != 0) + continue; + if ((mp->mnt_flag & (MNT_RDONLY | MNT_LOCAL)) != MNT_LOCAL || + (mp->mnt_kern_flag & MNTK_SUSPEND) != 0) { + mtx_lock(&mountlist_mtx); + vfs_unbusy(mp); + continue; + } + error = vfs_write_suspend(mp, 0); + if (error == 0) { + MNT_ILOCK(mp); + MPASS((mp->mnt_kern_flag & MNTK_SUSPEND_ALL) == 0); + mp->mnt_kern_flag |= MNTK_SUSPEND_ALL; + MNT_IUNLOCK(mp); + mtx_lock(&mountlist_mtx); + } else { + printf("suspend of %s failed, error %d\n", + mp->mnt_stat.f_mntonname, error); + mtx_lock(&mountlist_mtx); + vfs_unbusy(mp); + } + } + mtx_unlock(&mountlist_mtx); +} + +void +resume_all_fs(void) +{ + struct mount *mp; + + mtx_lock(&mountlist_mtx); + TAILQ_FOREACH(mp, &mountlist, mnt_list) { + if ((mp->mnt_kern_flag & MNTK_SUSPEND_ALL) == 0) + continue; + mtx_unlock(&mountlist_mtx); + MNT_ILOCK(mp); + MPASS((mp->mnt_kern_flag & MNTK_SUSPEND) != 0); + mp->mnt_kern_flag &= ~MNTK_SUSPEND_ALL; + MNT_IUNLOCK(mp); + vfs_write_resume(mp, 0); + mtx_lock(&mountlist_mtx); + vfs_unbusy(mp); + } + mtx_unlock(&mountlist_mtx); +} Modified: head/sys/sys/mount.h ============================================================================== --- head/sys/sys/mount.h Thu Nov 5 20:18:00 2020 (r367397) +++ head/sys/sys/mount.h Thu Nov 5 20:52:49 2020 (r367398) @@ -463,6 +463,7 @@ struct mntoptnames { #define MNTK_VMSETSIZE_BUG 0x00010000 #define MNTK_UNIONFS 0x00020000 /* A hack for F_ISUNIONSTACK */ #define MNTK_FPLOOKUP 0x00040000 /* fast path lookup is supported */ +#define MNTK_SUSPEND_ALL 0x00080000 /* Suspended by all-fs suspension */ #define MNTK_NOASYNC 0x00800000 /* disable async */ #define MNTK_UNMOUNT 0x01000000 /* unmount in progress */ #define MNTK_MWAIT 0x02000000 /* waiting for unmount to finish */ @@ -1047,6 +1048,9 @@ void vfs_dump_mount_counters(struct mount *); enum mount_counter { MNT_COUNT_REF, MNT_COUNT_LOCKREF, MNT_COUNT_WRITEOPCOUNT }; int vfs_mount_fetch_counter(struct mount *, enum mount_counter); + +void suspend_all_fs(void); +void resume_all_fs(void); /* * Code transitioning mnt_vfs_ops to > 0 issues IPIs until it observes