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 #if __FreeBSD_version >= 1300139 55 static struct sx arc_vnlru_lock; 56 static struct vnode *arc_vnlru_marker; 57 #endif 58 59 extern struct vfsops zfs_vfsops; 60 61 uint_t zfs_arc_free_target = 0; 62 63 static void 64 arc_free_target_init(void *unused __unused) 65 { 66 zfs_arc_free_target = vm_cnt.v_free_target; 67 } 68 SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY, 69 arc_free_target_init, NULL); 70 71 /* 72 * We don't have a tunable for arc_free_target due to the dependency on 73 * pagedaemon initialisation. 74 */ 75 static int 76 sysctl_vfs_zfs_arc_free_target(SYSCTL_HANDLER_ARGS) 77 { 78 uint_t val; 79 int err; 80 81 val = zfs_arc_free_target; 82 err = sysctl_handle_int(oidp, &val, 0, req); 83 if (err != 0 || req->newptr == NULL) 84 return (err); 85 86 if (val < minfree) 87 return (EINVAL); 88 if (val > vm_cnt.v_page_count) 89 return (EINVAL); 90 91 zfs_arc_free_target = val; 92 93 return (0); 94 } 95 SYSCTL_DECL(_vfs_zfs); 96 SYSCTL_PROC(_vfs_zfs, OID_AUTO, arc_free_target, 97 CTLTYPE_UINT | CTLFLAG_MPSAFE | CTLFLAG_RW, 0, sizeof (uint_t), 98 sysctl_vfs_zfs_arc_free_target, "IU", 99 "Desired number of free pages below which ARC triggers reclaim"); 100 101 int64_t 102 arc_available_memory(void) 103 { 104 int64_t lowest = INT64_MAX; 105 int64_t n __unused; 106 107 /* 108 * Cooperate with pagedaemon when it's time for it to scan 109 * and reclaim some pages. 110 */ 111 n = PAGESIZE * ((int64_t)freemem - zfs_arc_free_target); 112 if (n < lowest) { 113 lowest = n; 114 } 115 #if defined(__i386) || !defined(UMA_MD_SMALL_ALLOC) 116 /* 117 * If we're on an i386 platform, it's possible that we'll exhaust the 118 * kernel heap space before we ever run out of available physical 119 * memory. Most checks of the size of the heap_area compare against 120 * tune.t_minarmem, which is the minimum available real memory that we 121 * can have in the system. However, this is generally fixed at 25 pages 122 * which is so low that it's useless. In this comparison, we seek to 123 * calculate the total heap-size, and reclaim if more than 3/4ths of the 124 * heap is allocated. (Or, in the calculation, if less than 1/4th is 125 * free) 126 */ 127 n = uma_avail() - (long)(uma_limit() / 4); 128 if (n < lowest) { 129 lowest = n; 130 } 131 #endif 132 133 DTRACE_PROBE1(arc__available_memory, int64_t, lowest); 134 return (lowest); 135 } 136 137 /* 138 * Return a default max arc size based on the amount of physical memory. 139 */ 140 uint64_t 141 arc_default_max(uint64_t min, uint64_t allmem) 142 { 143 uint64_t size; 144 145 if (allmem >= 1 << 30) 146 size = allmem - (1 << 30); 147 else 148 size = min; 149 return (MAX(allmem * 5 / 8, size)); 150 } 151 152 /* 153 * Helper function for arc_prune_async() it is responsible for safely 154 * handling the execution of a registered arc_prune_func_t. 155 */ 156 static void 157 arc_prune_task(void *arg) 158 { 159 int64_t nr_scan = (intptr_t)arg; 160 161 arc_reduce_target_size(ptob(nr_scan)); 162 #if __FreeBSD_version >= 1300139 163 sx_xlock(&arc_vnlru_lock); 164 vnlru_free_vfsops(nr_scan, &zfs_vfsops, arc_vnlru_marker); 165 sx_xunlock(&arc_vnlru_lock); 166 #else 167 vnlru_free(nr_scan, &zfs_vfsops); 168 #endif 169 } 170 171 /* 172 * Notify registered consumers they must drop holds on a portion of the ARC 173 * buffered they reference. This provides a mechanism to ensure the ARC can 174 * honor the arc_meta_limit and reclaim otherwise pinned ARC buffers. This 175 * is analogous to dnlc_reduce_cache() but more generic. 176 * 177 * This operation is performed asynchronously so it may be safely called 178 * in the context of the arc_reclaim_thread(). A reference is taken here 179 * for each registered arc_prune_t and the arc_prune_task() is responsible 180 * for releasing it once the registered arc_prune_func_t has completed. 181 */ 182 void 183 arc_prune_async(int64_t adjust) 184 { 185 186 #ifndef __LP64__ 187 if (adjust > INTPTR_MAX) 188 adjust = INTPTR_MAX; 189 #endif 190 taskq_dispatch(arc_prune_taskq, arc_prune_task, 191 (void *)(intptr_t)adjust, TQ_SLEEP); 192 ARCSTAT_BUMP(arcstat_prune); 193 } 194 195 uint64_t 196 arc_all_memory(void) 197 { 198 return (ptob(physmem)); 199 } 200 201 int 202 arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg) 203 { 204 return (0); 205 } 206 207 uint64_t 208 arc_free_memory(void) 209 { 210 return (ptob(freemem)); 211 } 212 213 static eventhandler_tag arc_event_lowmem = NULL; 214 215 static void 216 arc_lowmem(void *arg __unused, int howto __unused) 217 { 218 int64_t free_memory, to_free; 219 220 arc_no_grow = B_TRUE; 221 arc_warm = B_TRUE; 222 arc_growtime = gethrtime() + SEC2NSEC(arc_grow_retry); 223 free_memory = arc_available_memory(); 224 to_free = (arc_c >> arc_shrink_shift) - MIN(free_memory, 0); 225 DTRACE_PROBE2(arc__needfree, int64_t, free_memory, int64_t, to_free); 226 arc_reduce_target_size(to_free); 227 228 /* 229 * It is unsafe to block here in arbitrary threads, because we can come 230 * here from ARC itself and may hold ARC locks and thus risk a deadlock 231 * with ARC reclaim thread. 232 */ 233 if (curproc == pageproc) 234 arc_wait_for_eviction(to_free, B_FALSE); 235 } 236 237 void 238 arc_lowmem_init(void) 239 { 240 arc_event_lowmem = EVENTHANDLER_REGISTER(vm_lowmem, arc_lowmem, NULL, 241 EVENTHANDLER_PRI_FIRST); 242 #if __FreeBSD_version >= 1300139 243 arc_vnlru_marker = vnlru_alloc_marker(); 244 sx_init(&arc_vnlru_lock, "arc vnlru lock"); 245 #endif 246 } 247 248 void 249 arc_lowmem_fini(void) 250 { 251 if (arc_event_lowmem != NULL) 252 EVENTHANDLER_DEREGISTER(vm_lowmem, arc_event_lowmem); 253 #if __FreeBSD_version >= 1300139 254 if (arc_vnlru_marker != NULL) { 255 vnlru_free_marker(arc_vnlru_marker); 256 sx_destroy(&arc_vnlru_lock); 257 } 258 #endif 259 } 260 261 void 262 arc_register_hotplug(void) 263 { 264 } 265 266 void 267 arc_unregister_hotplug(void) 268 { 269 } 270