From owner-svn-src-stable@FreeBSD.ORG Sat Feb 14 23:02:21 2009 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9B21A106566C; Sat, 14 Feb 2009 23:02:21 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 870D88FC08; Sat, 14 Feb 2009 23:02:21 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n1EN2LQ8032793; Sat, 14 Feb 2009 23:02:21 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n1EN2LPM032787; Sat, 14 Feb 2009 23:02:21 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200902142302.n1EN2LPM032787@svn.freebsd.org> From: Konstantin Belousov Date: Sat, 14 Feb 2009 23:02:21 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r188620 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb kern sys ufs/ffs X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 14 Feb 2009 23:02:22 -0000 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);