svn commit: r188620 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern sys ufs/ffs

Konstantin Belousov kib at FreeBSD.org
Sat Feb 14 15:02:22 PST 2009


Author: kib
Date: Sat Feb 14 23:02:21 2009
New Revision: 188620
URL: http://svn.freebsd.org/changeset/base/188620

Log:
  MFC r183073:
  When attempt is made to suspend a filesystem that is already syspended,
  wait until the current suspension is lifted instead of silently returning
  success immediately. The consequences of calling vfs_write() resume when
  not owning the suspension are not well-defined at best.
  
  Add the vfs_susp_clean() mount method to be called from
  vfs_write_resume(). Set it to process_deferred_inactive() for ffs, and
  stop calling it manually.
  
  Add the thread flag TDP_IGNSUSP that allows to bypass the suspension
  point in the vn_start_write. It is intended for use by VFS in the
  situations where the suspender want to do some i/o requiring calls to
  vn_start_write(), and this i/o cannot be done later.
  
  Note that addition of the mount method and new struct mount field change
  the KBI. This was approved by re and no objections on stable@ were
  raised.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/kern/vfs_vnops.c
  stable/7/sys/sys/mount.h
  stable/7/sys/sys/proc.h
  stable/7/sys/ufs/ffs/ffs_extern.h
  stable/7/sys/ufs/ffs/ffs_snapshot.c
  stable/7/sys/ufs/ffs/ffs_vfsops.c

Modified: stable/7/sys/kern/vfs_vnops.c
==============================================================================
--- stable/7/sys/kern/vfs_vnops.c	Sat Feb 14 22:29:54 2009	(r188619)
+++ stable/7/sys/kern/vfs_vnops.c	Sat Feb 14 23:02:21 2009	(r188620)
@@ -916,15 +916,18 @@ vn_start_write(vp, mpp, flags)
 	/*
 	 * Check on status of suspension.
 	 */
-	while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) {
-		if (flags & V_NOWAIT) {
-			error = EWOULDBLOCK;
-			goto unlock;
+	if ((curthread->td_pflags & TDP_IGNSUSP) == 0 ||
+	    mp->mnt_susp_owner != curthread) {
+		while ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) {
+			if (flags & V_NOWAIT) {
+				error = EWOULDBLOCK;
+				goto unlock;
+			}
+			error = msleep(&mp->mnt_flag, MNT_MTX(mp),
+			    (PUSER - 1) | (flags & PCATCH), "suspfs", 0);
+			if (error)
+				goto unlock;
 		}
-		error = msleep(&mp->mnt_flag, MNT_MTX(mp), 
-		    (PUSER - 1) | (flags & PCATCH), "suspfs", 0);
-		if (error)
-			goto unlock;
 	}
 	if (flags & V_XSLEEP)
 		goto unlock;
@@ -1048,11 +1051,14 @@ vfs_write_suspend(mp)
 	int error;
 
 	MNT_ILOCK(mp);
-	if (mp->mnt_kern_flag & MNTK_SUSPEND) {
+	if (mp->mnt_susp_owner == curthread) {
 		MNT_IUNLOCK(mp);
-		return (0);
+		return (EALREADY);
 	}
+	while (mp->mnt_kern_flag & MNTK_SUSPEND)
+		msleep(&mp->mnt_flag, MNT_MTX(mp), PUSER - 1, "wsuspfs", 0);
 	mp->mnt_kern_flag |= MNTK_SUSPEND;
+	mp->mnt_susp_owner = curthread;
 	if (mp->mnt_writeopcount > 0)
 		(void) msleep(&mp->mnt_writeopcount, 
 		    MNT_MTX(mp), (PUSER - 1)|PDROP, "suspwt", 0);
@@ -1073,12 +1079,17 @@ vfs_write_resume(mp)
 
 	MNT_ILOCK(mp);
 	if ((mp->mnt_kern_flag & MNTK_SUSPEND) != 0) {
+		KASSERT(mp->mnt_susp_owner == curthread, ("mnt_susp_owner"));
 		mp->mnt_kern_flag &= ~(MNTK_SUSPEND | MNTK_SUSPEND2 |
 				       MNTK_SUSPENDED);
+		mp->mnt_susp_owner = NULL;
 		wakeup(&mp->mnt_writeopcount);
 		wakeup(&mp->mnt_flag);
-	}
-	MNT_IUNLOCK(mp);
+		curthread->td_pflags &= ~TDP_IGNSUSP;
+		MNT_IUNLOCK(mp);
+		VFS_SUSP_CLEAN(mp);
+	} else
+		MNT_IUNLOCK(mp);
 }
 
 /*

Modified: stable/7/sys/sys/mount.h
==============================================================================
--- stable/7/sys/sys/mount.h	Sat Feb 14 22:29:54 2009	(r188619)
+++ stable/7/sys/sys/mount.h	Sat Feb 14 23:02:21 2009	(r188620)
@@ -175,6 +175,7 @@ struct mount {
 	int		mnt_holdcntwaiters;	/* waits on hold count */
 	int		mnt_secondary_writes;   /* (i) # of secondary writes */
 	int		mnt_secondary_accwrites;/* (i) secondary wr. starts */
+	struct thread	*mnt_susp_owner;	/* (i) thread owning suspension */
 #define	mnt_endzero	mnt_gjprovider
 	char		*mnt_gjprovider;	/* gjournal provider name */
 	struct lock	mnt_explock;		/* vfs_export walkers lock */
@@ -539,6 +540,7 @@ typedef	int vfs_extattrctl_t(struct moun
 typedef	int vfs_mount_t(struct mount *mp, struct thread *td);
 typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op,
 		    struct sysctl_req *req);
+typedef void vfs_susp_clean_t(struct mount *mp);
 
 struct vfsops {
 	vfs_mount_t		*vfs_mount;
@@ -555,6 +557,7 @@ struct vfsops {
 	vfs_uninit_t		*vfs_uninit;
 	vfs_extattrctl_t	*vfs_extattrctl;
 	vfs_sysctl_t		*vfs_sysctl;
+	vfs_susp_clean_t	*vfs_susp_clean;
 };
 
 vfs_statfs_t	__vfs_statfs;
@@ -576,6 +579,9 @@ vfs_statfs_t	__vfs_statfs;
 	(*(MP)->mnt_op->vfs_extattrctl)(MP, C, FN, NS, N, P)
 #define VFS_SYSCTL(MP, OP, REQ) \
 	(*(MP)->mnt_op->vfs_sysctl)(MP, OP, REQ)
+#define	VFS_SUSP_CLEAN(MP) \
+	({if (*(MP)->mnt_op->vfs_susp_clean != NULL)		\
+	       (*(MP)->mnt_op->vfs_susp_clean)(MP); })
 
 extern int mpsafe_vfs;
 

Modified: stable/7/sys/sys/proc.h
==============================================================================
--- stable/7/sys/sys/proc.h	Sat Feb 14 22:29:54 2009	(r188619)
+++ stable/7/sys/sys/proc.h	Sat Feb 14 23:02:21 2009	(r188620)
@@ -378,6 +378,7 @@ do {									\
 #define	TDP_NORUNNINGBUF 0x00040000 /* Ignore runningbufspace check */
 #define	TDP_WAKEUP	0x00080000 /* Don't sleep in umtx cond_wait */
 #define	TDP_INBDFLUSH	0x00100000 /* Already in BO_BDFLUSH, do not recurse */
+#define	TDP_IGNSUSP	0x00800000 /* Permission to ignore the MNTK_SUSPEND* */
 
 /*
  * Reasons that the current thread can not be run yet.

Modified: stable/7/sys/ufs/ffs/ffs_extern.h
==============================================================================
--- stable/7/sys/ufs/ffs/ffs_extern.h	Sat Feb 14 22:29:54 2009	(r188619)
+++ stable/7/sys/ufs/ffs/ffs_extern.h	Sat Feb 14 23:02:21 2009	(r188620)
@@ -80,6 +80,7 @@ void	ffs_snapremove(struct vnode *vp);
 int	ffs_snapshot(struct mount *mp, char *snapfile);
 void	ffs_snapshot_mount(struct mount *mp);
 void	ffs_snapshot_unmount(struct mount *mp);
+void	process_deferred_inactive(struct mount *mp);
 int	ffs_syncvnode(struct vnode *vp, int waitfor);
 int	ffs_truncate(struct vnode *, off_t, int, struct ucred *, struct thread *);
 int	ffs_update(struct vnode *, int);

Modified: stable/7/sys/ufs/ffs/ffs_snapshot.c
==============================================================================
--- stable/7/sys/ufs/ffs/ffs_snapshot.c	Sat Feb 14 22:29:54 2009	(r188619)
+++ stable/7/sys/ufs/ffs/ffs_snapshot.c	Sat Feb 14 23:02:21 2009	(r188620)
@@ -161,7 +161,6 @@ static int snapacct_ufs2(struct vnode *,
 static int mapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,
     struct fs *, ufs_lbn_t, int);
 static int readblock(struct vnode *vp, struct buf *, ufs2_daddr_t);
-static void process_deferred_inactive(struct mount *);
 static void try_free_snapdata(struct vnode *devvp, struct thread *td);
 static int ffs_bp_snapblk(struct vnode *, struct buf *);
 
@@ -2429,12 +2428,14 @@ readblock(vp, bp, lbn)
 	return (bp->b_error);
 }
 
+#endif
+
 /*
  * Process file deletes that were deferred by ufs_inactive() due to
  * the file system being suspended. Transfer IN_LAZYACCESS into
  * IN_MODIFIED for vnodes that were accessed during suspension.
  */
-static void
+void
 process_deferred_inactive(struct mount *mp)
 {
 	struct vnode *vp, *mvp;
@@ -2507,6 +2508,8 @@ process_deferred_inactive(struct mount *
 	vn_finished_secondary_write(mp);
 }
 
+#ifndef NO_FFS_SNAPSHOT
+
 /* Try to free snapdata associated with devvp */
 static void
 try_free_snapdata(struct vnode *devvp,

Modified: stable/7/sys/ufs/ffs/ffs_vfsops.c
==============================================================================
--- stable/7/sys/ufs/ffs/ffs_vfsops.c	Sat Feb 14 22:29:54 2009	(r188619)
+++ stable/7/sys/ufs/ffs/ffs_vfsops.c	Sat Feb 14 23:02:21 2009	(r188620)
@@ -105,6 +105,7 @@ static struct vfsops ufs_vfsops = {
 	.vfs_uninit =		ffs_uninit,
 	.vfs_unmount =		ffs_unmount,
 	.vfs_vget =		ffs_vget,
+	.vfs_susp_clean =	process_deferred_inactive,
 };
 
 VFS_SET(ufs_vfsops, ufs, 0);


More information about the svn-src-all mailing list