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>