svn commit: r305592 - head/sys/ufs/ffs

Konstantin Belousov kib at FreeBSD.org
Thu Sep 8 12:01:30 UTC 2016


Author: kib
Date: Thu Sep  8 12:01:28 2016
New Revision: 305592
URL: https://svnweb.freebsd.org/changeset/base/305592

Log:
  Partially lift suspension when ffs_reload() finished with cgs and
  going to re-read inodes.
  
  Secondary write initiators, e.g. ufs_inactive(), might need to start a
  write while owning the vnode lock.  Since the suspended state
  established by /dev/ufssuspend prevents them from entering
  vn_start_secondary_write(), we get deadlock otherwise.
  
  Note that it is arguably not very useful to re-read inodes after
  /dev/ufssuspend suspension, because the suspension does not block
  readers, and other threads might read existing files in parallel with
  suspension owner (for now, only growfs(8)) operations.  This
  effectively means that suspension owner cannot safely modify existing
  inodes, and then there is no sense in re-reading.  But keep the code
  enabled for now.
  
  Reported and tested by:	pho
  Reviewed by:	mckusick
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/ufs/ffs/ffs_extern.h
  head/sys/ufs/ffs/ffs_suspend.c
  head/sys/ufs/ffs/ffs_vfsops.c

Modified: head/sys/ufs/ffs/ffs_extern.h
==============================================================================
--- head/sys/ufs/ffs/ffs_extern.h	Thu Sep  8 12:00:02 2016	(r305591)
+++ head/sys/ufs/ffs/ffs_extern.h	Thu Sep  8 12:01:28 2016	(r305592)
@@ -106,6 +106,9 @@ void	ffs_susp_uninitialize(void);
 
 #define	FFSV_FORCEINSMQ	0x0001
 
+#define	FFSR_FORCE	0x0001
+#define	FFSR_UNSUSPEND	0x0002
+
 extern struct vop_vector ffs_vnodeops1;
 extern struct vop_vector ffs_fifoops1;
 extern struct vop_vector ffs_vnodeops2;

Modified: head/sys/ufs/ffs/ffs_suspend.c
==============================================================================
--- head/sys/ufs/ffs/ffs_suspend.c	Thu Sep  8 12:00:02 2016	(r305591)
+++ head/sys/ufs/ffs/ffs_suspend.c	Thu Sep  8 12:01:28 2016	(r305592)
@@ -235,7 +235,7 @@ ffs_susp_dtor(void *data)
 	KASSERT((mp->mnt_kern_flag & MNTK_SUSPEND) != 0,
 	    ("MNTK_SUSPEND not set"));
 
-	error = ffs_reload(mp, curthread, 1);
+	error = ffs_reload(mp, curthread, FFSR_FORCE | FFSR_UNSUSPEND);
 	if (error != 0)
 		panic("failed to unsuspend writes on %s", fs->fs_fsmnt);
 

Modified: head/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- head/sys/ufs/ffs/ffs_vfsops.c	Thu Sep  8 12:00:02 2016	(r305591)
+++ head/sys/ufs/ffs/ffs_vfsops.c	Thu Sep  8 12:01:28 2016	(r305592)
@@ -573,11 +573,13 @@ ffs_cmount(struct mntarg *ma, void *data
  *	2) re-read superblock from disk.
  *	3) re-read summary information from disk.
  *	4) invalidate all inactive vnodes.
- *	5) invalidate all cached file data.
- *	6) re-read inode data for all active vnodes.
+ *	5) clear MNTK_SUSPEND2 and MNTK_SUSPENDED flags, allowing secondary
+ *	   writers, if requested.
+ *	6) invalidate all cached file data.
+ *	7) re-read inode data for all active vnodes.
  */
 int
-ffs_reload(struct mount *mp, struct thread *td, int force)
+ffs_reload(struct mount *mp, struct thread *td, int flags)
 {
 	struct vnode *vp, *mvp, *devvp;
 	struct inode *ip;
@@ -592,7 +594,7 @@ ffs_reload(struct mount *mp, struct thre
 	ump = VFSTOUFS(mp);
 
 	MNT_ILOCK(mp);
-	if ((mp->mnt_flag & MNT_RDONLY) == 0 && force == 0) {
+	if ((mp->mnt_flag & MNT_RDONLY) == 0 && (flags & FFSR_FORCE) == 0) {
 		MNT_IUNLOCK(mp);
 		return (EINVAL);
 	}
@@ -682,6 +684,12 @@ ffs_reload(struct mount *mp, struct thre
 	size = fs->fs_ncg * sizeof(u_int8_t);
 	fs->fs_contigdirs = (u_int8_t *)space;
 	bzero(fs->fs_contigdirs, size);
+	if ((flags & FFSR_UNSUSPEND) != 0) {
+		MNT_ILOCK(mp);
+		mp->mnt_kern_flag &= ~(MNTK_SUSPENDED | MNTK_SUSPEND2);
+		wakeup(&mp->mnt_flag);
+		MNT_IUNLOCK(mp);
+	}
 
 loop:
 	MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {


More information about the svn-src-head mailing list