Date: Mon, 11 Aug 2008 09:24:14 GMT From: Nick Barkas <snb@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 147142 for review Message-ID: <200808110924.m7B9OEBL081618@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=147142 Change 147142 by snb@snb_toro on 2008/08/11 09:23:37 * Replace DH_RECLAIMAGE with a writeable sysctl (vfs.ufs.dirhash_reclaimage) * Fix bug where ufsdirhash_lowmem() tries to delete old locked hashes instead of skipping them, and doesn't delete the unlocked ones. * ufsdirhash_lowmem() now is more aggressive and deletes at a minimum enough dirhashes to free 10% of ufs_dirhashmem per invocation, and always deletes hashes it can older than ufs_dirhashreclaimage, as suggested by Alan Cox. Affected files ... .. //depot/projects/soc2008/snb-dirhash/sys-ufs-ufs/dirhash.h#3 edit .. //depot/projects/soc2008/snb-dirhash/sys-ufs-ufs/ufs_dirhash.c#8 edit Differences ... ==== //depot/projects/soc2008/snb-dirhash/sys-ufs-ufs/dirhash.h#3 (text+ko) ==== @@ -68,12 +68,6 @@ #define DH_SCOREINIT 8 /* initial dh_score when dirhash built */ #define DH_SCOREMAX 64 /* max dh_score value */ -/* - * If a vm_lowmem signal is received, we will try to free memory by - * deleting all hashes older than DH_RECLAIMAGE seconds. - */ -#define DH_RECLAIMAGE 5 - /* * The main hash table has 2 levels. It is an array of pointers to * blocks of DH_NBLKOFF offsets. ==== //depot/projects/soc2008/snb-dirhash/sys-ufs-ufs/ufs_dirhash.c#8 (text+ko) ==== @@ -85,6 +85,10 @@ 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 = 5; +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 ufsdirhash_hash(struct dirhash *dh, char *name, int namelen); @@ -1173,39 +1177,34 @@ { struct dirhash *dh; int memfreed = 0; + /* XXX: this 10% may need to be adjusted */ int memwanted = ufs_dirhashmem / 10; ufs_dirhashlowmemcount++; DIRHASHLIST_LOCK(); /* - * Delete dirhashes not used for more than DH_RECLAIMAGE seconds. - * If we can't get a lock on the dirhash, it will be skipped. Quit - * when we have freed up 10% or more of the memory currently used by - * dirhashes. - * XXX 10% may need to be adjusted? + * Delete dirhashes not used for more than ufs_dirhashreclaimage + * seconds. If we can't get a lock on the dirhash, it will be skipped. */ for (dh = TAILQ_FIRST(&ufsdirhash_list); dh != NULL; dh = TAILQ_NEXT(dh, dh_list)) { - if (time_second - dh->dh_lastused > DH_RECLAIMAGE && - lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) + if (lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) + continue; + if (time_second - dh->dh_lastused > ufs_dirhashreclaimage) memfreed += ufsdirhash_destroy(dh); - if (memfreed >= memwanted) - break; } /* - * If no hashes were old enough, instead try deleting a single dirhash - * from the end of the list. + * 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. */ - dh = TAILQ_FIRST(&ufsdirhash_list); - while (memfreed == 0 && dh != NULL) { - if (lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { - dh = TAILQ_NEXT(dh, dh_list); + for (dh = TAILQ_FIRST(&ufsdirhash_list); memfreed < memwanted && + dh !=NULL; dh = TAILQ_NEXT(dh, dh_list)) { + if (lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) continue; - } memfreed += ufsdirhash_destroy(dh); - break; } DIRHASHLIST_UNLOCK(); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200808110924.m7B9OEBL081618>