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 */