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