Date: Wed, 13 Mar 2013 10:01:06 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r248233 - in stable/9/sys: sys ufs/ffs ufs/ufs Message-ID: <201303131001.r2DA16lL071592@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Wed Mar 13 10:01:05 2013 New Revision: 248233 URL: http://svnweb.freebsd.org/changeset/base/248233 Log: MFC r247388: Work around the hold of references to the struct dquot by the freeblk workitems for some time at unmount. Modified: stable/9/sys/sys/vnode.h stable/9/sys/ufs/ffs/ffs_softdep.c stable/9/sys/ufs/ffs/ffs_vfsops.c stable/9/sys/ufs/ufs/ufs_quota.c Directory Properties: stable/9/sys/ (props changed) Modified: stable/9/sys/sys/vnode.h ============================================================================== --- stable/9/sys/sys/vnode.h Wed Mar 13 09:54:11 2013 (r248232) +++ stable/9/sys/sys/vnode.h Wed Mar 13 10:01:05 2013 (r248233) @@ -383,6 +383,7 @@ extern int vttoif_tab[]; #define SKIPSYSTEM 0x0001 /* vflush: skip vnodes marked VSYSTEM */ #define FORCECLOSE 0x0002 /* vflush: force file closure */ #define WRITECLOSE 0x0004 /* vflush: only close writable files */ +#define EARLYFLUSH 0x0008 /* vflush: early call for ffs_flushfiles */ #define V_SAVE 0x0001 /* vinvalbuf: sync file first */ #define V_ALT 0x0002 /* vinvalbuf: invalidate only alternate bufs */ #define V_NORMAL 0x0004 /* vinvalbuf: invalidate only regular bufs */ Modified: stable/9/sys/ufs/ffs/ffs_softdep.c ============================================================================== --- stable/9/sys/ufs/ffs/ffs_softdep.c Wed Mar 13 09:54:11 2013 (r248232) +++ stable/9/sys/ufs/ffs/ffs_softdep.c Wed Mar 13 10:01:05 2013 (r248233) @@ -1914,7 +1914,12 @@ softdep_flushfiles(oldmnt, flags, td) int flags; struct thread *td; { - int error, depcount, loopcnt, retry_flush_count, retry; +#ifdef QUOTA + struct ufsmount *ump; + int i; +#endif + int error, early, depcount, loopcnt, retry_flush_count, retry; + int morework; loopcnt = 10; retry_flush_count = 3; @@ -1932,7 +1937,9 @@ retry_flush: * Do another flush in case any vnodes were brought in * as part of the cleanup operations. */ - if ((error = ffs_flushfiles(oldmnt, flags, td)) != 0) + early = retry_flush_count == 1 || (oldmnt->mnt_kern_flag & + MNTK_UNMOUNT) == 0 ? 0 : EARLYFLUSH; + if ((error = ffs_flushfiles(oldmnt, flags | early, td)) != 0) break; if ((error = softdep_flushworklist(oldmnt, &depcount, td)) != 0 || depcount == 0) @@ -1956,7 +1963,17 @@ retry_flush: MNT_ILOCK(oldmnt); KASSERT((oldmnt->mnt_kern_flag & MNTK_NOINSMNTQ) != 0, ("softdep_flushfiles: !MNTK_NOINSMNTQ")); - if (oldmnt->mnt_nvnodelistsize > 0) { + morework = oldmnt->mnt_nvnodelistsize > 0; +#ifdef QUOTA + ump = VFSTOUFS(oldmnt); + UFS_LOCK(ump); + for (i = 0; i < MAXQUOTAS; i++) { + if (ump->um_quotas[i] != NULLVP) + morework = 1; + } + UFS_UNLOCK(ump); +#endif + if (morework) { if (--retry_flush_count > 0) { retry = 1; loopcnt = 3; Modified: stable/9/sys/ufs/ffs/ffs_vfsops.c ============================================================================== --- stable/9/sys/ufs/ffs/ffs_vfsops.c Wed Mar 13 09:54:11 2013 (r248232) +++ stable/9/sys/ufs/ffs/ffs_vfsops.c Wed Mar 13 10:01:05 2013 (r248233) @@ -1355,9 +1355,10 @@ ffs_flushfiles(mp, flags, td) struct thread *td; { struct ufsmount *ump; - int error; + int qerror, error; ump = VFSTOUFS(mp); + qerror = 0; #ifdef QUOTA if (mp->mnt_flag & MNT_QUOTA) { int i; @@ -1365,11 +1366,19 @@ ffs_flushfiles(mp, flags, td) if (error) return (error); for (i = 0; i < MAXQUOTAS; i++) { - quotaoff(td, mp, i); + error = quotaoff(td, mp, i); + if (error != 0) { + if ((flags & EARLYFLUSH) == 0) + return (error); + else + qerror = error; + } } + /* - * Here we fall through to vflush again to ensure - * that we have gotten rid of all the system vnodes. + * Here we fall through to vflush again to ensure that + * we have gotten rid of all the system vnodes, unless + * quotas must not be closed. */ } #endif @@ -1384,11 +1393,21 @@ ffs_flushfiles(mp, flags, td) * that we have gotten rid of all the system vnodes. */ } - /* - * Flush all the files. + + /* + * Do not close system files if quotas were not closed, to be + * able to sync the remaining dquots. The freeblks softupdate + * workitems might hold a reference on a dquot, preventing + * quotaoff() from completing. Next round of + * softdep_flushworklist() iteration should process the + * blockers, allowing the next run of quotaoff() to finally + * flush held dquots. + * + * Otherwise, flush all the files. */ - if ((error = vflush(mp, 0, flags, td)) != 0) + if (qerror == 0 && (error = vflush(mp, 0, flags, td)) != 0) return (error); + /* * Flush filesystem metadata. */ Modified: stable/9/sys/ufs/ufs/ufs_quota.c ============================================================================== --- stable/9/sys/ufs/ufs/ufs_quota.c Wed Mar 13 09:54:11 2013 (r248232) +++ stable/9/sys/ufs/ufs/ufs_quota.c Wed Mar 13 10:01:05 2013 (r248233) @@ -80,7 +80,7 @@ static int dqopen(struct vnode *, struct static int dqget(struct vnode *, u_long, struct ufsmount *, int, struct dquot **); static int dqsync(struct vnode *, struct dquot *); -static void dqflush(struct vnode *); +static int dqflush(struct vnode *); static int quotaoff1(struct thread *td, struct mount *mp, int type); static int quotaoff_inchange(struct thread *td, struct mount *mp, int type); @@ -680,8 +680,12 @@ again: vrele(vp); } - dqflush(qvp); - /* Clear um_quotas before closing the quota vnode to prevent + error = dqflush(qvp); + if (error != 0) + return (error); + + /* + * Clear um_quotas before closing the quota vnode to prevent * access to the closed vnode from dqget/dqsync */ UFS_LOCK(ump); @@ -1615,17 +1619,19 @@ out: /* * Flush all entries from the cache for a particular vnode. */ -static void +static int dqflush(struct vnode *vp) { struct dquot *dq, *nextdq; struct dqhash *dqh; + int error; /* * Move all dquot's that used to refer to this quota * file off their hash chains (they will eventually * fall off the head of the free list and be re-used). */ + error = 0; DQH_LOCK(); for (dqh = &dqhashtbl[dqhash]; dqh >= dqhashtbl; dqh--) { for (dq = LIST_FIRST(dqh); dq; dq = nextdq) { @@ -1633,12 +1639,15 @@ dqflush(struct vnode *vp) if (dq->dq_ump->um_quotas[dq->dq_type] != vp) continue; if (dq->dq_cnt) - panic("dqflush: stray dquot"); - LIST_REMOVE(dq, dq_hash); - dq->dq_ump = (struct ufsmount *)0; + error = EBUSY; + else { + LIST_REMOVE(dq, dq_hash); + dq->dq_ump = NULL; + } } } DQH_UNLOCK(); + return (error); } /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201303131001.r2DA16lL071592>