summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2009-08-14 11:00:38 +0000
committerkib <kib@FreeBSD.org>2009-08-14 11:00:38 +0000
commit3658df033e6752b1ee969cc6f0d1bfdce1d92898 (patch)
treecb42b686a57ae97600b63393e6952807149bde6e
parent7b967903b946c407314128c1c5fe2aa83ec6d9f0 (diff)
downloadFreeBSD-src-3658df033e6752b1ee969cc6f0d1bfdce1d92898.zip
FreeBSD-src-3658df033e6752b1ee969cc6f0d1bfdce1d92898.tar.gz
When a UFS node is truncated to the zero length, e.g. by explicit
truncate(2) call, or by being removed or truncated on open, either new softupdate freeblks structure is allocated to track the freed blocks of the node, or truncation is done syncronously when too many SU dependencies are accumulated. The decision does not take into account the allocated freeblks dependencies, allowing workloads that do huge amount of truncations to exhaust the kernel memory. Take the number of allocated freeblks into consideration for softdep_slowdown(). Reported by: pluknet gmail com Diagnosed and tested by: pho Approved by: re (rwatson) MFC after: 1 month
-rw-r--r--sys/ufs/ffs/ffs_softdep.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 72522b2..5f16280 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -663,6 +663,8 @@ static int req_clear_inodedeps; /* syncer process flush some inodedeps */
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 */
+
/*
* runtime statistics
*/
@@ -2223,6 +2225,9 @@ softdep_setup_freeblocks(ip, length, flags)
freeblks->fb_uid = ip->i_uid;
freeblks->fb_previousinum = ip->i_number;
freeblks->fb_devvp = ip->i_devvp;
+ ACQUIRE_LOCK(&lk);
+ num_freeblkdep++;
+ FREE_LOCK(&lk);
extblocks = 0;
if (fs->fs_magic == FS_UFS2_MAGIC)
extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize));
@@ -2815,6 +2820,7 @@ handle_workitem_freeblocks(freeblks, flags)
ACQUIRE_LOCK(&lk);
WORKITEM_FREE(freeblks, D_FREEBLKS);
+ num_freeblkdep--;
FREE_LOCK(&lk);
}
@@ -5768,7 +5774,8 @@ softdep_slowdown(vp)
max_softdeps_hard = max_softdeps * 11 / 10;
if (num_dirrem < max_softdeps_hard / 2 &&
num_inodedep < max_softdeps_hard &&
- VFSTOUFS(vp->v_mount)->um_numindirdeps < maxindirdeps) {
+ VFSTOUFS(vp->v_mount)->um_numindirdeps < maxindirdeps &&
+ num_freeblkdep < max_softdeps_hard) {
FREE_LOCK(&lk);
return (0);
}
OpenPOWER on IntegriCloud