From owner-svn-src-all@FreeBSD.ORG Wed Mar 23 05:13:54 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id D679C106567A; Wed, 23 Mar 2011 05:13:54 +0000 (UTC) (envelope-from mckusick@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id C437C8FC0A; Wed, 23 Mar 2011 05:13:54 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p2N5DsSR082179; Wed, 23 Mar 2011 05:13:54 GMT (envelope-from mckusick@svn.freebsd.org) Received: (from mckusick@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p2N5DsCb082175; Wed, 23 Mar 2011 05:13:54 GMT (envelope-from mckusick@svn.freebsd.org) Message-Id: <201103230513.p2N5DsCb082175@svn.freebsd.org> From: Kirk McKusick Date: Wed, 23 Mar 2011 05:13:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r219895 - head/sys/ufs/ffs X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 23 Mar 2011 05:13:54 -0000 Author: mckusick Date: Wed Mar 23 05:13:54 2011 New Revision: 219895 URL: http://svn.freebsd.org/changeset/base/219895 Log: Add retry code analogous to the block allocation retry code to avoid running out of inodes. Reported by: Peter Holm Modified: head/sys/ufs/ffs/ffs_alloc.c head/sys/ufs/ffs/ffs_extern.h head/sys/ufs/ffs/ffs_softdep.c Modified: head/sys/ufs/ffs/ffs_alloc.c ============================================================================== --- head/sys/ufs/ffs/ffs_alloc.c Wed Mar 23 03:58:55 2011 (r219894) +++ head/sys/ufs/ffs/ffs_alloc.c Wed Mar 23 05:13:54 2011 (r219895) @@ -219,7 +219,7 @@ nospace: #endif if (fs->fs_pendingblocks > 0 && reclaimed == 0) { reclaimed = 1; - softdep_request_cleanup(fs, ITOV(ip)); + softdep_request_cleanup(fs, ITOV(ip), FLUSH_BLOCKS_WAIT); goto retry; } UFS_UNLOCK(ump); @@ -420,7 +420,7 @@ nospace: */ if (fs->fs_pendingblocks > 0 && reclaimed == 0) { reclaimed = 1; - softdep_request_cleanup(fs, vp); + softdep_request_cleanup(fs, vp, FLUSH_BLOCKS_WAIT); UFS_UNLOCK(ump); if (bp) { brelse(bp); @@ -936,7 +936,7 @@ ffs_valloc(pvp, mode, cred, vpp) struct ufsmount *ump; ino_t ino, ipref; u_int cg; - int error, error1; + int error, error1, reclaimed; static struct timeval lastfail; static int curfail; @@ -946,6 +946,8 @@ ffs_valloc(pvp, mode, cred, vpp) ump = pip->i_ump; UFS_LOCK(ump); + reclaimed = 0; +retry: if (fs->fs_cstotal.cs_nifree == 0) goto noinodes; @@ -1019,6 +1021,11 @@ dup_alloc: (*vpp)->v_op = &ffs_vnodeops1; return (0); noinodes: + if (fs->fs_pendinginodes > 0 && reclaimed == 0) { + reclaimed = 1; + softdep_request_cleanup(fs, pvp, FLUSH_INODES_WAIT); + goto retry; + } UFS_UNLOCK(ump); if (ppsratecheck(&lastfail, &curfail, 1)) { ffs_fserr(fs, pip->i_number, "out of inodes"); Modified: head/sys/ufs/ffs/ffs_extern.h ============================================================================== --- head/sys/ufs/ffs/ffs_extern.h Wed Mar 23 03:58:55 2011 (r219894) +++ head/sys/ufs/ffs/ffs_extern.h Wed Mar 23 05:13:54 2011 (r219895) @@ -120,7 +120,7 @@ int softdep_flushfiles(struct mount *, i void softdep_update_inodeblock(struct inode *, struct buf *, int); void softdep_load_inodeblock(struct inode *); void softdep_freefile(struct vnode *, ino_t, int); -int softdep_request_cleanup(struct fs *, struct vnode *); +int softdep_request_cleanup(struct fs *, struct vnode *, int); void softdep_setup_freeblocks(struct inode *, off_t, int); void softdep_setup_inomapdep(struct buf *, struct inode *, ino_t); void softdep_setup_blkmapdep(struct buf *, struct mount *, ufs2_daddr_t, @@ -147,6 +147,13 @@ int softdep_waitidle(struct mount *); int softdep_prealloc(struct vnode *, int); int softdep_journal_lookup(struct mount *, struct vnode **); +/* + * Things to request flushing in softdep_request_cleanup() + */ +#define FLUSH_INODES 1 +#define FLUSH_INODES_WAIT 2 +#define FLUSH_BLOCKS 3 +#define FLUSH_BLOCKS_WAIT 4 int ffs_rdonly(struct inode *); Modified: head/sys/ufs/ffs/ffs_softdep.c ============================================================================== --- head/sys/ufs/ffs/ffs_softdep.c Wed Mar 23 03:58:55 2011 (r219894) +++ head/sys/ufs/ffs/ffs_softdep.c Wed Mar 23 05:13:54 2011 (r219895) @@ -1105,10 +1105,7 @@ static int *stat_countp; /* statistic to static struct callout softdep_callout; static int req_pending; static int req_clear_inodedeps; /* syncer process flush some inodedeps */ -#define FLUSH_INODES 1 static int req_clear_remove; /* syncer process flush some freeblks */ -#define FLUSH_REMOVE 2 -#define FLUSH_REMOVE_WAIT 3 static long num_freeblkdep; /* number of freeblks workitems allocated */ /* @@ -7131,7 +7128,7 @@ newdirrem(bp, dp, ip, isrmdir, prevdirre */ ACQUIRE_LOCK(&lk); if (!(ip->i_flags & SF_SNAPSHOT) && num_dirrem > max_softdeps / 2) - (void) request_cleanup(ITOV(dp)->v_mount, FLUSH_REMOVE); + (void) request_cleanup(ITOV(dp)->v_mount, FLUSH_BLOCKS); num_dirrem += 1; FREE_LOCK(&lk); dirrem = malloc(sizeof(struct dirrem), @@ -10868,19 +10865,22 @@ softdep_slowdown(vp) /* * Called by the allocation routines when they are about to fail - * in the hope that we can free up some disk space. + * in the hope that we can free up the requested resource (inodes + * or 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. + * clean up entries until we successfully free the requested resource. + * 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 none of the requested resource, + * encourage the syncer daemon to help us. In no event will we try for + * longer than tickdelay seconds. */ int -softdep_request_cleanup(fs, vp) +softdep_request_cleanup(fs, vp, resource) struct fs *fs; struct vnode *vp; + int resource; { struct ufsmount *ump; long starttime; @@ -10889,7 +10889,12 @@ softdep_request_cleanup(fs, vp) ump = VTOI(vp)->i_ump; mtx_assert(UFS_MTX(ump), MA_OWNED); - needed = fs->fs_cstotal.cs_nbfree + fs->fs_contigsumsize; + if (resource == FLUSH_BLOCKS_WAIT) + needed = fs->fs_cstotal.cs_nbfree + fs->fs_contigsumsize; + else if (resource == FLUSH_INODES_WAIT) + needed = fs->fs_cstotal.cs_nifree + 2; + else + return (0); starttime = time_second + tickdelay; /* * If we are being called because of a process doing a @@ -10903,7 +10908,10 @@ softdep_request_cleanup(fs, vp) if (error != 0) return (0); } - while (fs->fs_pendingblocks > 0 && fs->fs_cstotal.cs_nbfree <= needed) { + while ((resource == FLUSH_BLOCKS_WAIT && fs->fs_pendingblocks > 0 && + fs->fs_cstotal.cs_nbfree <= needed) || + (resource == FLUSH_INODES_WAIT && fs->fs_pendinginodes > 0 && + fs->fs_cstotal.cs_nifree <= needed)) { if (time_second > starttime) return (0); UFS_UNLOCK(ump); @@ -10916,7 +10924,7 @@ softdep_request_cleanup(fs, vp) UFS_LOCK(ump); continue; } - request_cleanup(UFSTOVFS(ump), FLUSH_REMOVE_WAIT); + request_cleanup(UFSTOVFS(ump), resource); FREE_LOCK(&lk); UFS_LOCK(ump); } @@ -10963,7 +10971,9 @@ request_cleanup(mp, resource) * Next, we attempt to speed up the syncer process. If that * is successful, then we allow the process to continue. */ - if (softdep_speedup() && resource != FLUSH_REMOVE_WAIT) + if (softdep_speedup() && + resource != FLUSH_BLOCKS_WAIT && + resource != FLUSH_INODES_WAIT) return(0); /* * If we are resource constrained on inode dependencies, try @@ -10978,13 +10988,14 @@ request_cleanup(mp, resource) switch (resource) { case FLUSH_INODES: + case FLUSH_INODES_WAIT: stat_ino_limit_push += 1; req_clear_inodedeps += 1; stat_countp = &stat_ino_limit_hit; break; - case FLUSH_REMOVE: - case FLUSH_REMOVE_WAIT: + case FLUSH_BLOCKS: + case FLUSH_BLOCKS_WAIT: stat_blk_limit_push += 1; req_clear_remove += 1; stat_countp = &stat_blk_limit_hit;