zfs_mount(MS_REMOUNT): protect zfs_(un)register_callbacks calls

We now take z_teardown_lock as a writer to ensure that there is no I/O
while the filesystem state is in a flux.  Also, zfs_suspend_fs() ->
zfsvfs_teardown() call zfs_unregister_callbacks() and zfs_resume_fs() ->
zfsvfs_setup() call zfs_unregister_callbacks().  Previously there was no
synchronization between those calls and the calls in the re-mounting
case.  That could lead to concurrent execution and a crash.

PR:		180060
Differential Revision:	https://reviews.freebsd.org/D2865
Suggested by:	mahrens
Reviewed by:	delphij, pho, mahrens, will
MFC after:	13 days
Sponsored by:	ClusterHQ
This commit is contained in:
Andriy Gapon 2015-07-02 08:32:02 +00:00
parent 556e4c9a83
commit 74f75cb1bd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=285021

View File

@ -1717,9 +1717,19 @@ zfs_mount(vfs_t *vfsp)
* according to those options set in the current VFS options.
*/
if (vfsp->vfs_flag & MS_REMOUNT) {
/* refresh mount options */
zfs_unregister_callbacks(vfsp->vfs_data);
zfsvfs_t *zfsvfs = vfsp->vfs_data;
/*
* Refresh mount options with z_teardown_lock blocking I/O while
* the filesystem is in an inconsistent state.
* The lock also serializes this code with filesystem
* manipulations between entry to zfs_suspend_fs() and return
* from zfs_resume_fs().
*/
rrm_enter(&zfsvfs->z_teardown_lock, RW_WRITER, FTAG);
zfs_unregister_callbacks(zfsvfs);
error = zfs_register_callbacks(vfsp);
rrm_exit(&zfsvfs->z_teardown_lock, FTAG);
goto out;
}