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 ? Message-ID: <20020327101947.GA2322@caerdonn.eurocontrol.fr>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20020327101947.GA2322>
