summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/aio_impl.h
blob: a67031d0fab762427bc4cbafb0ea80855c7a8c76 (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
/*
 * 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 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_AIO_IMPL_H
#define	_SYS_AIO_IMPL_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

#include <sys/aio_req.h>
#include <sys/aio.h>
#include <sys/aiocb.h>
#include <sys/uio.h>
#include <sys/dditypes.h>
#include <sys/siginfo.h>
#include <sys/port.h>
#include <sys/port_kernel.h>

#ifdef	__cplusplus
extern "C" {
#endif

#ifdef _KERNEL

#define	AIO_HASHSZ		8192L		/* power of 2 */
#define	AIO_HASH(cookie)	(((uintptr_t)(cookie) >> 3) & (AIO_HASHSZ-1))
#define	DUPLICATE 1
#define	AIO_IOCB_MAX		32768L

/*
 * an aio_list_t is the head of a list. a group of requests are in
 * the same list if their aio_req_list field point to the same list
 * head.
 *
 * a list head is used for notification. a group of requests that
 * should only notify a process when they are done will have a
 * list head. notification is sent when the group of requests are
 * done.
 */
typedef struct aio_lio {
	int 		lio_nent;		/* number of requests in list */
	int 		lio_refcnt;		/* number of requests active */
	struct aio_lio	*lio_next;		/* free list pointer */
	kcondvar_t	lio_notify;		/* list notification */
	sigqueue_t	*lio_sigqp;		/* sigqueue_t pointer */
	int		lio_port;		/* port number notification */
	port_kevent_t	*lio_portkev;		/* port event structure */
} aio_lio_t;

/*
 * async I/O request struct - one per I/O request.
 */

/*
 * Clustering: The aio_req_t structure is used by the PXFS module
 * as a contract private interface.
 */

typedef struct aio_req_t {
	struct aio_req	aio_req;
	int		aio_req_fd;		/* aio's file descriptor */
	int		aio_req_flags;		/* flags */
	aio_result_t	*aio_req_resultp;	/* pointer to user's results */
	int		(*aio_req_cancel)();	/* driver's cancel cb. */
	struct aio_req_t *aio_req_next;		/* doneq and pollq pointers */
	struct aio_req_t *aio_req_prev;		/* doubly linked list */
	struct aio_req_t *aio_hash_next;	/* next in a hash bucket */
	aio_lio_t 	*aio_req_lio;		/* head of list IO chain */
	struct uio	aio_req_uio;		/* uio struct */
	struct iovec	aio_req_iov;		/* iovec struct */
	struct buf	aio_req_buf;		/* buf struct */
	sigqueue_t	*aio_req_sigqp;		/* sigqueue_t pointer */
	union {
		caddr_t 	iocb;		/* ptr to aiocb: 32-32, 64-64 */
		caddr32_t	iocb32;		/* ptr to aiocb: 32-64 */
	} aio_req_iocb;
	port_kevent_t	*aio_req_portkev;	/* port event structure */
	int		aio_req_port;		/* port id */
} aio_req_t;

/*
 * Struct for asynchronous I/O (aio) information per process.
 * Each proc stucture has a field pointing to this struct.
 * The field will be null if no aio is used.
 */
typedef struct aio {
	int		aio_pending;		/* # uncompleted requests */
	int		aio_outstanding;	/* total # of requests */
	int		aio_ok;			/* everything ok when set */
	int		aio_flags;		/* flags */
	int		aio_rqclnup;		/* cleanup request used by DR */
	int		aio_portpendcnt;	/* # pending req. per port */
	aio_req_t	*aio_portq;  		/* port queue head */
	aio_req_t	*aio_portcleanupq;	/* port cleanup queue head */
	aio_req_t	*aio_portpending;	/* list of pending requests */
	aio_req_t	*aio_free;  		/* freelist of aio requests */
	aio_lio_t	*aio_lio_free;		/* freelist of lio heads */
	aio_req_t	*aio_doneq;		/* done queue head */
	aio_req_t	*aio_pollq;		/* poll queue head */
	aio_req_t	*aio_notifyq;		/* notify queue head */
	aio_req_t	*aio_cleanupq;		/* cleanup queue head */
	kmutex_t    	aio_mutex;		/* mutex for aio struct */
	kmutex_t	aio_cleanupq_mutex;	/* cleanupq processing */
	kcondvar_t  	aio_waitcv;		/* cv for aiowait()'ers */
	kcondvar_t  	aio_cleanupcv;		/* notify cleanup, aio_done */
	kcondvar_t  	aio_waitncv;		/* cv for further aiowaitn() */
	kcondvar_t  	aio_portcv;		/* cv for port events */
	aiocb_t		**aio_iocb;		/* list of 32 & 64 bit ptrs */
	size_t		aio_iocbsz;		/* reserved space for iocbs */
	uint_t		aio_waitncnt;		/* # requests for aiowaitn */
	int 		aio_notifycnt;		/* # user-level notifications */
	kmutex_t	aio_portq_mutex;	/* mutex for aio_portq */
	aio_req_t 	*aio_hash[AIO_HASHSZ];	/* hash list of requests */
} aio_t;

/*
 * aio_flags for an aio_t.
 */
#define	AIO_CLEANUP		0x1		/* do aio cleanup processing */
#define	AIO_WAITN		0x2		/* aiowaitn in progress */
#define	AIO_WAITN_PENDING	0x4		/* aiowaitn requests pending */
#define	AIO_REQ_BLOCK		0x8		/* block new requests */
#define	AIO_CLEANUP_PORT	0x10
#define	AIO_DONE_ACTIVE		0x20		/* aio_done call in progress */

/*
 * aio_req_flags for an aio_req_t
 */
#define	AIO_POLL	0x1			/* AIO_INPROGRESS is set */
#define	AIO_PENDING	0x2			/* aio is in progress */
#define	AIO_PHYSIODONE	0x4			/* unlocked phys pages */
#define	AIO_COPYOUTDONE	0x8			/* result copied to userland */
#define	AIO_NOTIFYQ	0x10			/* aio req is on the notifyq */
#define	AIO_CLEANUPQ	0x20			/* aio req is on the cleanupq */
#define	AIO_POLLQ	0x40			/* aio req is on the pollq */
#define	AIO_DONEQ	0x80			/* aio req is on the doneq */
#define	AIO_ZEROLEN	0x100			/* aio req is zero length */
#define	AIO_PAGELOCKDONE	0x200		/* aio called as_pagelock() */
#define	AIO_CLOSE_PORT		0x400		/* port is being closed */

/* flag argument of aio_cleanup() */

#define	AIO_CLEANUP_POLL	0		/* check kaio poll queue */
#define	AIO_CLEANUP_EXIT	1		/* aio_cleanup_exit() */
#define	AIO_CLEANUP_THREAD	2		/* aio_cleanup_thread() */

/* functions exported by common/os/aio_subr.c */

extern int aphysio(int (*)(), int (*)(), dev_t, int, void (*)(),
		struct aio_req *);
extern void aphysio_unlock(aio_req_t *);
extern void aio_cleanup(int);
extern void aio_cleanup_exit(void);
extern void aio_zerolen(aio_req_t *);
extern void aio_req_free(aio_t *, aio_req_t *);
extern void aio_cleanupq_concat(aio_t *, aio_req_t *, int);
extern void aio_copyout_result(aio_req_t *);
extern void aio_copyout_result_port(struct iovec *, struct buf *, void *);
extern void aio_req_remove_portq(aio_t *, aio_req_t *);
extern void aio_enq(aio_req_t **, aio_req_t *, int);
extern void aio_deq(aio_req_t **, aio_req_t *);
/* Clustering: PXFS module uses this interface */
extern void aio_done(struct buf *);

#endif /* _KERNEL */

#ifdef	__cplusplus
}
#endif

#endif /* _SYS_AIO_IMPL_H */