summaryrefslogtreecommitdiff
path: root/usr/src/uts/intel/sys/fs/xmem.h
blob: 11e36ee5c2affc9e7305b7c59ba26c663ee3bfd5 (plain)
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 */