[Midnightbsd-cvs] src [8939] trunk/sys: work around the hold of references to the struct dquot by the freeblk workitems.
laffer1 at midnightbsd.org
laffer1 at midnightbsd.org
Mon Sep 26 19:06:55 EDT 2016
Revision: 8939
http://svnweb.midnightbsd.org/src/?rev=8939
Author: laffer1
Date: 2016-09-26 19:06:55 -0400 (Mon, 26 Sep 2016)
Log Message:
-----------
work around the hold of references to the struct dquot by the freeblk workitems.
Modified Paths:
--------------
trunk/sys/sys/vnode.h
trunk/sys/ufs/ffs/ffs_softdep.c
trunk/sys/ufs/ffs/ffs_vfsops.c
trunk/sys/ufs/ufs/ufs_quota.c
Modified: trunk/sys/sys/vnode.h
===================================================================
--- trunk/sys/sys/vnode.h 2016-09-26 23:06:31 UTC (rev 8938)
+++ trunk/sys/sys/vnode.h 2016-09-26 23:06:55 UTC (rev 8939)
@@ -383,6 +383,7 @@
#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: trunk/sys/ufs/ffs/ffs_softdep.c
===================================================================
--- trunk/sys/ufs/ffs/ffs_softdep.c 2016-09-26 23:06:31 UTC (rev 8938)
+++ trunk/sys/ufs/ffs/ffs_softdep.c 2016-09-26 23:06:55 UTC (rev 8939)
@@ -1914,7 +1914,12 @@
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 @@
* 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 @@
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: trunk/sys/ufs/ffs/ffs_vfsops.c
===================================================================
--- trunk/sys/ufs/ffs/ffs_vfsops.c 2016-09-26 23:06:31 UTC (rev 8938)
+++ trunk/sys/ufs/ffs/ffs_vfsops.c 2016-09-26 23:06:55 UTC (rev 8939)
@@ -1355,9 +1355,10 @@
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 @@
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 @@
* 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: trunk/sys/ufs/ufs/ufs_quota.c
===================================================================
--- trunk/sys/ufs/ufs/ufs_quota.c 2016-09-26 23:06:31 UTC (rev 8938)
+++ trunk/sys/ufs/ufs/ufs_quota.c 2016-09-26 23:06:55 UTC (rev 8939)
@@ -80,7 +80,7 @@
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 @@
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,11 +1619,12 @@
/*
* 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
@@ -1626,6 +1631,7 @@
* 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 @@
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 Midnightbsd-cvs
mailing list