summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorhannken <hannken@NetBSD.org>2004-01-10 16:23:36 +0000
committerhannken <hannken@NetBSD.org>2004-01-10 16:23:36 +0000
commit8308a4868d9900cbffdcdef06dc34d8171da67dc (patch)
tree6729e838308f21d31aad0254396c952439c6b96a /sys
parent42fd51da28f50124a22b58cff097cdf21419dd89 (diff)
Split out softdep_flushworklist() from softdep_flushfiles() so that
it can be used to clear the work queue. Cleanup ffs_sync() which did not synchronously wait when MNT_WAIT was specified. Clear the work queue when MNT_WAIT is specified. Result is a clean on-disk file system after ffs_sync(.., MNT_WAIT, ..) From FreeBSD.
Diffstat (limited to 'sys')
-rw-r--r--sys/ufs/ffs/ffs_extern.h3
-rw-r--r--sys/ufs/ffs/ffs_softdep.c104
-rw-r--r--sys/ufs/ffs/ffs_softdep.stub.c14
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c24
4 files changed, 103 insertions, 42 deletions
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index 00d8b65aab3..8c6109edeca 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_extern.h,v 1.35 2004/01/02 05:08:57 dbj Exp $ */
+/* $NetBSD: ffs_extern.h,v 1.36 2004/01/10 16:23:36 hannken Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@@ -161,6 +161,7 @@ void softdep_initialize __P((void));
void softdep_reinitialize __P((void));
int softdep_mount __P((struct vnode *, struct mount *, struct fs *,
struct ucred *));
+int softdep_flushworklist __P((struct mount *, int *, struct proc *));
int softdep_flushfiles __P((struct mount *, int, struct proc *));
void softdep_update_inodeblock __P((struct inode *, struct buf *, int));
void softdep_load_inodeblock __P((struct inode *));
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 3038ca0dc4a..58b1c42d26c 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_softdep.c,v 1.53 2003/10/15 11:29:01 hannken Exp $ */
+/* $NetBSD: ffs_softdep.c,v 1.54 2004/01/10 16:23:36 hannken Exp $ */
/*
* Copyright 1998 Marshall Kirk McKusick. All Rights Reserved.
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.c,v 1.53 2003/10/15 11:29:01 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.c,v 1.54 2004/01/10 16:23:36 hannken Exp $");
#include <sys/param.h>
#include <sys/buf.h>
@@ -551,7 +551,8 @@ workitem_free(item, type)
*/
static struct workhead softdep_workitem_pending;
static struct worklist *worklist_tail;
-static int softdep_worklist_busy;
+static int softdep_worklist_busy; /* 1 => trying to do unmount */
+static int softdep_worklist_req; /* serialized waiters */
static int max_softdeps; /* maximum number of structs before slowdown */
static int tickdelay = 2; /* number of ticks to pause during slowdown */
static int proc_waiting; /* tracks whether we have a timeout posted */
@@ -648,8 +649,12 @@ softdep_process_worklist(matchmnt)
* (below) can get an accurate count of the number of items
* related to its mount point that are in the list.
*/
- if (softdep_worklist_busy && matchmnt == NULL)
- return (-1);
+ if (matchmnt == NULL) {
+ if (softdep_worklist_busy < 0)
+ return (-1);
+ softdep_worklist_busy += 1;
+ }
+
/*
* If requested, try removing inode or removal dependencies.
*/
@@ -727,8 +732,16 @@ softdep_process_worklist(matchmnt)
TYPENAME(wk->wk_type));
/* NOTREACHED */
}
- if (softdep_worklist_busy && matchmnt == NULL)
- return (-1);
+
+ /*
+ * If a umount operation wants to run the worklist
+ * accurately, abort.
+ */
+ if (softdep_worklist_req && matchmnt == NULL) {
+ ACQUIRE_LOCK(&lk);
+ matchcnt = -1;
+ break;
+ }
/*
* If requested, try removing inode or removal dependencies.
*/
@@ -750,6 +763,11 @@ softdep_process_worklist(matchmnt)
ACQUIRE_LOCK(&lk);
softdep_freequeue_process();
}
+ if (matchmnt == NULL) {
+ softdep_worklist_busy -= 1;
+ if (softdep_worklist_req && softdep_worklist_busy == 0)
+ wakeup(&softdep_worklist_req);
+ }
FREE_LOCK(&lk);
return (matchcnt);
}
@@ -783,46 +801,33 @@ softdep_move_dependencies(oldbp, newbp)
* Purge the work list of all items associated with a particular mount point.
*/
int
-softdep_flushfiles(oldmnt, flags, p)
+softdep_flushworklist(oldmnt, countp, p)
struct mount *oldmnt;
- int flags;
+ int *countp;
struct proc *p;
{
struct vnode *devvp;
- int error, loopcnt;
+ int count, error = 0;
/*
* Await our turn to clear out the queue.
*/
- while (softdep_worklist_busy)
- tsleep(&lbolt, PRIBIO, "softflush", 0);
- softdep_worklist_busy = 1;
- if ((error = ffs_flushfiles(oldmnt, flags, p)) != 0) {
- softdep_worklist_busy = 0;
- return (error);
+ while (softdep_worklist_busy) {
+ softdep_worklist_req += 1;
+ tsleep(&softdep_worklist_req, PRIBIO, "softflush", 0);
+ softdep_worklist_req -= 1;
}
+ softdep_worklist_busy = -1;
/*
* Alternately flush the block device associated with the mount
* point and process any dependencies that the flushing
- * creates. In theory, this loop can happen at most twice,
- * but we give it a few extra just to be sure.
+ * creates. We continue until no more worklist dependencies
+ * are found.
*/
+ *countp = 0;
devvp = VFSTOUFS(oldmnt)->um_devvp;
- for (loopcnt = 10; loopcnt > 0; ) {
- if (softdep_process_worklist(oldmnt) == 0) {
- loopcnt--;
- /*
- * Do another flush in case any vnodes were brought in
- * as part of the cleanup operations.
- */
- if ((error = ffs_flushfiles(oldmnt, flags, p)) != 0)
- break;
- /*
- * If we still found nothing to do, we are really done.
- */
- if (softdep_process_worklist(oldmnt) == 0)
- break;
- }
+ while ((count = softdep_process_worklist(oldmnt)) > 0) {
+ *countp += count;
vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
error = VOP_FSYNC(devvp, p->p_ucred, FSYNC_WAIT, 0, 0, p);
VOP_UNLOCK(devvp, 0);
@@ -830,6 +835,39 @@ softdep_flushfiles(oldmnt, flags, p)
break;
}
softdep_worklist_busy = 0;
+ if (softdep_worklist_req)
+ wakeup(&softdep_worklist_req);
+ return (error);
+}
+
+/*
+ * Flush all vnodes and worklist items associated with a specified mount point.
+ */
+int
+softdep_flushfiles(oldmnt, flags, p)
+ struct mount *oldmnt;
+ int flags;
+ struct proc *p;
+{
+ int error, count, loopcnt;
+
+ /*
+ * Alternately flush the vnodes associated with the mount
+ * point and process any dependencies that the flushing
+ * creates. In theory, this loop can happen at most twice,
+ * but we give it a few extra just to be sure.
+ */
+ for (loopcnt = 10; loopcnt > 0; loopcnt--) {
+ /*
+ * Do another flush in case any vnodes were brought in
+ * as part of the cleanup operations.
+ */
+ if ((error = ffs_flushfiles(oldmnt, flags, p)) != 0)
+ break;
+ if ((error = softdep_flushworklist(oldmnt, &count, p)) != 0 ||
+ count == 0)
+ break;
+ }
/*
* If we are unmounting then it is an error to fail. If we
* are simply trying to downgrade to read-only, then filesystem
diff --git a/sys/ufs/ffs/ffs_softdep.stub.c b/sys/ufs/ffs/ffs_softdep.stub.c
index 090bd4a93db..d9bbce0a8e7 100644
--- a/sys/ufs/ffs/ffs_softdep.stub.c
+++ b/sys/ufs/ffs/ffs_softdep.stub.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_softdep.stub.c,v 1.12 2003/06/29 22:32:36 fvdl Exp $ */
+/* $NetBSD: ffs_softdep.stub.c,v 1.13 2004/01/10 16:23:36 hannken Exp $ */
/*
* Copyright 1997 Marshall Kirk McKusick. All Rights Reserved.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.stub.c,v 1.12 2003/06/29 22:32:36 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_softdep.stub.c,v 1.13 2004/01/10 16:23:36 hannken Exp $");
#include <sys/param.h>
#include <sys/vnode.h>
@@ -45,6 +45,16 @@ __KERNEL_RCSID(0, "$NetBSD: ffs_softdep.stub.c,v 1.12 2003/06/29 22:32:36 fvdl E
#include <ufs/ufs/ufs_extern.h>
int
+softdep_flushworklist(oldmnt, countp, p)
+ struct mount *oldmnt;
+ int *countp;
+ struct proc *p;
+{
+
+ panic("softdep_flushworklist called");
+}
+
+int
softdep_flushfiles(oldmnt, flags, p)
struct mount *oldmnt;
int flags;
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 2055d1dfc83..72a940d07d4 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ffs_vfsops.c,v 1.131 2004/01/09 19:10:22 dbj Exp $ */
+/* $NetBSD: ffs_vfsops.c,v 1.132 2004/01/10 16:23:36 hannken Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1994
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.131 2004/01/09 19:10:22 dbj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.132 2004/01/10 16:23:36 hannken Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ffs.h"
@@ -1221,7 +1221,7 @@ ffs_sync(mp, waitfor, cred, p)
struct inode *ip;
struct ufsmount *ump = VFSTOUFS(mp);
struct fs *fs;
- int error, allerror = 0;
+ int error, count, allerror = 0;
fs = ump->um_fs;
if (fs->fs_fmod != 0 && fs->fs_ronly != 0) { /* XXX */
@@ -1270,14 +1270,26 @@ loop:
/*
* Force stale file system control information to be flushed.
*/
- if (waitfor != MNT_LAZY) {
- if (ump->um_mountp->mnt_flag & MNT_SOFTDEP)
- waitfor = MNT_NOWAIT;
+ if (waitfor == MNT_WAIT && (ump->um_mountp->mnt_flag & MNT_SOFTDEP)) {
+ if ((error = softdep_flushworklist(ump->um_mountp, &count, p)))
+ allerror = error;
+ /* Flushed work items may create new vnodes to clean */
+ if (allerror == 0 && count) {
+ simple_lock(&mntvnode_slock);
+ goto loop;
+ }
+ }
+ if (waitfor != MNT_LAZY && (ump->um_devvp->v_numoutput > 0 ||
+ !LIST_EMPTY(&ump->um_devvp->v_dirtyblkhd))) {
vn_lock(ump->um_devvp, LK_EXCLUSIVE | LK_RETRY);
if ((error = VOP_FSYNC(ump->um_devvp, cred,
waitfor == MNT_WAIT ? FSYNC_WAIT : 0, 0, 0, p)) != 0)
allerror = error;
VOP_UNLOCK(ump->um_devvp, 0);
+ if (allerror == 0 && waitfor == MNT_WAIT) {
+ simple_lock(&mntvnode_slock);
+ goto loop;
+ }
}
#ifdef QUOTA
qsync(mp);