Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Mar 2002 13:34:29 -0800
From:      Kirk McKusick <mckusick@beastie.mckusick.com>
To:        Ollivier Robert <roberto@eurocontrol.fr>
Cc:        arch@FreeBSD.ORG
Subject:   Re: [PATCH] MFC the full filesystem softupdates fix ? 
Message-ID:  <200203272134.g2RLYTD97258@beastie.mckusick.com>
In-Reply-To: Your message of "Wed, 27 Mar 2002 11:19:47 %2B0100." <20020327101947.GA2322@caerdonn.eurocontrol.fr> 

next in thread | previous in thread | raw e-mail | index | archive | help
If it was easy as your patch, there would be no problem in
putting it in. The problem is that -current does not have
the code to maintain the fs_pendingblocks variable. At a
minimum you would have to add that code as well. It is a
good deal more extensive, though at this point well enough
tested that I am less fearful of adding it.

	Kirk McKusick

=-=-=-=-=-=

Date: Wed, 27 Mar 2002 11:19:47 +0100
From: Ollivier Robert <roberto@eurocontrol.fr>
To: mckusick@mckusick.com
Cc: arch@FreeBSD.ORG
Subject: [PATCH] MFC the full filesystem softupdates fix ?

Following some discussions in the French fr.comp.os.bsd newsgroup about
softupdates and the full filesystem problem (which is fixed in CURRENT
thanks to you), here a proposed diff to merge the fix into STABLE.

Can you (and -arch) review it ?  It would be nice to have this fixed in
STABLE as well.

Thanks.

Index: ffs_alloc.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_alloc.c,v
retrieving revision 1.64.2.2
diff -u -2 -r1.64.2.2 ffs_alloc.c
--- ffs_alloc.c	21 Sep 2001 19:15:21 -0000	1.64.2.2
+++ ffs_alloc.c	27 Mar 2002 10:08:29 -0000
@@ -107,5 +107,5 @@
 	register struct fs *fs;
 	ufs_daddr_t bno;
-	int cg;
+	int cg, reclaimed;
 #ifdef QUOTA
 	int error;
@@ -124,4 +124,6 @@
 		panic("ffs_alloc: missing credential");
 #endif /* DIAGNOSTIC */
+	reclaimed = 0;
+retry:
 	if (size == fs->fs_bsize && fs->fs_cstotal.cs_nbfree == 0)
 		goto nospace;
@@ -155,4 +157,9 @@
 #endif
 nospace:
+	if (fs->fs_pendingblocks > 0 && reclaimed == 0) {
+		reclaimed = 1;
+		softdep_request_cleanup(fs, ITOV(ip));
+		goto retry;
+	}
 	ffs_fserr(fs, cred->cr_uid, "file system full");
 	uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
@@ -177,7 +184,7 @@
 	struct buf **bpp;
 {
-	register struct fs *fs;
+	struct fs *fs;
 	struct buf *bp;
-	int cg, request, error;
+	int cg, request, error, reclaimed;
 	ufs_daddr_t bprev, bno;
 
@@ -198,4 +205,6 @@
 	if (cred->cr_uid != 0 &&
 	    freespace(fs, fs->fs_minfree) -  numfrags(fs, nsize - osize) < 0)
+	reclaimed = 0;
+retry:
 		goto nospace;
 	if ((bprev = ip->i_db[lbprev]) == 0) {
@@ -208,5 +217,5 @@
 	 * Allocate the extra space in the buffer.
 	 */
-	error = bread(ITOV(ip), lbprev, osize, NOCRED, &bp);
+	error = bread(vp, lbprev, osize, NOCRED, &bp);
 	if (error) {
 		brelse(bp);
@@ -295,5 +304,5 @@
 	if (bno > 0) {
 		bp->b_blkno = fsbtodb(fs, bno);
-		if (!DOINGSOFTDEP(ITOV(ip)))
+		if (!DOINGSOFTDEP(vp))
 			ffs_blkfree(ip, bprev, (long)osize);
 		if (nsize < request)
@@ -319,4 +328,9 @@
 	 * no space available
 	 */
+	if (fs->fs_pendingblocks > 0 && reclaimed == 0) {
+		reclaimed = 1;
+		softdep_request_cleanup(fs, vp);
+		goto retry;
+	}
 	ffs_fserr(fs, cred->cr_uid, "file system full");
 	uprintf("\n%s: write failed, file system is full\n", fs->fs_fsmnt);
Index: ffs_extern.h
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_extern.h,v
retrieving revision 1.30
diff -u -2 -r1.30 ffs_extern.h
--- ffs_extern.h	9 Jan 2000 22:40:02 -0000	1.30
+++ ffs_extern.h	27 Mar 2002 10:05:03 -0000
@@ -115,4 +115,5 @@
 void	softdep_load_inodeblock __P((struct inode *));
 void	softdep_freefile __P((struct vnode *, ino_t, int));
+int	softdep_request_cleanup __P((struct fs *, struct vnode *));
 void	softdep_setup_freeblocks __P((struct inode *, off_t));
 void	softdep_setup_inomapdep __P((struct buf *, struct inode *, ino_t));
Index: ffs_softdep.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_softdep.c,v
retrieving revision 1.57.2.11
diff -u -2 -r1.57.2.11 ffs_softdep.c
--- ffs_softdep.c	5 Feb 2002 18:46:53 -0000	1.57.2.11
+++ ffs_softdep.c	27 Mar 2002 10:12:48 -0000
@@ -508,7 +508,8 @@
 static struct proc *filesys_syncer; /* proc of filesystem syncer process */
 static int req_clear_inodedeps;	/* syncer process flush some inodedeps */
-#define FLUSH_INODES	1
+#define FLUSH_INODES		1
 static int req_clear_remove;	/* syncer process flush some freeblks */
-#define FLUSH_REMOVE	2
+#define FLUSH_REMOVE		2
+#define FLUSH_REMOVE_WAIT	3
 /*
  * runtime statistics
@@ -703,5 +704,5 @@
 	if (wk == 0) {
 		FREE_LOCK(&lk);
-		return (0);
+		return (-1);
 	}
 	WORKLIST_REMOVE(wk);
@@ -4561,4 +4562,39 @@
 
 /*
+ * Called by the allocation routines when they are about to fail
+ * in the hope that we can free up some disk space.
+ * 
+ * First check to see if the work list has anything on it. If it has,
+ * clean up entries until we successfully free some space. Because this
+ * process holds inodes locked, we cannot handle any remove requests
+ * that might block on a locked inode as that could lead to deadlock.
+ * If the worklist yields no free space, encourage the syncer daemon
+ * to help us. In no event will we try for longer than tickdelay seconds.
+ */
+int
+softdep_request_cleanup(fs, vp)
+	struct fs *fs;
+	struct vnode *vp;
+{
+	long starttime, needed;
+
+	needed = fs->fs_cstotal.cs_nbfree + fs->fs_contigsumsize;
+	starttime = time_second + tickdelay;
+	if (UFS_UPDATE(vp, 1) != 0)
+		return (0);
+	while (fs->fs_pendingblocks > 0 && fs->fs_cstotal.cs_nbfree <= needed) {
+		if (time_second > starttime)
+			return (0);
+		if (num_on_worklist > 0 &&
+		    process_worklist_item(NULL, LK_NOWAIT) != -1) {
+			stat_worklist_push += 1;
+			continue;
+		}
+		request_cleanup(FLUSH_REMOVE_WAIT, 0);
+	}
+	return (1);
+}
+
+/*
  * If memory utilization has gotten too high, deliberately slow things
  * down and speed up the I/O processing.
@@ -4595,4 +4631,10 @@
 
 	/*
+	* Next, we attempt to speed up the syncer process. If that
+	* is successful, then we allow the process to continue.
+	*/
+	if (speedup_syncer() && resource != FLUSH_REMOVE_WAIT)
+		return(0);
+	/*
 	 * If we are resource constrained on inode dependencies, try
 	 * flushing some dirty inodes. Otherwise, we are constrained
@@ -4613,4 +4655,5 @@
 
 	case FLUSH_REMOVE:
+	case FLUSH_REMOVE_WAIT:
 		stat_blk_limit_push += 1;
 		req_clear_remove += 1;

-- 
Ollivier ROBERT  -=-  Eurocontrol EEC/ITM  -=-  Ollivier.Robert@eurocontrol.fr
FreeBSD caerdonn.eurocontrol.fr 5.0-CURRENT #46: Wed Jan  3 15:52:00 CET 2001

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200203272134.g2RLYTD97258>