Attachment 'dirhash_lowmem_event_2008-6-28.patch'

Download

   1 --- ufs_dirhash.c.orig	2008-06-05 16:24:13.000000000 -0700
   2 +++ ufs_dirhash.c	2008-06-22 18:18:39.000000000 -0700
   3 @@ -48,6 +48,7 @@
   4  #include <sys/vnode.h>
   5  #include <sys/mount.h>
   6  #include <sys/sysctl.h>
   7 +#include <sys/eventhandler.h>
   8  #include <vm/uma.h>
   9  
  10  #include <ufs/ufs/quota.h>
  11 @@ -80,6 +81,9 @@
  12  static int ufs_dirhashcheck = 0;
  13  SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_docheck, CTLFLAG_RW, &ufs_dirhashcheck,
  14      0, "enable extra sanity tests");
  15 +static int ufs_dirhashlowmemcount = 0;
  16 +SYSCTL_INT(_vfs_ufs, OID_AUTO, dirhash_lowmemcount, CTLFLAG_RD, 
  17 +    &ufs_dirhashlowmemcount, 0, "number of times low memory hook called");
  18  
  19  
  20  static int ufsdirhash_hash(struct dirhash *dh, char *name, int namelen);
  21 @@ -88,7 +92,9 @@
  22  static int ufsdirhash_findslot(struct dirhash *dh, char *name, int namelen,
  23  	   doff_t offset);
  24  static doff_t ufsdirhash_getprev(struct direct *dp, doff_t offset);
  25 +static int ufsdirhash_destroy(void);
  26  static int ufsdirhash_recycle(int wanted);
  27 +static void ufsdirhash_lowmem(void);
  28  static void ufsdirhash_free_locked(struct inode *ip);
  29  
  30  static uma_zone_t	ufsdirhash_zone;
  31 @@ -1075,17 +1081,71 @@
  32  }
  33  
  34  /*
  35 - * Try to free up `wanted' bytes by stealing memory from existing
  36 - * dirhashes. Returns zero with list locked if successful.
  37 + * Delete the first dirhash on the list and reclaim its memory. 
  38 + * Assumes that ufsdirhash_list is locked, and leaves it locked. 
  39 + * If unable to obtain a lock on the first dirhash, moves down 
  40 + * the list until it can lock a dirhash and destroys it. Returns 
  41 + * the amount of memory freed, or -1 if unable to find any 
  42 + * dirhashes that can be destroyed.
  43   */
  44  static int
  45 -ufsdirhash_recycle(int wanted)
  46 +ufsdirhash_destroy()
  47  {
  48  	struct dirhash *dh;
  49  	doff_t **hash;
  50  	u_int8_t *blkfree;
  51  	int i, mem, narrays;
  52  
  53 +	dh = TAILQ_FIRST(&ufsdirhash_list);
  54 +	if (dh == NULL)
  55 +		return (-1);
  56 +
  57 +	/*
  58 +	 * If we can't lock it it's in use and we don't want to
  59 +	 * destroy it anyway. Go on to the next in the list.
  60 +	 */
  61 +	while (lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
  62 +		dh = TAILQ_NEXT(dh, dh_list);
  63 +		if (dh == NULL)
  64 +			return (-1);
  65 +	}
  66 +	KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list"));
  67 +
  68 +	/* Remove it from the list and detach its memory. */
  69 +	TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
  70 +	dh->dh_onlist = 0;
  71 +	hash = dh->dh_hash;
  72 +	dh->dh_hash = NULL;
  73 +	blkfree = dh->dh_blkfree;
  74 +	dh->dh_blkfree = NULL;
  75 +	narrays = dh->dh_narrays;
  76 +	mem = dh->dh_memreq;
  77 +	dh->dh_memreq = 0;
  78 +
  79 +	/* Unlock everything, free the detached memory. */
  80 +	ufsdirhash_release(dh);
  81 +	DIRHASHLIST_UNLOCK();
  82 +	for (i = 0; i < narrays; i++)
  83 +		DIRHASH_BLKFREE(hash[i]);
  84 +	FREE(hash, M_DIRHASH);
  85 +	FREE(blkfree, M_DIRHASH);
  86 +
  87 +	/* Account for the returned memory. */
  88 +	DIRHASHLIST_LOCK();
  89 +	ufs_dirhashmem -= mem;	
  90 +
  91 +	return (mem);
  92 +}
  93 +
  94 +/*
  95 + * Try to free up `wanted' bytes by stealing memory from existing
  96 + * dirhashes. Returns zero with list locked if successful.
  97 + */
  98 +static int
  99 +ufsdirhash_recycle(int wanted)
 100 +{
 101 +	struct dirhash *dh;
 102 +
 103  	DIRHASHLIST_LOCK();
 104  	dh = TAILQ_FIRST(&ufsdirhash_list);
 105  	while (wanted + ufs_dirhashmem > ufs_dirhashmaxmem) {
 106 @@ -1094,44 +1154,36 @@
 107  			DIRHASHLIST_UNLOCK();
 108  			return (-1);
 109  		}
 110 -		/*
 111 -		 * If we can't lock it it's in use and we don't want to
 112 -		 * recycle it anyway.
 113 -		 */
 114 -		if (lockmgr(&dh->dh_lock, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
 115 -			dh = TAILQ_NEXT(dh, dh_list);
 116 -			continue;
 117 -		}
 118 -		KASSERT(dh->dh_hash != NULL, ("dirhash: NULL hash on list"));
 119  
 120 -		/* Remove it from the list and detach its memory. */
 121 -		TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
 122 -		dh->dh_onlist = 0;
 123 -		hash = dh->dh_hash;
 124 -		dh->dh_hash = NULL;
 125 -		blkfree = dh->dh_blkfree;
 126 -		dh->dh_blkfree = NULL;
 127 -		narrays = dh->dh_narrays;
 128 -		mem = dh->dh_memreq;
 129 -		dh->dh_memreq = 0;
 130 +		/* Try deleting a dirhash. Give up if we can't delete any. */
 131 +		if (ufsdirhash_destroy() < 0)
 132 +			return (-1);
 133  
 134 -		/* Unlock everything, free the detached memory. */
 135 -		ufsdirhash_release(dh);
 136 -		DIRHASHLIST_UNLOCK();
 137 -		for (i = 0; i < narrays; i++)
 138 -			DIRHASH_BLKFREE(hash[i]);
 139 -		FREE(hash, M_DIRHASH);
 140 -		FREE(blkfree, M_DIRHASH);
 141 -
 142 -		/* Account for the returned memory, and repeat if necessary. */
 143 -		DIRHASHLIST_LOCK();
 144 -		ufs_dirhashmem -= mem;
 145 +		/* Repeat if necessary. */
 146  		dh = TAILQ_FIRST(&ufsdirhash_list);
 147  	}
 148  	/* Success; return with list locked. */
 149  	return (0);
 150  }
 151  
 152 +/*
 153 + * Calback that frees some dirhashes when the system is low on virtual memory.
 154 + */
 155 +static void
 156 +ufsdirhash_lowmem()
 157 +{
 158 +	ufs_dirhashlowmemcount++;
 159 +
 160 +	DIRHASHLIST_LOCK();
 161 +	if (ufs_dirhashmem > 0)
 162 +		/* 
 163 +		 * Try deleting only one dirhash for now, and don't bother  
 164 +		 * to check if it worked.
 165 +		 */
 166 +		ufsdirhash_destroy();
 167 +	DIRHASHLIST_UNLOCK();
 168 +}
 169 +
 170  
 171  void
 172  ufsdirhash_init()
 173 @@ -1140,6 +1192,10 @@
 174  	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
 175  	mtx_init(&ufsdirhash_mtx, "dirhash list", NULL, MTX_DEF);
 176  	TAILQ_INIT(&ufsdirhash_list);
 177 +	
 178 +	/* Register a callback function to handle low memory signals */
 179 +	EVENTHANDLER_REGISTER(vm_lowmem, ufsdirhash_lowmem, NULL, 
 180 +	    EVENTHANDLER_PRI_FIRST);
 181  }
 182  
 183  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.