-
Notifications
You must be signed in to change notification settings - Fork 24
/
buf.h
335 lines (299 loc) · 12 KB
/
buf.h
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
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
/* $NetBSD: buf.h,v 1.106.6.3 2008/09/28 10:41:04 mjf Exp $ */
/*-
* Copyright (c) 1999, 2000, 2007 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center, and by Andrew Doran.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1982, 1986, 1989, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)buf.h 8.9 (Berkeley) 3/30/95
*/
#ifndef _SYS_BUF_H_
#define _SYS_BUF_H_
#include <sys/pool.h>
#include <sys/queue.h>
#include <sys/mutex.h>
#include <sys/condvar.h>
#if defined(_KERNEL)
#include <sys/workqueue.h>
#endif /* defined(_KERNEL) */
struct buf;
struct mount;
struct vnode;
struct kauth_cred;
#define NOLIST ((struct buf *)0x87654321)
/*
* To avoid including <ufs/ffs/softdep.h>
*/
LIST_HEAD(workhead, worklist);
/*
* These are currently used only by the soft dependency code, hence
* are stored once in a global variable. If other subsystems wanted
* to use these hooks, a pointer to a set of bio_ops could be added
* to each buffer.
*/
struct bio_ops {
void (*io_start)(struct buf *);
void (*io_complete)(struct buf *);
void (*io_deallocate)(struct buf *);
int (*io_fsync)(struct vnode *, int);
int (*io_sync)(struct mount *);
void (*io_movedeps)(struct buf *, struct buf *);
int (*io_countdeps)(struct buf *, int);
void (*io_pageiodone)(struct buf *);
};
extern kmutex_t bufcache_lock;
extern kmutex_t buffer_lock;
/*
* The buffer header describes an I/O operation in the kernel.
*
* Field markings and the corresponding locks:
*
* b thread of execution that holds BC_BUSY, does not correspond
* directly to any particular LWP
* c bufcache_lock
* l b_objlock
*
* For buffers associated with a vnode, b_objlock points to vp->v_interlock.
* If not associated with a vnode, it points to the generic buffer_lock.
*/
struct buf {
union {
TAILQ_ENTRY(buf) u_actq;
#if defined(_KERNEL) /* u_work is smaller than u_actq. XXX */
struct work u_work;
#endif /* defined(_KERNEL) */
} b_u; /* b: device driver queue */
#define b_actq b_u.u_actq
#define b_work b_u.u_work
void (*b_iodone)(struct buf *);/* b: call when done */
int b_error; /* b: errno value. */
int b_resid; /* b: remaining I/O. */
u_int b_flags; /* b: B_* flags */
int b_prio; /* b: priority for queue */
int b_bufsize; /* b: allocated size */
int b_bcount; /* b: valid bytes in buffer */
dev_t b_dev; /* b: associated device */
void *b_data; /* b: fs private data */
daddr_t b_blkno; /* b: physical block number
(partition relative) */
daddr_t b_rawblkno; /* b: raw physical block number
(volume relative) */
struct proc *b_proc; /* b: proc if BB_PHYS */
void *b_saveaddr; /* b: saved b_data for physio */
/*
* b: private data for owner.
* - buffer cache buffers are owned by corresponding filesystem.
* - non-buffer cache buffers are owned by subsystem which
* allocated them. (filesystem, disk driver, etc)
*/
void *b_private;
off_t b_dcookie; /* NFS: Offset cookie if dir block */
kcondvar_t b_busy; /* c: threads waiting on buf */
u_int b_refcnt; /* c: refcount for b_busy */
struct workhead b_dep; /* c: softdep */
LIST_ENTRY(buf) b_hash; /* c: hash chain */
LIST_ENTRY(buf) b_vnbufs; /* c: associated vnode */
TAILQ_ENTRY(buf) b_freelist; /* c: position if not active */
LIST_ENTRY(buf) b_wapbllist; /* c: transaction buffer list */
daddr_t b_lblkno; /* c: logical block number */
int b_freelistindex;/* c: free list index (BQ_) */
u_int b_cflags; /* c: BC_* flags */
struct vnode *b_vp; /* c: file vnode */
kcondvar_t b_done; /* o: waiting on completion */
u_int b_oflags; /* o: BO_* flags */
kmutex_t *b_objlock; /* o: completion lock */
};
/*
* For portability with historic industry practice, the cylinder number has
* to be maintained in the `b_resid' field.
*/
#define b_cylinder b_resid /* Cylinder number for disksort(). */
/*
* These flags are kept in b_cflags (owned by buffer cache).
*/
#define BC_AGE 0x00000001 /* Move to age queue when I/O done. */
#define BC_BUSY 0x00000010 /* I/O in progress. */
#define BC_SCANNED 0x00000020 /* Block already pushed during sync */
#define BC_INVAL 0x00002000 /* Does not contain valid info. */
#define BC_NOCACHE 0x00008000 /* Do not cache block after use. */
#define BC_WANTED 0x00800000 /* Process wants this buffer. */
#define BC_VFLUSH 0x04000000 /* Buffer is being synced. */
/*
* These flags are kept in b_oflags (owned by associated object).
*/
#define BO_DELWRI 0x00000080 /* Delay I/O until buffer reused. */
#define BO_DONE 0x00000200 /* I/O completed. */
/*
* These flags are kept in b_flags (owned by buffer holder).
*/
#define B_WRITE 0x00000000 /* Write buffer (pseudo flag). */
#define B_ASYNC 0x00000004 /* Start I/O, do not wait. */
#define B_COWDONE 0x00000400 /* Copy-on-write already done. */
#define B_GATHERED 0x00001000 /* LFS: already in a segment. */
#define B_LOCKED 0x00004000 /* Locked in core (not reusable). */
#define B_PHYS 0x00040000 /* I/O to user memory. */
#define B_RAW 0x00080000 /* Set by physio for raw transfers. */
#define B_READ 0x00100000 /* Read buffer. */
#define B_DEVPRIVATE 0x02000000 /* Device driver private flag. */
#define BUF_FLAGBITS \
"\20\1AGE\3ASYNC\4BAD\5BUSY\6SCANNED\10DELWRI" \
"\12DONE\13COWDONE\15GATHERED\16INVAL\17LOCKED\20NOCACHE" \
"\23PHYS\24RAW\25READ\32DEVPRIVATE\33VFLUSH"
/* Avoid weird code due to B_WRITE being a "pseudo flag" */
#define BUF_ISREAD(bp) (((bp)->b_flags & B_READ) == B_READ)
#define BUF_ISWRITE(bp) (((bp)->b_flags & B_READ) == B_WRITE)
/*
* This structure describes a clustered I/O. It is stored in the b_saveaddr
* field of the buffer on which I/O is done. At I/O completion, cluster
* callback uses the structure to parcel I/O's to individual buffers, and
* then free's this structure.
*/
struct cluster_save {
long bs_bcount; /* Saved b_bcount. */
long bs_bufsize; /* Saved b_bufsize. */
void *bs_saveaddr; /* Saved b_addr. */
int bs_nchildren; /* Number of associated buffers. */
struct buf *bs_children; /* List of associated buffers. */
};
/*
* Zero out the buffer's data area.
*/
#define clrbuf(bp) \
do { \
memset((bp)->b_data, 0, (u_int)(bp)->b_bcount); \
(bp)->b_resid = 0; \
} while (/* CONSTCOND */ 0)
/* Flags to low-level allocation routines. */
#define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */
#define B_SYNC 0x02 /* Do all allocations synchronously. */
#define B_METAONLY 0x04 /* Return indirect block buffer. */
#define B_CONTIG 0x08 /* Allocate file contiguously. */
/* Flags to bread(), breadn() and breada(). */
#define B_MODIFY 0x01 /* Hint: caller might modify buffer */
#ifdef _KERNEL
#define BIO_GETPRIO(bp) ((bp)->b_prio)
#define BIO_SETPRIO(bp, prio) (bp)->b_prio = (prio)
#define BIO_COPYPRIO(bp1, bp2) BIO_SETPRIO(bp1, BIO_GETPRIO(bp2))
#define BPRIO_NPRIO 3
#define BPRIO_TIMECRITICAL 2
#define BPRIO_TIMELIMITED 1
#define BPRIO_TIMENONCRITICAL 0
#define BPRIO_DEFAULT BPRIO_TIMELIMITED
extern const struct bio_ops *bioopsp;
extern u_int nbuf; /* The number of buffer headers */
/*
* Definitions for the buffer free lists.
*/
#define BQUEUES 4 /* number of free buffer queues */
#define BQ_LOCKED 0 /* super-blocks &c */
#define BQ_LRU 1 /* lru, useful buffers */
#define BQ_AGE 2 /* rubbish */
#define BQ_EMPTY 3 /* buffer headers with no memory */
struct bqueue {
TAILQ_HEAD(, buf) bq_queue;
uint64_t bq_bytes;
buf_t *bq_marker;
};
extern struct bqueue bufqueues[BQUEUES];
extern struct simplelock bqueue_slock;
__BEGIN_DECLS
int allocbuf(buf_t *, int, int);
void bawrite(buf_t *);
void bdirty(buf_t *);
void bdwrite(buf_t *);
void biodone(buf_t *);
int biowait(buf_t *);
int bread(struct vnode *, daddr_t, int, struct kauth_cred *, int, buf_t **);
int breada(struct vnode *, daddr_t, int, daddr_t, int, struct kauth_cred *,
int, buf_t **);
int breadn(struct vnode *, daddr_t, int, daddr_t *, int *, int,
struct kauth_cred *, int, buf_t **);
void brelsel(buf_t *, int);
void brelse(buf_t *, int);
void bremfree(buf_t *);
void bufinit(void);
void bufinit2(void);
int bwrite(buf_t *);
buf_t *getblk(struct vnode *, daddr_t, int, int, int);
buf_t *geteblk(int);
buf_t *incore(struct vnode *, daddr_t);
void minphys(buf_t *);
int physio(void (*)(buf_t *), buf_t *, dev_t, int,
void (*)(buf_t *), struct uio *);
void brelvp(buf_t *);
void reassignbuf(buf_t *, struct vnode *);
void bgetvp(struct vnode *, buf_t *);
int buf_syncwait(void);
u_long buf_memcalc(void);
int buf_drain(int);
int buf_setvalimit(vsize_t);
#ifdef DDB
void vfs_buf_print(buf_t *, int, void (*)(const char *, ...));
#endif
buf_t *getiobuf(struct vnode *, bool);
void putiobuf(buf_t *);
void buf_init(buf_t *);
void buf_destroy(buf_t *);
int bbusy(buf_t *, bool, int, kmutex_t *);
void nestiobuf_iodone(buf_t *);
void nestiobuf_setup(buf_t *, buf_t *, int, size_t);
void nestiobuf_done(buf_t *, int, int);
__END_DECLS
#endif /* _KERNEL */
#endif /* !_SYS_BUF_H_ */