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