diff options
author | kib <kib@FreeBSD.org> | 2009-08-14 11:00:38 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2009-08-14 11:00:38 +0000 |
commit | 3658df033e6752b1ee969cc6f0d1bfdce1d92898 (patch) | |
tree | cb42b686a57ae97600b63393e6952807149bde6e | |
parent | 7b967903b946c407314128c1c5fe2aa83ec6d9f0 (diff) | |
download | FreeBSD-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.c | 9 |
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); } |