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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_FS_XMEM_H
#define _SYS_FS_XMEM_H
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/t_lock.h>
#include <vm/seg.h>
#include <vm/seg_vn.h>
#include <sys/fs/seg_xmem.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _KERNEL
/*
* xmemnode is the file system dependent node for xmemfs.
*
* xn_rwlock protects access of the directory list at xn_dir
* as well as syncronizing read and writes to the xmemnode
*
* xn_contents protects growing, shrinking, reading and writing
* the file along with xn_rwlock (see below).
*
* xn_tlock protects updates to xn_mode and xn_nlink
*
* xm_contents in the xmount filesystem data structure protects
* xn_forw and xn_back which are used to maintain a linked
* list of all xmemfs files associated with that file system
*
* XXX - valid ? The pp array represents the store for xmemfs.
* To grow or shrink the file or fill in holes requires
* manipulation of the pp array. These operations are protected
* by a combination of xn_rwlock and xn_contents. Growing or shrinking
* the array requires the write lock on xn_rwlock and xn_contents.
* Filling in a slot in the array requires the write lock on xn_contents.
* Reading the array requires the read lock on xn_contents.
*
* The ordering of the locking is:
* xn_rwlock -> xn_contents -> page locks on pages in file
*
* xn_tlock doesn't require any xmemnode locks
*/
struct xmemnode {
struct xmemnode *xn_back; /* linked list of xmemnodes */
struct xmemnode *xn_forw; /* linked list of xmemnodes */
union {
struct {
struct xdirent *un_dirlist; /* dirent list */
uint_t un_dirents; /* number of dirents */
} un_dirstruct;
char *un_symlink; /* pointer to symlink */
struct {
page_t ***un_ppa; /* page backing for file */
size_t un_size; /* size repres. by array */
} un_ppstruct;
} un_xmemnode;
struct vnode *xn_vnode; /* vnode for this xmemnode */
int xn_gen; /* pseudo gen number for xfid */
struct vattr xn_attr; /* attributes */
krwlock_t xn_contents; /* vm side -serialize mods */
krwlock_t xn_rwlock; /* rw,trunc size - serialize */
/* mods and directory updates */
kmutex_t xn_tlock; /* time, flag, and nlink lock */
};
/*
* each xn_ppa[] entry points to an array of page_t pointers.
*/
#define xn_ppa un_xmemnode.un_ppstruct.un_ppa
#define xn_ppasz un_xmemnode.un_ppstruct.un_size
#define xn_dir un_xmemnode.un_dirstruct.un_dirlist
#define xn_dirents un_xmemnode.un_dirstruct.un_dirents
#define xn_symlink un_xmemnode.un_symlink
/*
* Attributes
*/
#define xn_mask xn_attr.va_mask
#define xn_type xn_attr.va_type
#define xn_mode xn_attr.va_mode
#define xn_uid xn_attr.va_uid
#define xn_gid xn_attr.va_gid
#define xn_fsid xn_attr.va_fsid
#define xn_nodeid xn_attr.va_nodeid
#define xn_nlink xn_attr.va_nlink
#define xn_size xn_attr.va_size
#define xn_atime xn_attr.va_atime
#define xn_mtime xn_attr.va_mtime
#define xn_ctime xn_attr.va_ctime
#define xn_rdev xn_attr.va_rdev
#define xn_blksize xn_attr.va_blksize
#define xn_nblocks xn_attr.va_nblocks
#define xn_seq xn_attr.va_seq
/*
* xmemfs directories are made up of a linked list of xdirent structures
* hanging off directory xmemnodes. File names are not fixed length,
* but are null terminated.
*/
struct xdirent {
struct xmemnode *xd_xmemnode; /* xmemnode for this file */
struct xdirent *xd_next; /* next directory entry */
struct xdirent *xd_prev; /* prev directory entry */
uint_t xd_offset; /* "offset" of dir entry */
uint_t xd_hash; /* a hash of xd_name */
struct xdirent *xd_link; /* linked via the hash table */
struct xmemnode *xd_parent; /* parent, dir we are in */
char *xd_name; /* must be null terminated */
/* max length is MAXNAMELEN */
};
/*
* xfid overlays the fid structure (for VFS_VGET)
*/
struct xfid {
uint16_t xfid_len;
ino32_t xfid_ino;
int32_t xfid_gen;
};
#define ESAME (-1) /* trying to rename linked files (special) */
extern struct vnodeops *xmem_vnodeops;
extern const struct fs_operation_def xmem_vnodeops_template[];
/*
* xmemfs per-mount data structure.
*
* All fields are protected by xm_contents.
* File renames on a particular file system are protected xm_renamelck.
*/
struct xmount {
struct vfs *xm_vfsp; /* filesystem's vfs struct */
struct xmemnode *xm_rootnode; /* root xmemnode */
char *xm_mntpath; /* name of xmemfs mount point */
uint_t xm_flags; /* Miscellaneous Flags */
size_t xm_bsize; /* block size for this file system */
uint_t xm_bshift; /* for converting offset to block # */
pgcnt_t xm_ppb; /* pages per block */
struct map *xm_map; /* Map for kernel addresses */
caddr_t xm_mapaddr; /* Base of above map */
size_t xm_mapsize; /* size of above map */
caddr_t xm_vmmapaddr; /* Base of heap for above map */
size_t xm_vmmapsize; /* size of heap for above map */
ulong_t xm_max; /* file system max reservation */
pgcnt_t xm_mem; /* pages of reserved memory */
dev_t xm_dev; /* unique dev # of mounted `device' */
uint_t xm_gen; /* pseudo generation number for files */
kmutex_t xm_contents; /* lock for xmount structure */
kmutex_t xm_renamelck; /* rename lock for this mount */
uint_t xm_xpgcnt; /* index and count for xpg_array */
void **xm_xpgarray; /* array of pointers */
};
#ifndef DEBUG
#define XMEMPRINTF(level, args)
#else
extern int xmemlevel;
/*PRINTFLIKE1*/
extern void xmemprintf(const char *, ...)
__KPRINTFLIKE(1);
#define XMEMPRINTF(level, args) if (level >= xmemlevel) xmemprintf args
#endif
#endif /* _KERNEL */
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack(4)
#endif
/*
* Make sizeof struct xmemfs_args the same on x86 and amd64.
*/
struct xmemfs_args {
offset_t xa_fssize; /* file system size in bytes */
offset_t xa_bsize; /* block size for this file system */
uint_t xa_flags; /* flags for this mount */
};
#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
#pragma pack()
#endif
/* Flag bits */
#define XARGS_RESERVEMEM 1 /* pre reserve memory */
#define XARGS_LARGEPAGES 2 /* Use large pages */
#ifdef _KERNEL
/*
* File system independent to xmemfs conversion macros
*/
#define VFSTOXM(vfsp) ((struct xmount *)(vfsp)->vfs_data)
#define VTOXM(vp) ((struct xmount *)(vp)->v_vfsp->vfs_data)
#define VTOXN(vp) ((struct xmemnode *)(vp)->v_data)
#define XNTOV(xp) ((xp)->xn_vnode)
#define xmemnode_hold(tp) VN_HOLD(XNTOV(tp))
#define xmemnode_rele(tp) VN_RELE(XNTOV(tp))
/*
* enums
*/
enum de_op { DE_CREATE, DE_MKDIR, DE_LINK, DE_RENAME }; /* direnter ops */
enum dr_op { DR_REMOVE, DR_RMDIR, DR_RENAME }; /* dirremove ops */
/*
* xmemfs_minfree is the amount (in pages) of memory that xmemfs
* leaves free for the rest of the system.
* NB: If xmemfs allocates too much space, other processes will be
* unable to execute. 320 is chosen arbitrarily to be about right for
* an RDBMS environment with all of it's buffers coming from xmemfs.
*/
#define XMEMMINFREE 320 * 1024 * 1024 /* 320 Megabytes */
/*
* number of simultaneous reads/writes is limited by NUM_SIMULMAPS
* below. We cannot set it much higher as we expect typical block
* size to be 2MB or 4MB and we cannot afford to reserve and keep
* too much kernel virtual memory for ourselves.
*/
#define SEGXMEM_NUM_SIMULMAPS 4
extern pgcnt_t xmemfs_minfree; /* memory in pages */
extern void xmemnode_init(struct xmount *, struct xmemnode *,
struct vattr *, struct cred *);
extern int xmemnode_trunc(struct xmount *, struct xmemnode *, u_offset_t);
extern int xdirlookup(struct xmemnode *, char *, struct xmemnode **,
struct cred *);
extern int xdirdelete(struct xmemnode *, struct xmemnode *, char *,
enum dr_op, struct cred *);
extern void xdirinit(struct xmemnode *, struct xmemnode *);
extern void xdirtrunc(struct xmemnode *);
extern void *xmem_memalloc(size_t, int);
extern void xmem_memfree(void *, size_t);
extern int xmem_xaccess(void *, int, struct cred *);
extern int xdirenter(struct xmount *, struct xmemnode *, char *,
enum de_op, struct xmemnode *, struct xmemnode *, struct vattr *,
struct xmemnode **, struct cred *);
extern int xmem_fillpages(struct xmemnode *, struct vnode *, offset_t,
offset_t, int);
extern int xmem_sticky_remove_access(struct xmemnode *, struct xmemnode *,
struct cred *);
#endif /* _KERNEL */
#define XMEM_MUSTHAVE 1
#ifdef __cplusplus
}
#endif
#endif /* _SYS_FS_XMEM_H */
|