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