1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 #include <sys/spa.h> 23 #include <sys/zio.h> 24 #include <sys/spa_impl.h> 25 #include <sys/counter.h> 26 #include <sys/zio_compress.h> 27 #include <sys/zio_checksum.h> 28 #include <sys/zfs_context.h> 29 #include <sys/arc.h> 30 #include <sys/zfs_refcount.h> 31 #include <sys/vdev.h> 32 #include <sys/vdev_trim.h> 33 #include <sys/vdev_impl.h> 34 #include <sys/dsl_pool.h> 35 #include <sys/zio_checksum.h> 36 #include <sys/multilist.h> 37 #include <sys/abd.h> 38 #include <sys/zil.h> 39 #include <sys/fm/fs/zfs.h> 40 #include <sys/eventhandler.h> 41 #include <sys/callb.h> 42 #include <sys/kstat.h> 43 #include <sys/zthr.h> 44 #include <zfs_fletcher.h> 45 #include <sys/arc_impl.h> 46 #include <sys/sdt.h> 47 #include <sys/aggsum.h> 48 #include <sys/vnode.h> 49 #include <cityhash.h> 50 #include <machine/vmparam.h> 51 #include <sys/vm.h> 52 #include <sys/vmmeter.h> 53 54 extern struct vfsops zfs_vfsops; 55 56 uint_t zfs_arc_free_target = 0; 57 58 static void 59 arc_free_target_init(void *unused __unused) 60 { 61 zfs_arc_free_target = vm_cnt.v_free_target; 62 } 63 SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY, 64 arc_free_target_init, NULL); 65 66 /* 67 * We don't have a tunable for arc_free_target due to the dependency on 68 * pagedaemon initialisation. 69 */ 70 static int 71 sysctl_vfs_zfs_arc_free_target(SYSCTL_HANDLER_ARGS) 72 { 73 uint_t val; 74 int err; 75 76 val = zfs_arc_free_target; 77 err = sysctl_handle_int(oidp, &val, 0, req); 78 if (err != 0 || req->newptr == NULL) 79 return (err); 80 81 if (val < minfree) 82 return (EINVAL); 83 if (val > vm_cnt.v_page_count) 84 return (EINVAL); 85 86 zfs_arc_free_target = val; 87 88 return (0); 89 } 90 SYSCTL_DECL(_vfs_zfs); 91 /* BEGIN CSTYLED */ 92 SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_free_target, 93 CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RW, 0, sizeof (uint_t), 94 sysctl_vfs_zfs_arc_free_target, "IU", 95 "Desired number of free pages below which ARC triggers reclaim"); 96 /* END CSTYLED */ 97 98 int64_t 99 arc_available_memory(void) 100 { 101 int64_t lowest = INT64_MAX; 102 int64_t n __unused; 103 104 /* 105 * Cooperate with pagedaemon when it's time for it to scan 106 * and reclaim some pages. 107 */ 108 n = PAGESIZE * ((int64_t)freemem - zfs_arc_free_target); 109 if (n < lowest) { 110 lowest = n; 111 } 112 #if defined(__i386) || !defined(UMA_MD_SMALL_ALLOC) 113 /* 114 * If we're on an i386 platform, it's possible that we'll exhaust the 115 * kernel heap space before we ever run out of available physical 116 * memory. Most checks of the size of the heap_area compare against 117 * tune.t_minarmem, which is the minimum available real memory that we 118 * can have in the system. However, this is generally fixed at 25 pages 119 * which is so low that it's useless. In this comparison, we seek to 120 * calculate the total heap-size, and reclaim if more than 3/4ths of the 121 * heap is allocated. (Or, in the calculation, if less than 1/4th is 122 * free) 123 */ 124 n = uma_avail() - (long)(uma_limit() / 4); 125 if (n < lowest) { 126 lowest = n; 127 } 128 #endif 129 130 DTRACE_PROBE1(arc__available_memory, int64_t, lowest); 131 return (lowest); 132 } 133 134 /* 135 * Return a default max arc size based on the amount of physical memory. 136 */ 137 uint64_t 138 arc_default_max(uint64_t min, uint64_t allmem) 139 { 140 uint64_t size; 141 142 if (allmem >= 1 << 30) 143 size = allmem - (1 << 30); 144 else 145 size = min; 146 return (MAX(allmem * 5 / 8, size)); 147 } 148 149 /* 150 * Helper function for arc_prune_async() it is responsible for safely 151 * handling the execution of a registered arc_prune_func_t. 152 */ 153 static void 154 arc_prune_task(void *arg) 155 { 156 int64_t nr_scan = *(int64_t *)arg; 157 158 arc_reduce_target_size(ptob(nr_scan)); 159 free(arg, M_TEMP); 160 vnlru_free(nr_scan, &zfs_vfsops); 161 } 162 163 /* 164 * Notify registered consumers they must drop holds on a portion of the ARC 165 * buffered they reference. This provides a mechanism to ensure the ARC can 166 * honor the arc_meta_limit and reclaim otherwise pinned ARC buffers. This 167 * is analogous to dnlc_reduce_cache() but more generic. 168 * 169 * This operation is performed asynchronously so it may be safely called 170 * in the context of the arc_reclaim_thread(). A reference is taken here 171 * for each registered arc_prune_t and the arc_prune_task() is responsible 172 * for releasing it once the registered arc_prune_func_t has completed. 173 */ 174 void 175 arc_prune_async(int64_t adjust) 176 { 177 178 int64_t *adjustptr; 179 180 if ((adjustptr = malloc(sizeof (int64_t), M_TEMP, M_NOWAIT)) == NULL) 181 return; 182 183 *adjustptr = adjust; 184 taskq_dispatch(arc_prune_taskq, arc_prune_task, adjustptr, TQ_SLEEP); 185 ARCSTAT_BUMP(arcstat_prune); 186 } 187 188 uint64_t 189 arc_all_memory(void) 190 { 191 return (ptob(physmem)); 192 } 193 194 int 195 arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg) 196 { 197 return (0); 198 } 199 200 uint64_t 201 arc_free_memory(void) 202 { 203 return (ptob(freemem)); 204 } 205 206 static eventhandler_tag arc_event_lowmem = NULL; 207 208 static void 209 arc_lowmem(void *arg __unused, int howto __unused) 210 { 211 int64_t free_memory, to_free; 212 213 arc_no_grow = B_TRUE; 214 arc_warm = B_TRUE; 215 arc_growtime = gethrtime() + SEC2NSEC(arc_grow_retry); 216 free_memory = arc_available_memory(); 217 to_free = (arc_c >> arc_shrink_shift) - MIN(free_memory, 0); 218 DTRACE_PROBE2(arc__needfree, int64_t, free_memory, int64_t, to_free); 219 arc_reduce_target_size(to_free); 220 221 /* 222 * It is unsafe to block here in arbitrary threads, because we can come 223 * here from ARC itself and may hold ARC locks and thus risk a deadlock 224 * with ARC reclaim thread. 225 */ 226 if (curproc == pageproc) 227 arc_wait_for_eviction(to_free); 228 else 229 arc_wait_for_eviction(0); 230 } 231 232 void 233 arc_lowmem_init(void) 234 { 235 arc_event_lowmem = EVENTHANDLER_REGISTER(vm_lowmem, arc_lowmem, NULL, 236 EVENTHANDLER_PRI_FIRST); 237 238 } 239 240 void 241 arc_lowmem_fini(void) 242 { 243 if (arc_event_lowmem != NULL) 244 EVENTHANDLER_DEREGISTER(vm_lowmem, arc_event_lowmem); 245 } 246