Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Sep 2015 13:07:27 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r287361 - head/sys/ufs/ffs
Message-ID:  <201509011307.t81D7R1G000644@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Tue Sep  1 13:07:27 2015
New Revision: 287361
URL: https://svnweb.freebsd.org/changeset/base/287361

Log:
  By doing file extension fast, it is possible to create excess supply
  of the D_NEWBLK kinds of dependencies (i.e. D_ALLOCDIRECT and
  D_ALLOCINDIR), which can exhaust kmem.
  
  Handle excess of D_NEWBLK in the same way as excess of D_INODEDEP and
  D_DIRREM, by scheduling ast to flush dependencies, after the thread,
  which created new dep, left the VFS/FFS innards.  For D_NEWBLK, the
  only way to get rid of them is to do full sync, since items are
  attached to data blocks of arbitrary vnodes.  The check for D_NEWBLK
  excess in softdep_ast_cleanup_proc() is unlocked.
  
  For 32bit arches, reduce the total amount of allowed dependencies by
  two.  It could be considered increasing the limit for 64 bit platforms
  with direct maps.
  
  Reported and tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/ufs/ffs/ffs_softdep.c

Modified: head/sys/ufs/ffs/ffs_softdep.c
==============================================================================
--- head/sys/ufs/ffs/ffs_softdep.c	Tue Sep  1 12:47:11 2015	(r287360)
+++ head/sys/ufs/ffs/ffs_softdep.c	Tue Sep  1 13:07:27 2015	(r287361)
@@ -923,8 +923,7 @@ static	int journal_unsuspend(struct ufsm
 static	void softdep_prelink(struct vnode *, struct vnode *);
 static	void add_to_journal(struct worklist *);
 static	void remove_from_journal(struct worklist *);
-static	bool softdep_excess_inodes(struct ufsmount *);
-static	bool softdep_excess_dirrem(struct ufsmount *);
+static	bool softdep_excess_items(struct ufsmount *, int);
 static	void softdep_process_journal(struct mount *, struct worklist *, int);
 static	struct jremref *newjremref(struct dirrem *, struct inode *,
 	    struct inode *ip, off_t, nlink_t);
@@ -2212,7 +2211,7 @@ inodedep_lookup(mp, inum, flags, inodede
 	 * responsible for more than our share of that usage and
 	 * we are not in a rush, request some inodedep cleanup.
 	 */
-	if (softdep_excess_inodes(ump))
+	if (softdep_excess_items(ump, D_INODEDEP))
 		schedule_cleanup(mp);
 	else
 		FREE_LOCK(ump);
@@ -2307,7 +2306,12 @@ newblk_lookup(mp, newblkno, flags, newbl
 		return (1);
 	if ((flags & DEPALLOC) == 0)
 		return (0);
-	FREE_LOCK(ump);
+	if (softdep_excess_items(ump, D_NEWBLK) ||
+	    softdep_excess_items(ump, D_ALLOCDIRECT) ||
+	    softdep_excess_items(ump, D_ALLOCINDIR))
+		schedule_cleanup(mp);
+	else
+		FREE_LOCK(ump);
 	newblk = malloc(sizeof(union allblk), M_NEWBLK,
 	    M_SOFTDEP_FLAGS | M_ZERO);
 	workitem_alloc(&newblk->nb_list, D_NEWBLK, mp);
@@ -2406,7 +2410,11 @@ softdep_initialize()
 {
 
 	TAILQ_INIT(&softdepmounts);
+#ifdef __LP64__
 	max_softdeps = desiredvnodes * 4;
+#else
+	max_softdeps = desiredvnodes * 2;
+#endif
 
 	/* initialise bioops hack */
 	bioops.io_start = softdep_disk_io_initiation;
@@ -9106,7 +9114,7 @@ newdirrem(bp, dp, ip, isrmdir, prevdirre
 	 * the number of freefile and freeblks structures.
 	 */
 	ACQUIRE_LOCK(ip->i_ump);
-	if (!IS_SNAPSHOT(ip) && softdep_excess_dirrem(ip->i_ump))
+	if (!IS_SNAPSHOT(ip) && softdep_excess_items(ip->i_ump, D_DIRREM))
 		schedule_cleanup(ITOV(dp)->v_mount);
 	else
 		FREE_LOCK(ip->i_ump);
@@ -13244,20 +13252,12 @@ retry:
 }
 
 static bool
-softdep_excess_inodes(struct ufsmount *ump)
+softdep_excess_items(struct ufsmount *ump, int item)
 {
 
-	return (dep_current[D_INODEDEP] > max_softdeps &&
-	    ump->softdep_curdeps[D_INODEDEP] > max_softdeps /
-	    stat_flush_threads);
-}
-
-static bool
-softdep_excess_dirrem(struct ufsmount *ump)
-{
-
-	return (dep_current[D_DIRREM] > max_softdeps / 2 &&
-	    ump->softdep_curdeps[D_DIRREM] > (max_softdeps / 2) /
+	KASSERT(item >= 0 && item < D_LAST, ("item %d", item));
+	return (dep_current[item] > max_softdeps &&
+	    ump->softdep_curdeps[item] > max_softdeps /
 	    stat_flush_threads);
 }
 
@@ -13313,15 +13313,21 @@ softdep_ast_cleanup_proc(void)
 		for (;;) {
 			req = false;
 			ACQUIRE_LOCK(ump);
-			if (softdep_excess_inodes(ump)) {
+			if (softdep_excess_items(ump, D_INODEDEP)) {
 				req = true;
 				request_cleanup(mp, FLUSH_INODES);
 			}
-			if (softdep_excess_dirrem(ump)) {
+			if (softdep_excess_items(ump, D_DIRREM)) {
 				req = true;
 				request_cleanup(mp, FLUSH_BLOCKS);
 			}
 			FREE_LOCK(ump);
+			if (softdep_excess_items(ump, D_NEWBLK) ||
+			    softdep_excess_items(ump, D_ALLOCDIRECT) ||
+			    softdep_excess_items(ump, D_ALLOCINDIR)) {
+				req = true;
+				VFS_SYNC(mp, MNT_WAIT);
+			}
 			if ((td->td_pflags & TDP_KTHREAD) != 0 || !req)
 				break;
 		}



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