Attachment 'dirhash_lowmem_event_2008-7-12.patch'

Download

   1 ==== //depot/projects/soc2008/snb-dirhash/sys-ufs-ufs/dirhash.h#1 - /Users/snb/Documents/soc/perforce/snb-dirhash/sys-ufs-ufs/dirhash.h ====
   2 --- /tmp/tmp.23276.25	2008-07-07 23:06:16.000000000 +0200
   3 +++ /Users/snb/Documents/soc/perforce/snb-dirhash/sys-ufs-ufs/dirhash.h	2008-07-06 23:16:04.000000000 +0200
   4 @@ -68,6 +68,12 @@
   5  #define DH_SCOREINIT	8	/* initial dh_score when dirhash built */
   6  #define DH_SCOREMAX	64	/* max dh_score value */
   7  
   8 +/* 
   9 + * If a vm_lowmem signal is received, we will try to free memory by 
  10 + * deleting all hashes older than DH_RECLAIMAGE seconds. 
  11 + */
  12 +#define DH_RECLAIMAGE	5
  13 +
  14  /*
  15   * The main hash table has 2 levels. It is an array of pointers to
  16   * blocks of DH_NBLKOFF offsets.
  17 @@ -101,6 +107,8 @@
  18  
  19  	int	dh_onlist;	/* true if on the ufsdirhash_list chain */
  20  
  21 +	time_t	dh_lastused;	/* time the dirhash was last read or written*/
  22 +
  23  	/* Protected by ufsdirhash_mtx. */
  24  	TAILQ_ENTRY(dirhash) dh_list;	/* chain of all dirhashes */
  25  };
  26 ==== //depot/projects/soc2008/snb-dirhash/sys-ufs-ufs/ufs_dirhash.c#1 - /Users/snb/Documents/soc/perforce/snb-dirhash/sys-ufs-ufs/ufs_dirhash.c ====
  27 --- /tmp/tmp.23276.28	2008-07-07 23:06:16.000000000 +0200
  28 +++ /Users/snb/Documents/soc/perforce/snb-dirhash/sys-ufs-ufs/ufs_dirhash.c	2008-07-07 14:10:15.000000000 +0200
  29 @@ -48,6 +48,8 @@
  30  #include <sys/vnode.h>
  31  #include <sys/mount.h>
  32  #include <sys/sysctl.h>
  33 +#include <sys/eventhandler.h>
  34 +#include <sys/time.h>
  35  #include <vm/uma.h>
  36  
  37  #include <ufs/ufs/quota.h>
  38 @@ -80,6 +82,9 @@
  39  static int ufs_dirhashcheck = 0;
  40  SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_docheck, CTLFLAG_RW, &ufs_dirhashcheck,
  41      0, "enable extra sanity tests");
  42 +static int ufs_dirhashlowmemcount = 0;
  43 +SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_lowmemcount, CTLFLAG_RD, 
  44 +    &ufs_dirhashlowmemcount, 0, "number of times low memory hook called");
  45  
  46  
  47  static int ufsdirhash_hash(struct dirhash *dh, char *name, int namelen);
  48 @@ -88,7 +93,9 @@
  49  static int ufsdirhash_findslot(struct dirhash *dh, char *name, int namelen,
  50  	   doff_t offset);
  51  static doff_t ufsdirhash_getprev(struct direct *dp, doff_t offset);
  52 +static int ufsdirhash_destroy(struct dirhash *dh);
  53  static int ufsdirhash_recycle(int wanted);
  54 +static void ufsdirhash_lowmem(void);
  55  static void ufsdirhash_free_locked(struct inode *ip);
  56  
  57  static uma_zone_t	ufsdirhash_zone;
  58 @@ -324,6 +331,7 @@
  59  	dh->dh_seqopt = 0;
  60  	dh->dh_seqoff = 0;
  61  	dh->dh_score = DH_SCOREINIT;
  62 +	dh->dh_lastused = time_second;
  63  
  64  	/*
  65  	 * Use non-blocking mallocs so that we will revert to a linear
  66 @@ -494,6 +502,9 @@
  67  	/* Update the score. */
  68  	if (dh->dh_score < DH_SCOREMAX)
  69  		dh->dh_score++;
  70 +
  71 +	/* Update last used time. */
  72 +	dh->dh_lastused = time_second;
  73  	DIRHASHLIST_UNLOCK();
  74  
  75  	vp = ip->i_vnode;
  76 @@ -736,6 +747,9 @@
  77  		dh->dh_hused++;
  78  	DH_ENTRY(dh, slot) = offset;
  79  
  80 +	/* Update last used time. */
  81 +	dh->dh_lastused = time_second;
  82 +
  83  	/* Update the per-block summary info. */
  84  	ufsdirhash_adjfree(dh, offset, -DIRSIZ(0, dirp));
  85  	ufsdirhash_release(dh);
  86 @@ -1075,6 +1089,46 @@
  87  }
  88  
  89  /*
  90 + * Delete the given dirhash and reclaim its memory. Assumes that 
  91 + * ufsdirhash_list is locked, and leaves it locked. Also assumes 
  92 + * that dh is locked. Returns the amount of memory freed.
  93 + */
  94 +static int
  95 +ufsdirhash_destroy(struct dirhash *dh)
  96 +{
  97 +	doff_t **hash;
  98 +	u_int8_t *blkfree;
  99 +	int i, mem, narrays;
 100 +
 101 +	KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list"));
 102 +
 103 +	/* Remove it from the list and detach its memory. */
 104 +	TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
 105 +	dh->dh_onlist = 0;
 106 +	hash = dh->dh_hash;
 107 +	dh->dh_hash = NULL;
 108 +	blkfree = dh->dh_blkfree;
 109 +	dh->dh_blkfree = NULL;
 110 +	narrays = dh->dh_narrays;
 111 +	mem = dh->dh_memreq;
 112 +	dh->dh_memreq = 0;
 113 +
 114 +	/* Unlock everything, free the detached memory. */
 115 +	ufsdirhash_release(dh);
 116 +	DIRHASHLIST_UNLOCK();
 117 +	for (i = 0; i < narrays; i++)
 118 +		DIRHASH_BLKFREE(hash[i]);
 119 +	FREE(hash, M_DIRHASH);
 120 +	FREE(blkfree, M_DIRHASH);
 121 +
 122 +	/* Account for the returned memory. */
 123 +	DIRHASHLIST_LOCK();
 124 +	ufs_dirhashmem -= mem;
 125 +
 126 +	return (mem);
 127 +}
 128 +
 129 +/*
 130   * Try to free up `wanted' bytes by stealing memory from existing
 131   * dirhashes. Returns zero with list locked if successful.
 132   */
 133 @@ -1082,9 +1136,6 @@
 134  ufsdirhash_recycle(int wanted)
 135  {
 136  	struct dirhash *dh;
 137 -	doff_t **hash;
 138 -	u_int8_t *blkfree;
 139 -	int i, mem, narrays;
 140  
 141  	DIRHASHLIST_LOCK();
 142  	dh = TAILQ_FIRST(&ufsdirhash_list);
 143 @@ -1094,6 +1145,7 @@
 144  			DIRHASHLIST_UNLOCK();
 145  			return (-1);
 146  		}
 147 +
 148  		/*
 149  		 * If we can't lock it it's in use and we don't want to
 150  		 * recycle it anyway.
 151 @@ -1102,36 +1154,54 @@
 152  			dh = TAILQ_NEXT(dh, dh_list);
 153  			continue;
 154  		}
 155 -		KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list"));
 156  
 157 -		/* Remove it from the list and detach its memory. */
 158 -		TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
 159 -		dh->dh_onlist = 0;
 160 -		hash = dh->dh_hash;
 161 -		dh->dh_hash = NULL;
 162 -		blkfree = dh->dh_blkfree;
 163 -		dh->dh_blkfree = NULL;
 164 -		narrays = dh->dh_narrays;
 165 -		mem = dh->dh_memreq;
 166 -		dh->dh_memreq = 0;
 167 +		ufsdirhash_destroy(dh);
 168  
 169 -		/* Unlock everything, free the detached memory. */
 170 -		ufsdirhash_release(dh);
 171 -		DIRHASHLIST_UNLOCK();
 172 -		for (i = 0; i < narrays; i++)
 173 -			DIRHASH_BLKFREE(hash[i]);
 174 -		FREE(hash, M_DIRHASH);
 175 -		FREE(blkfree, M_DIRHASH);
 176 -
 177 -		/* Account for the returned memory, and repeat if necessary. */
 178 -		DIRHASHLIST_LOCK();
 179 -		ufs_dirhashmem -= mem;
 180 +		/* Repeat if necessary. */
 181  		dh = TAILQ_FIRST(&ufsdirhash_list);
 182  	}
 183  	/* Success; return with list locked. */
 184  	return (0);
 185  }
 186  
 187 +/*
 188 + * Calback that frees some dirhashes when the system is low on virtual memory.
 189 + */
 190 +static void
 191 +ufsdirhash_lowmem()
 192 +{
 193 +	struct dirhash *dh;
 194 +	int memfreed = 0;
 195 +
 196 +	ufs_dirhashlowmemcount++;
 197 +
 198 +	DIRHASHLIST_LOCK();
 199 +	/* 
 200 +	 * Delete all dirhashes not used for more than DH_RECLAIMAGE seconds. 
 201 +	 * If we can't get a lock on the dirhash, it will be skipped.
 202 +	 */
 203 +	for (dh = TAILQ_FIRST(&ufsdirhash_list); dh != NULL; dh = 
 204 +	     TAILQ_NEXT(dh, dh_list)) {
 205 +		if (time_second - dh->dh_lastused > DH_RECLAIMAGE && 
 206 +		    lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL))
 207 +			memfreed += ufsdirhash_destroy(dh);
 208 +	}
 209 +	
 210 +	/* 
 211 +	 * If no hashes were old enough, instead try deleting a single dirhash 
 212 +	 * from the end of the list.
 213 +	 */
 214 +	dh = TAILQ_FIRST(&ufsdirhash_list);
 215 +	while (memfreed == 0 && dh != NULL) {
 216 +		if (lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
 217 +			dh = TAILQ_NEXT(dh, dh_list);
 218 +			continue;
 219 +		}
 220 +		memfreed += ufsdirhash_destroy(dh);
 221 +	}
 222 +	DIRHASHLIST_UNLOCK();
 223 +}
 224 +
 225  
 226  void
 227  ufsdirhash_init()
 228 @@ -1140,6 +1210,10 @@
 229  	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
 230  	mtx_init(&ufsdirhash_mtx, "dirhash list", NULL, MTX_DEF);
 231  	TAILQ_INIT(&ufsdirhash_list);
 232 +	
 233 +	/* Register a callback function to handle low memory signals */
 234 +	EVENTHANDLER_REGISTER(vm_lowmem, ufsdirhash_lowmem, NULL, 
 235 +	    EVENTHANDLER_PRI_FIRST);
 236  }
 237  
 238  void

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.