summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/fdbuffer.h
blob: 1e8144acf890e5a7c10d3d513505d5a98f1b6c57 (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
/*
 * 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 (c) 1998 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _SYS_FDBUFFER_H
#define	_SYS_FDBUFFER_H

#ifdef __cplusplus
extern "C" {
#endif

#include <vm/page.h>
#include <sys/buf.h>

typedef enum {
	FDB_PAGEIO,		/* fdbuffer is a page buffer */
	FDB_VADDR		/* fdbuffer is a address buffer */
} fdb_type_t;

#define	FDB_READ	0x01		/* fdbuffer is readable */
#define	FDB_WRITE	0x02		/* fdbuffer is asked for write */
#define	FDB_DONE	0x04		/* fdbuffer buffer io done */
#define	FDB_ERROR	0x08		/* fdbuffer in error state */
#define	FDB_ASYNC	0x10		/* fdbuffer using async i/o requests */
#define	FDB_SYNC	0x20		/* fdbuffer using direct i/o requests */
#define	FDB_ICALLBACK	0x40		/* fdbuffer immediate call back */
#define	FDB_ZEROHOLE	0x80		/* fdbuffer auto-zero holes */

typedef struct fdb_holes {
	struct fdb_holes *next_hole;
	u_offset_t off;		/* start offset for this hole */
	size_t len;		/* length of this hole */
} fdb_holes_t;

struct fdbuffer;

typedef void (*fdb_iodone_t)(struct fdbuffer *fdbuf, void *kargp, buf_t *bp);


/*
 * Implementation notes in the fdbuffer structure members:
 *
 * fd_state: The state variable carries four distinct types of information
 *           it could probably be a bit field as such.
 *
 *	READ/WRITE:
 *		This information is stored in fdbuffer at the time the
 *		The buffer is created and is used for sanity check in
 *		subsequent calls to fdb_iosetup(). This information
 *		persists for the entire life of the buffer.
 *
 *	[A]SYNC:
 *		The buffer can be either in sync or async mode. In
 *		async mode all calls are to be async and the i/o
 *		must take place for the entire range or the fdbuf
 *		i/o must be ended with a call to fdb_ioerrdone()
 *		In the async case the call back is made either
 *		for every i/o completed or only once at the end
 *		of i/o. This depends on how the call back function
 *		is registered. See fdb_set_iofunc(). The fdbuf has
 *		to be freed by the call back function.
 *
 *	ZEROHOLE:
 *		This is the case the holes are to be zeroed. Note
 *		that we do not zero the holes when fdb_add_hole() is
 *		getting called. We leave the zeroing of the holes to
 *		when a list is requested or the buffer is freed. This
 *		so that we can avoid zeroing pages while holding ufs
 *		locks.
 */


typedef struct fdbuffer {
	fdb_type_t fd_type;	/* type of buffer */
	int	fd_state;	/* state of the fdbfer */
	size_t	fd_len;		/* length of this fdbuffer */
	size_t	fd_iocount;	/* total io acked, includes errors and holes */
	int	fd_iodispatch;	/* # of io's dispatched */
	int	fd_err;		/* last i/o error due from buf_t */
	ssize_t	fd_resid;	/* total len in error */

	buf_t *fd_parentbp;	/* buf associated with parent buf */

	union {
		page_t *pages;	/* page list for FDPAGE_BUF */
		caddr_t	addr;	/* address for FDADDR_BUF */
	} fd_un;

	fdb_holes_t *fd_holes;	/* holes list if this fdbuffer has holes */

	page_t **fd_shadow;	/* shadow pages used for direct i/o to uspace */
	struct proc *fd_procp;	/* procp used in bp for direct i/o to uspace */

	/*
	 * Call this function when the I/O on the full range of fdbuffer
	 * is completed. The call is made only if the i/o requests
	 * are asynchronous.
	 */

	fdb_iodone_t fd_iofunc;
	void *fd_iargp;		/* iodone function argument to be passed */

	/*
	 * The mutex protects iodispatch, iocount, state, and resid
	 * flags and variables since they are examined and updated by
	 * async call backs. All other structure members are modified
	 * in a single threaded fashion and do not require a lock.
	 */
	kmutex_t fd_mutex;

} fdbuffer_t;

#define	fd_pages	fd_un.pages
#define	fd_addr		fd_un.addr

extern fdbuffer_t *fdb_page_create(page_t *pp, size_t len, int flag);
extern fdbuffer_t *fdb_addr_create(caddr_t addr, size_t len, int flag,
    page_t **pplist, struct proc *procp);

extern void fdb_set_iofunc(fdbuffer_t *fdbuf, fdb_iodone_t iofunc, void *ioarg,
    int flags);
extern fdb_holes_t *fdb_get_holes(fdbuffer_t *fdbuf);
extern int fdb_get_error(fdbuffer_t *fdbuf);
extern void fdb_free(fdbuffer_t *fdbuf);
/*
 * Need to add:
 * fdb_get_iolen
 */
extern void fdb_add_hole(fdbuffer_t *fdbuf, u_offset_t off, size_t len);
extern buf_t *fdb_iosetup(fdbuffer_t *fdbuf, u_offset_t off, size_t len,
    struct vnode *vn, int flags);
extern int fdb_iodone(buf_t *bufp);
extern void fdb_ioerrdone(fdbuffer_t *fdbuf, int error);
extern void fdb_init(void);

#ifdef __cplusplus
}
#endif

#endif	/* _SYS_FDBUFFER_H */