1 // SPDX-License-Identifier: CDDL-1.0 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License (the "License"). 7 * You may not use this file except in compliance with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or https://opensource.org/licenses/CDDL-1.0. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 #include <sys/spa.h> 24 #include <sys/zio.h> 25 #include <sys/spa_impl.h> 26 #include <sys/counter.h> 27 #include <sys/zio_compress.h> 28 #include <sys/zio_checksum.h> 29 #include <sys/zfs_context.h> 30 #include <sys/arc.h> 31 #include <sys/arc_os.h> 32 #include <sys/zfs_refcount.h> 33 #include <sys/vdev.h> 34 #include <sys/vdev_trim.h> 35 #include <sys/vdev_impl.h> 36 #include <sys/dsl_pool.h> 37 #include <sys/zio_checksum.h> 38 #include <sys/multilist.h> 39 #include <sys/abd.h> 40 #include <sys/zil.h> 41 #include <sys/fm/fs/zfs.h> 42 #include <sys/eventhandler.h> 43 #include <sys/callb.h> 44 #include <sys/kstat.h> 45 #include <sys/zthr.h> 46 #include <zfs_fletcher.h> 47 #include <sys/arc_impl.h> 48 #include <sys/sdt.h> 49 #include <sys/aggsum.h> 50 #include <sys/vnode.h> 51 #include <cityhash.h> 52 #include <machine/vmparam.h> 53 #include <sys/vm.h> 54 #include <sys/vmmeter.h> 55 56 extern struct vfsops zfs_vfsops; 57 58 uint_t zfs_arc_free_target = 0; 59 60 static void 61 arc_free_target_init(void *unused __unused) 62 { 63 zfs_arc_free_target = vm_cnt.v_free_target; 64 } 65 SYSINIT(arc_free_target_init, SI_SUB_KTHREAD_PAGE, SI_ORDER_ANY, 66 arc_free_target_init, NULL); 67 68 /* 69 * We don't have a tunable for arc_free_target due to the dependency on 70 * pagedaemon initialisation. 71 */ 72 ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, free_target, 73 param_set_arc_free_target, 0, CTLFLAG_RW, 74 "Desired number of free pages below which ARC triggers reclaim"); 75 ZFS_MODULE_PARAM_CALL(zfs_arc, zfs_arc_, no_grow_shift, 76 param_set_arc_no_grow_shift, 0, ZMOD_RW, 77 "log2(fraction of ARC which must be free to allow growing)"); 78 79 int64_t 80 arc_available_memory(void) 81 { 82 int64_t lowest = INT64_MAX; 83 int64_t n __unused; 84 85 /* 86 * Cooperate with pagedaemon when it's time for it to scan 87 * and reclaim some pages. 88 */ 89 n = PAGESIZE * ((int64_t)freemem - zfs_arc_free_target); 90 if (n < lowest) { 91 lowest = n; 92 } 93 #if !defined(UMA_MD_SMALL_ALLOC) && !defined(UMA_USE_DMAP) 94 /* 95 * If we're on a platform without a direct map, it's possible that we'll 96 * exhaust the kernel heap space before we ever run out of available 97 * physical memory. Most checks of the size of the heap_area compare 98 * against tune.t_minarmem, which is the minimum available real memory 99 * that we can have in the system. However, this is generally fixed at 100 * 25 pages which is so low that it's useless. In this comparison, we 101 * seek to calculate the total heap-size, and reclaim if more than 102 * 3/4ths of the heap is allocated. (Or, in the calculation, if less 103 * than 1/4th is free) 104 */ 105 n = uma_avail() - (long)(uma_limit() / 4); 106 if (n < lowest) { 107 lowest = n; 108 } 109 #endif 110 111 DTRACE_PROBE1(arc__available_memory, int64_t, lowest); 112 return (lowest); 113 } 114 115 /* 116 * Return a default max arc size based on the amount of physical memory. 117 */ 118 uint64_t 119 arc_default_max(uint64_t min, uint64_t allmem) 120 { 121 uint64_t size; 122 123 if (allmem >= 1 << 30) 124 size = allmem - (1 << 30); 125 else 126 size = min; 127 return (MAX(allmem * 5 / 8, size)); 128 } 129 130 uint64_t 131 arc_all_memory(void) 132 { 133 return (ptob(physmem)); 134 } 135 136 int 137 arc_memory_throttle(spa_t *spa, uint64_t reserve, uint64_t txg) 138 { 139 return (0); 140 } 141 142 uint64_t 143 arc_free_memory(void) 144 { 145 return (ptob(freemem)); 146 } 147 148 static eventhandler_tag arc_event_lowmem = NULL; 149 150 static void 151 arc_lowmem(void *arg __unused, int howto __unused) 152 { 153 int64_t can_free, free_memory, to_free; 154 155 arc_no_grow = B_TRUE; 156 arc_warm = B_TRUE; 157 arc_growtime = gethrtime() + SEC2NSEC(arc_grow_retry); 158 159 free_memory = arc_available_memory(); 160 can_free = arc_c - arc_c_min; 161 to_free = (MAX(can_free, 0) >> arc_shrink_shift) - MIN(free_memory, 0); 162 DTRACE_PROBE2(arc__needfree, int64_t, free_memory, int64_t, to_free); 163 to_free = arc_reduce_target_size(to_free); 164 165 /* 166 * It is unsafe to block here in arbitrary threads, because we can come 167 * here from ARC itself and may hold ARC locks and thus risk a deadlock 168 * with ARC reclaim thread. 169 */ 170 if (curproc == pageproc) { 171 arc_wait_for_eviction(to_free, B_FALSE, B_FALSE); 172 ARCSTAT_BUMP(arcstat_memory_indirect_count); 173 } else { 174 ARCSTAT_BUMP(arcstat_memory_direct_count); 175 } 176 } 177 178 void 179 arc_lowmem_init(void) 180 { 181 arc_event_lowmem = EVENTHANDLER_REGISTER(vm_lowmem, arc_lowmem, NULL, 182 EVENTHANDLER_PRI_FIRST); 183 } 184 185 void 186 arc_lowmem_fini(void) 187 { 188 if (arc_event_lowmem != NULL) 189 EVENTHANDLER_DEREGISTER(vm_lowmem, arc_event_lowmem); 190 } 191 192 void 193 arc_register_hotplug(void) 194 { 195 } 196 197 void 198 arc_unregister_hotplug(void) 199 { 200 } 201