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