PERFORCE change 143807 for review
Nick Barkas
snb at FreeBSD.org
Fri Jun 20 08:54:37 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=143807
Change 143807 by snb at snb_toro on 2008/06/20 08:54:17
First cut at deleting a single dirhash whenever a vm_lowmem event
occurs. Untested.
Affected files ...
.. //depot/projects/soc2008/snb-dirhash/sys-ufs-ufs/ufs_dirhash.c#3 edit
Differences ...
==== //depot/projects/soc2008/snb-dirhash/sys-ufs-ufs/ufs_dirhash.c#3 (text+ko) ====
@@ -89,7 +89,9 @@
static int ufsdirhash_findslot(struct dirhash *dh, char *name, int namelen,
doff_t offset);
static doff_t ufsdirhash_getprev(struct direct *dp, doff_t offset);
+static int ufsdirhash_destroy(void);
static int ufsdirhash_recycle(int wanted);
+static void ufsdirhash_lowmem(void);
static void ufsdirhash_free_locked(struct inode *ip);
static uma_zone_t ufsdirhash_zone;
@@ -1076,6 +1078,62 @@
}
/*
+ * Delete the first dirhash on the list and reclaim its memory.
+ * Assumes that ufsdirhash_list is locked, and leaves it locked.
+ * If unable to obtain a lock on the first dirhash, moves down
+ * the list until it can lock a dirhash and destroys it. Returns
+ * -1 if unable to find any dirhashes that can be destroyed.
+ */
+static int
+ufsdirhash_destroy()
+{
+ struct dirhash *dh;
+ doff_t **hash;
+ u_int8_t *blkfree;
+ int i, mem, narrays;
+
+ dh = TAILQ_FIRST(&ufsdirhash_list);
+ if (dh == NULL)
+ return (-1);
+
+ /*
+ * If we can't lock it it's in use and we don't want to
+ * destroy it anyway. Go on to the next in the list.
+ */
+ while (lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
+ dh = TAILQ_NEXT(dh, dh_list);
+ if (dh == NULL)
+ return (-1);
+ }
+ KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list"));
+
+ /* Remove it from the list and detach its memory. */
+ TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
+ dh->dh_onlist = 0;
+ hash = dh->dh_hash;
+ dh->dh_hash = NULL;
+ blkfree = dh->dh_blkfree;
+ dh->dh_blkfree = NULL;
+ narrays = dh->dh_narrays;
+ mem = dh->dh_memreq;
+ dh->dh_memreq = 0;
+
+ /* Unlock everything, free the detached memory. */
+ ufsdirhash_release(dh);
+ DIRHASHLIST_UNLOCK();
+ for (i = 0; i < narrays; i++)
+ DIRHASH_BLKFREE(hash[i]);
+ FREE(hash, M_DIRHASH);
+ FREE(blkfree, M_DIRHASH);
+
+ /* Account for the returned memory. */
+ DIRHASHLIST_LOCK();
+ ufs_dirhashmem -= mem;
+
+ return (0);
+}
+
+/*
* Try to free up `wanted' bytes by stealing memory from existing
* dirhashes. Returns zero with list locked if successful.
*/
@@ -1083,9 +1141,6 @@
ufsdirhash_recycle(int wanted)
{
struct dirhash *dh;
- doff_t **hash;
- u_int8_t *blkfree;
- int i, mem, narrays;
DIRHASHLIST_LOCK();
dh = TAILQ_FIRST(&ufsdirhash_list);
@@ -1095,38 +1150,12 @@
DIRHASHLIST_UNLOCK();
return (-1);
}
- /*
- * If we can't lock it it's in use and we don't want to
- * recycle it anyway.
- */
- if (lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
- dh = TAILQ_NEXT(dh, dh_list);
- continue;
- }
- KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list"));
- /* Remove it from the list and detach its memory. */
- TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
- dh->dh_onlist = 0;
- hash = dh->dh_hash;
- dh->dh_hash = NULL;
- blkfree = dh->dh_blkfree;
- dh->dh_blkfree = NULL;
- narrays = dh->dh_narrays;
- mem = dh->dh_memreq;
- dh->dh_memreq = 0;
+ /* Try deleting a dirhash. Give up if we can't delete any. */
+ if (ufsdirhash_destroy() < 0)
+ return (-1);
- /* Unlock everything, free the detached memory. */
- ufsdirhash_release(dh);
- DIRHASHLIST_UNLOCK();
- for (i = 0; i < narrays; i++)
- DIRHASH_BLKFREE(hash[i]);
- FREE(hash, M_DIRHASH);
- FREE(blkfree, M_DIRHASH);
-
- /* Account for the returned memory, and repeat if necessary. */
- DIRHASHLIST_LOCK();
- ufs_dirhashmem -= mem;
+ /* Repeat if necessary. */
dh = TAILQ_FIRST(&ufsdirhash_list);
}
/* Success; return with list locked. */
@@ -1139,7 +1168,16 @@
static void
ufsdirhash_lowmem()
{
-
+ /* XXX: temporary silly way of notifying when this is called */
+ printf("dirhash: ufsdirhash_lowmem() called\n");
+
+ DIRHASHLIST_LOCK();
+ /*
+ * Try deleting only one dirhash for now, and don't bother
+ * to check if it worked.
+ */
+ ufsdirhash_destroy();
+ DIRHASHLIST_UNLOCK();
}
More information about the p4-projects
mailing list