summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authordavide <davide@FreeBSD.org>2014-08-25 17:06:18 +0000
committerdavide <davide@FreeBSD.org>2014-08-25 17:06:18 +0000
commita8c92b02a83a5428c0dffa17afd962f57687bd73 (patch)
tree1595c8d91df052a8986ff68d8f1e06552d035bf9 /sys/ufs
parent36a18518ac75939d8e43702e6a9c4f79c741814f (diff)
downloadFreeBSD-src-a8c92b02a83a5428c0dffa17afd962f57687bd73.zip
FreeBSD-src-a8c92b02a83a5428c0dffa17afd962f57687bd73.tar.gz
Rather than using an hardcoded reclaim age, rely on an LRU-like approach
for dirhash cache, setting a target percent to reclaim (exposed via SYSCTL). This allows to always make some amount of progress keeping the maximum reclaim age dynamic. Tested by: pho Reviewed by: jhb
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ufs/ufs_dirhash.c55
1 files changed, 19 insertions, 36 deletions
diff --git a/sys/ufs/ufs/ufs_dirhash.c b/sys/ufs/ufs/ufs_dirhash.c
index 5c29923..476ec38 100644
--- a/sys/ufs/ufs/ufs_dirhash.c
+++ b/sys/ufs/ufs/ufs_dirhash.c
@@ -85,10 +85,10 @@ SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_docheck, CTLFLAG_RW, &ufs_dirhashcheck,
static int ufs_dirhashlowmemcount = 0;
SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_lowmemcount, CTLFLAG_RD,
&ufs_dirhashlowmemcount, 0, "number of times low memory hook called");
-static int ufs_dirhashreclaimage = 60;
-SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_reclaimage, CTLFLAG_RW,
- &ufs_dirhashreclaimage, 0,
- "max time in seconds of hash inactivity before deletion in low VM events");
+static int ufs_dirhash_reclaimperc = 10;
+SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_reclaimperc, CTLFLAG_RW,
+ &ufs_dirhash_reclaimperc, 0,
+ "percentage of dirhash cache to be removed in low VM events");
static int ufsdirhash_hash(struct dirhash *dh, char *name, int namelen);
@@ -1247,45 +1247,28 @@ static void
ufsdirhash_lowmem()
{
struct dirhash *dh, *dh_temp;
- int memfreed = 0;
- /*
- * Will free a *minimum* of 10% of the dirhash, but possibly much
- * more (depending on dirhashreclaimage). System with large dirhashes
- * probably also need a much larger dirhashreclaimage.
- * XXX: this percentage may need to be adjusted.
- */
- int memwanted = ufs_dirhashmem / 10;
+ int memfreed, memwanted;
ufs_dirhashlowmemcount++;
+ memfreed = 0;
+ memwanted = ufs_dirhashmem / ufs_dirhash_reclaimperc;
DIRHASHLIST_LOCK();
- /*
- * Delete dirhashes not used for more than ufs_dirhashreclaimage
- * seconds. If we can't get a lock on the dirhash, it will be skipped.
- */
- TAILQ_FOREACH_SAFE(dh, &ufsdirhash_list, dh_list, dh_temp) {
- if (!sx_try_xlock(&dh->dh_lock))
- continue;
- if (time_second - dh->dh_lastused > ufs_dirhashreclaimage)
- memfreed += ufsdirhash_destroy(dh);
- /* Unlock if we didn't delete the dirhash */
- else
- ufsdirhash_release(dh);
- }
- /*
- * If not enough memory was freed, keep deleting hashes from the head
- * of the dirhash list. The ones closest to the head should be the
- * oldest.
+ /*
+ * Reclaim up to memwanted from the oldest dirhashes. This will allow
+ * us to make some progress when the system is running out of memory
+ * without compromising the dinamicity of maximum age. If the situation
+ * does not improve lowmem will be eventually retriggered and free some
+ * other entry in the cache. The entries on the head of the list should
+ * be the oldest. If during list traversal we can't get a lock on the
+ * dirhash, it will be skipped.
*/
- if (memfreed < memwanted) {
- TAILQ_FOREACH_SAFE(dh, &ufsdirhash_list, dh_list, dh_temp) {
- if (!sx_try_xlock(&dh->dh_lock))
- continue;
+ TAILQ_FOREACH_SAFE(dh, &ufsdirhash_list, dh_list, dh_temp) {
+ if (sx_try_xlock(&dh->dh_lock))
memfreed += ufsdirhash_destroy(dh);
- if (memfreed >= memwanted)
- break;
- }
+ if (memfreed >= memwanted)
+ break;
}
DIRHASHLIST_UNLOCK();
}
OpenPOWER on IntegriCloud