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(__i386) || !defined(UMA_MD_SMALL_ALLOC) 93 /* 94 * If we're on an i386 platform, it's possible that we'll exhaust the 95 * kernel heap space before we ever run out of available physical 96 * memory. Most checks of the size of the heap_area compare against 97 * tune.t_minarmem, which is the minimum available real memory that we 98 * can have in the system. However, this is generally fixed at 25 pages 99 * which is so low that it's useless. In this comparison, we seek to 100 * calculate the total heap-size, and reclaim if more than 3/4ths of the 101 * heap is allocated. (Or, in the calculation, if less than 1/4th is 102 * 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 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 free_memory = arc_available_memory(); 158 int64_t can_free = arc_c - arc_c_min; 159 if (can_free <= 0) 160 return; 161 to_free = (can_free >> arc_shrink_shift) - MIN(free_memory, 0); 162 DTRACE_PROBE2(arc__needfree, int64_t, free_memory, int64_t, to_free); 163 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); 172 } 173 174 void 175 arc_lowmem_init(void) 176 { 177 arc_event_lowmem = EVENTHANDLER_REGISTER(vm_lowmem, arc_lowmem, NULL, 178 EVENTHANDLER_PRI_FIRST); 179 } 180 181 void 182 arc_lowmem_fini(void) 183 { 184 if (arc_event_lowmem != NULL) 185 EVENTHANDLER_DEREGISTER(vm_lowmem, arc_event_lowmem); 186 } 187 188 void 189 arc_register_hotplug(void) 190 { 191 } 192 193 void 194 arc_unregister_hotplug(void) 195 { 196 } 197