svn commit: r248233 - in stable/9/sys: sys ufs/ffs ufs/ufs
Konstantin Belousov
kib at FreeBSD.org
Wed Mar 13 10:01:07 UTC 2013
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);
}
/*
More information about the svn-src-stable-9
mailing list