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 * Copyright 2014 Garrett D'Amore <garrett@damore.org> 23 * Copyright (c) 1987, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 #ifndef _SYS_SWAP_H 40 #define _SYS_SWAP_H 41 42 #include <sys/isa_defs.h> 43 #include <sys/feature_tests.h> 44 #include <vm/anon.h> 45 #include <sys/fs/swapnode.h> 46 47 #ifdef __cplusplus 48 extern "C" { 49 #endif 50 51 #if !defined(_LP64) && _FILE_OFFSET_BITS == 64 52 #error "Cannot use swapctl in the large files compilation environment" 53 #endif 54 55 /* The following are for the swapctl system call */ 56 57 #define SC_ADD 1 /* add a specified resource for swapping */ 58 #define SC_LIST 2 /* list all the swapping resources */ 59 #define SC_REMOVE 3 /* remove the specified swapping resource */ 60 #define SC_GETNSWP 4 /* get number of swap resources configured */ 61 #define SC_AINFO 5 /* get anonymous memory resource information */ 62 63 typedef struct swapres { 64 char *sr_name; /* pathname of the resource specified */ 65 off_t sr_start; /* starting offset of the swapping resource */ 66 off_t sr_length; /* length of the swap area */ 67 } swapres_t; 68 69 typedef struct swapent { 70 char *ste_path; /* get the name of the swap file */ 71 off_t ste_start; /* starting block for swapping */ 72 off_t ste_length; /* length of swap area */ 73 long ste_pages; /* numbers of pages for swapping */ 74 long ste_free; /* numbers of ste_pages free */ 75 int ste_flags; /* see below */ 76 } swapent_t; 77 78 typedef struct swaptable { 79 int swt_n; /* number of swapents following */ 80 struct swapent swt_ent[1]; /* array of swt_n swapents */ 81 } swaptbl_t; 82 83 84 #if defined(_SYSCALL32) 85 86 /* Kernel's view of user ILP32 swapres and swapent structures */ 87 88 typedef struct swapres32 { 89 caddr32_t sr_name; /* pathname of the resource specified */ 90 off32_t sr_start; /* starting offset of the swapping resource */ 91 off32_t sr_length; /* length of the swap area */ 92 } swapres32_t; 93 94 typedef struct swapent32 { 95 caddr32_t ste_path; /* get the name of the swap file */ 96 off32_t ste_start; /* starting block for swapping */ 97 off32_t ste_length; /* length of swap area */ 98 int32_t ste_pages; /* numbers of pages for swapping */ 99 int32_t ste_free; /* numbers of ste_pages free */ 100 int32_t ste_flags; /* see below */ 101 } swapent32_t; 102 103 typedef struct swaptable32 { 104 int32_t swt_n; /* number of swapents following */ 105 struct swapent32 swt_ent[1]; /* array of swt_n swapents */ 106 } swaptbl32_t; 107 108 #endif /* _SYSCALL32 */ 109 110 #if defined(_KERNEL) 111 extern int swapctl(int, void *, int *); 112 #if defined(_LP64) && defined(_SYSCALL32) 113 extern int swapctl32(int, void *, int *); 114 #endif /* _LP64 && _SYSCALL32 */ 115 #else /* !_KERNEL */ 116 extern int swapctl(int, void *); 117 #endif /* _KERNEL */ 118 119 120 /* ste_flags values */ 121 122 #define ST_INDEL 0x01 /* Deletion of file is in progress. */ 123 /* Prevents others from deleting or */ 124 /* allocating from it */ 125 #define ST_DOINGDEL 0x02 /* Set during deletion of file */ 126 /* Clearing during deletion signals */ 127 /* that you want to add the file back */ 128 /* again, and will eventually cause */ 129 /* it to be added back */ 130 131 /* 132 * VM - virtual swap device. 133 */ 134 struct swapinfo { 135 ulong_t si_soff; /* starting offset (bytes) of file */ 136 ulong_t si_eoff; /* ending offset (bytes) of file */ 137 struct vnode *si_vp; /* vnode (commonvp if device) */ 138 struct swapinfo *si_next; /* next swap area */ 139 int si_allocs; /* # of conseq. allocs from this area */ 140 short si_flags; /* flags defined below */ 141 pgcnt_t si_npgs; /* number of pages of swap space */ 142 pgcnt_t si_nfpgs; /* number of free pages of swap space */ 143 int si_pnamelen; /* swap file name length + 1 */ 144 char *si_pname; /* swap file name */ 145 ssize_t si_mapsize; /* # bytes allocated for bitmap */ 146 uint_t *si_swapslots; /* bitmap of slots, unset == free */ 147 pgcnt_t si_hint; /* first page to check if free */ 148 ssize_t si_checkcnt; /* # of checks to find freeslot */ 149 ssize_t si_alloccnt; /* used to find ave checks */ 150 }; 151 152 /* 153 * Stuff to convert an anon slot pointer to a page name. 154 * Because the address of the slot (ap) is a unique identifier, we 155 * use it to generate a unique (vp,off), as shown in the comment for 156 * swap_alloc(). 157 * 158 * The off bits are shifted PAGESHIFT to directly form a page aligned 159 * offset; the vp index bits map 1-1 to a vnode. 160 * 161 */ 162 #define MAX_SWAP_VNODES_LOG2 11 /* log2(MAX_SWAP_VNODES) */ 163 #define MAX_SWAP_VNODES (1U << MAX_SWAP_VNODES_LOG2) /* max # swap vnodes */ 164 #define AN_VPMASK (MAX_SWAP_VNODES - 1) /* vp index mask */ 165 #define AN_VPSHIFT MAX_SWAP_VNODES_LOG2 166 /* 167 * Convert from an anon slot to associated vnode and offset. 168 */ 169 #define swap_xlate(AP, VPP, OFFP) \ 170 { \ 171 *(VPP) = (AP)->an_vp; \ 172 *(OFFP) = (AP)->an_off; \ 173 } 174 #define swap_xlate_nopanic swap_xlate 175 176 /* 177 * Get a vnode name for an anon slot. 178 * The vnum, offset are derived from anon struct address which is 179 * 16 bytes aligned. anon structs may be kmem_cache_alloc'd concurrently by 180 * multiple threads and come from a small range of addresses (same slab), in 181 * which case high order AP bits do not vary much, so choose vnum from low 182 * order bits which vary the most. Different threads will thus get different 183 * vnums and vnodes, which avoids vph_mutex_contention on the subsequent 184 * page_hashin(). 185 * 186 * +-----------...-------------------+-----------------------+----+ 187 * | swap offset | vnum |0000| 188 * +-----------...-------------------+-----------------------+----+ 189 * 63 15 14 4 3 0 190 */ 191 #define swap_alloc(AP) \ 192 { \ 193 (AP)->an_vp = swapfs_getvp(((uintptr_t)(AP) >> AN_CACHE_ALIGN_LOG2) \ 194 & AN_VPMASK); \ 195 (AP)->an_off = (anoff_t)((((uintptr_t)(AP)) >> \ 196 AN_VPSHIFT + AN_CACHE_ALIGN_LOG2) << PAGESHIFT); \ 197 } 198 199 /* 200 * Free the page name for the specified anon slot. 201 * For now there's nothing to do. 202 */ 203 #define swap_free(AP) 204 205 /* Flags for swap_phys_alloc */ 206 #define SA_NOT 0x01 /* Must have slot from swap dev other than input one */ 207 208 /* Special error codes for swap_newphysname() */ 209 #define SE_NOSWAP -1 /* No physical swap slots available */ 210 #define SE_NOANON -2 /* No anon slot for swap slot */ 211 212 #ifdef _KERNEL 213 extern struct anon *swap_anon(struct vnode *vp, u_offset_t off); 214 extern int swap_phys_alloc(struct vnode **vpp, u_offset_t *offp, size_t *lenp, 215 uint_t flags); 216 extern void swap_phys_free(struct vnode *vp, u_offset_t off, size_t len); 217 extern int swap_getphysname(struct vnode *vp, u_offset_t off, 218 struct vnode **pvpp, u_offset_t *poffp); 219 extern int swap_newphysname(struct vnode *vp, u_offset_t offset, 220 u_offset_t *offp, size_t *lenp, struct vnode **pvpp, u_offset_t *poffp); 221 222 extern struct swapinfo *swapinfo; 223 extern int swap_debug; 224 #endif /* _KERNEL */ 225 226 #ifdef SWAP_DEBUG 227 #define SW_RENAME 0x01 228 #define SW_RESV 0x02 229 #define SW_ALLOC 0x04 230 #define SW_CTL 0x08 231 #define SWAP_PRINT(f, s, x1, x2, x3, x4, x5) \ 232 if (swap_debug & f) \ 233 printf(s, x1, x2, x3, x4, x5); 234 #else /* SWAP_DEBUG */ 235 #define SWAP_PRINT(f, s, x1, x2, x3, x4, x5) 236 #endif /* SWAP_DEBUG */ 237 238 #ifdef __cplusplus 239 } 240 #endif 241 242 #endif /* _SYS_SWAP_H */ 243