1/* $OpenBSD: buf.h,v 1.120 2025/08/14 16:13:52 beck Exp $ */
2/* $NetBSD: buf.h,v 1.25 1997/04/09 21:12:17 mycroft Exp $ */
3
4/*
5 * Copyright (c) 1982, 1986, 1989, 1993
6 * The Regents of the University of California. All rights reserved.
7 * (c) UNIX System Laboratories, Inc.
8 * All or some portions of this file are derived from material licensed
9 * to the University of California by American Telephone and Telegraph
10 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
11 * the permission of UNIX System Laboratories, Inc.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)buf.h 8.7 (Berkeley) 1/21/94
38 */
39
40#ifndef _SYS_BUF_H_
41#define _SYS_BUF_H_
42#include <sys/queue.h>
43#include <sys/tree.h>
44#include <sys/mutex.h>
45#include <uvm/uvm_extern.h>
46
47#define NOLIST ((struct buf *)0x87654321)
48
49struct buf;
50struct vnode;
51
52LIST_HEAD(bufhead, buf);
53
54/*
55 * Buffer queues
56 */
57#define BUFQ_NSCAN_N 128
58#define BUFQ_FIFO 0
59#define BUFQ_NSCAN 1
60#define BUFQ_DEFAULT BUFQ_NSCAN
61#define BUFQ_HOWMANY 2
62
63/*
64 * Write limits for bufq - defines high and low water marks for how
65 * many kva slots are allowed to be consumed to parallelize writes from
66 * the buffer cache from any individual bufq.
67 */
68#define BUFQ_HI 128
69#define BUFQ_LOW 64
70
71struct bufq_impl;
72
73struct bufq {
74 SLIST_ENTRY(bufq) bufq_entries;
75 struct mutex bufq_mtx;
76 void *bufq_data;
77 u_int bufq_outstanding;
78 u_int bufq_hi;
79 u_int bufq_low;
80 int bufq_waiting;
81 int bufq_stop;
82 int bufq_type;
83 const struct bufq_impl *bufq_impl;
84};
85
86int bufq_init(struct bufq *, int);
87void bufq_destroy(struct bufq *);
88
89void bufq_queue(struct bufq *, struct buf *);
90struct buf *bufq_dequeue(struct bufq *);
91int bufq_peek(struct bufq *);
92void bufq_drain(struct bufq *);
93
94void bufq_wait(struct bufq *);
95void bufq_done(struct bufq *, struct buf *);
96void bufq_quiesce(void);
97void bufq_restart(void);
98
99/* fifo */
100SIMPLEQ_HEAD(bufq_fifo_head, buf);
101struct bufq_fifo {
102 SIMPLEQ_ENTRY(buf) bqf_entries;
103};
104
105/* nscan */
106SIMPLEQ_HEAD(bufq_nscan_head, buf);
107struct bufq_nscan {
108 SIMPLEQ_ENTRY(buf) bqf_entries;
109};
110
111/* bufq link in struct buf */
112union bufq_data {
113 struct bufq_fifo bufq_data_fifo;
114 struct bufq_nscan bufq_data_nscan;
115};
116
117/* The buffer header describes an I/O operation in the kernel. */
118struct buf {
119 RBT_ENTRY(buf) b_rbbufs; /* vnode "hash" tree */
120 LIST_ENTRY(buf) b_list; /* All allocated buffers. */
121 LIST_ENTRY(buf) b_vnbufs; /* Buffer's associated vnode. */
122 TAILQ_ENTRY(buf) b_freelist; /* Free list position if not active. */
123 int cache; /* which cache are we in */
124 struct proc *b_proc; /* Associated proc; NULL if kernel. */
125 volatile long b_flags; /* B_* flags. */
126 long b_bufsize; /* Allocated buffer size. */
127 long b_bcount; /* Valid bytes in buffer. */
128 size_t b_resid; /* Remaining I/O. */
129 int b_error; /* Errno value. */
130 dev_t b_dev; /* Device associated with buffer. */
131 caddr_t b_data; /* associated data */
132 void *b_saveaddr; /* Original b_data for physio. */
133
134 TAILQ_ENTRY(buf) b_valist; /* LRU of va to reuse. */
135
136 union bufq_data b_bufq;
137 struct bufq *b_bq; /* What bufq this buf is on */
138
139 struct uvm_object *b_pobj;
140 struct uvm_object b_uobj; /* Object containing the pages */
141 off_t b_poffs; /* Offset within object */
142
143 daddr_t b_lblkno; /* Logical block number. */
144 daddr_t b_blkno; /* Underlying physical block number. */
145 /* Function to call upon completion.
146 * Will be called at splbio(). */
147 void (*b_iodone)(struct buf *);
148 struct vnode *b_vp; /* Device vnode. */
149 int b_dirtyoff; /* Offset in buffer of dirty region. */
150 int b_dirtyend; /* Offset of end of dirty region. */
151 int b_validoff; /* Offset in buffer of valid region. */
152 int b_validend; /* Offset of end of valid region. */
153};
154
155TAILQ_HEAD(bufqueue, buf);
156
157struct bufcache {
158 int64_t hotbufpages;
159 int64_t warmbufpages;
160 int64_t cachepages;
161 struct bufqueue hotqueue;
162 struct bufqueue coldqueue;
163 struct bufqueue warmqueue;
164};
165
166/*
167 * These flags are kept in b_flags.
168 */
169#define B_WRITE 0x00000000 /* Write buffer (pseudo flag). */
170#define B_AGE 0x00000001 /* Move to age queue when I/O done. */
171#define B_NEEDCOMMIT 0x00000002 /* Needs committing to stable storage */
172#define B_ASYNC 0x00000004 /* Start I/O, do not wait. */
173#define B_BAD 0x00000008 /* Bad block revectoring in progress. */
174#define B_BUSY 0x00000010 /* I/O in progress. */
175#define B_CACHE 0x00000020 /* Bread found us in the cache. */
176#define B_CALL 0x00000040 /* Call b_iodone from biodone. */
177#define B_DELWRI 0x00000080 /* Delay I/O until buffer reused. */
178#define B_DONE 0x00000100 /* I/O completed. */
179#define B_EINTR 0x00000200 /* I/O was interrupted */
180#define B_ERROR 0x00000400 /* I/O error occurred. */
181#define B_INVAL 0x00000800 /* Does not contain valid info. */
182#define B_NOCACHE 0x00001000 /* Do not cache block after use. */
183#define B_PHYS 0x00002000 /* I/O to user memory. */
184#define B_RAW 0x00004000 /* Set by physio for raw transfers. */
185#define B_READ 0x00008000 /* Read buffer. */
186#define B_WANTED 0x00010000 /* Process wants this buffer. */
187#define B_WRITEINPROG 0x00020000 /* Write in progress. */
188#define B_XXX 0x00040000 /* Debugging flag. */
189#define B_DEFERRED 0x00080000 /* Skipped over for cleaning */
190#define B_SCANNED 0x00100000 /* Block already pushed during sync */
191#define B_PDAEMON 0x00200000 /* I/O started by pagedaemon */
192#define B_RELEASED 0x00400000 /* free this buffer after its kvm */
193#define B_WARM 0x00800000 /* buffer is or has been on the warm queue */
194#define B_COLD 0x01000000 /* buffer is on the cold queue */
195#define B_BC 0x02000000 /* buffer is managed by the cache */
196#define B_DMA 0x04000000 /* buffer is DMA reachable */
197
198#define B_BITS "\20\001AGE\002NEEDCOMMIT\003ASYNC\004BAD\005BUSY" \
199 "\006CACHE\007CALL\010DELWRI\011DONE\012EINTR\013ERROR" \
200 "\014INVAL\015NOCACHE\016PHYS\017RAW\020READ" \
201 "\021WANTED\022WRITEINPROG\023XXX(FORMAT)\024DEFERRED" \
202 "\025SCANNED\026DAEMON\027RELEASED\030WARM\031COLD\032BC\033DMA"
203
204/*
205 * Zero out the buffer's data area.
206 */
207#define clrbuf(bp) { \
208 bzero((bp)->b_data, (bp)->b_bcount); \
209 (bp)->b_resid = 0; \
210}
211
212
213/* Flags to low-level allocation routines. */
214#define B_CLRBUF 0x01 /* Request allocated buffer be cleared. */
215#define B_SYNC 0x02 /* Do all allocations synchronously. */
216
217struct cluster_info {
218 daddr_t ci_lastr; /* last read (read-ahead) */
219 daddr_t ci_lastw; /* last write (write cluster) */
220 daddr_t ci_cstart; /* start block of cluster */
221 daddr_t ci_lasta; /* last allocation */
222 int ci_clen; /* length of current cluster */
223 int ci_ralen; /* Read-ahead length */
224 daddr_t ci_maxra; /* last readahead block */
225};
226
227#ifdef _KERNEL
228__BEGIN_DECLS
229/* Kva slots (of size MAXPHYS) reserved for syncer and cleaner. */
230#define RESERVE_SLOTS 4
231/* Buffer cache pages reserved for syncer and cleaner. */
232#define RESERVE_PAGES (RESERVE_SLOTS * MAXPHYS / PAGE_SIZE)
233/* Minimum size of the buffer cache, in pages. */
234#define BCACHE_MIN (RESERVE_PAGES * 2)
235#define UNCLEAN_PAGES (bcstats.numbufpages - bcstats.numcleanpages)
236
237extern struct proc *cleanerproc;
238extern long bufpages; /* Max number of pages for buffers' data */
239extern struct pool bufpool;
240extern struct bufhead bufhead;
241
242void bawrite(struct buf *);
243void bdwrite(struct buf *);
244void biodone(struct buf *);
245int biowait(struct buf *);
246int bread(struct vnode *, daddr_t, int, struct buf **);
247int breadn(struct vnode *, daddr_t, int, daddr_t *, int *, int,
248 struct buf **);
249void brelse(struct buf *);
250void bufinit(void);
251void buf_dirty(struct buf *);
252void buf_undirty(struct buf *);
253void buf_adjcnt(struct buf *, long);
254int bwrite(struct buf *);
255struct buf *getblk(struct vnode *, daddr_t, int, int, uint64_t);
256struct buf *geteblk(size_t);
257struct buf *incore(struct vnode *, daddr_t);
258
259/*
260 * bufcache functions
261 */
262void bufcache_take(struct buf *);
263void bufcache_release(struct buf *);
264
265int buf_flip_high(struct buf *);
266void buf_flip_dma(struct buf *);
267struct buf *bufcache_getcleanbuf(int, int);
268struct buf *bufcache_getdirtybuf(void);
269
270/*
271 * buf_kvm_init initializes the kvm handling for buffers.
272 * buf_acquire sets the B_BUSY flag and ensures that the buffer is
273 * mapped in the kvm.
274 * buf_release clears the B_BUSY flag and allows the buffer to become
275 * unmapped.
276 * buf_unmap is for internal use only. Unmaps the buffer from kvm.
277 */
278void buf_mem_init(vsize_t);
279void buf_acquire(struct buf *);
280void buf_acquire_nomap(struct buf *);
281void buf_map(struct buf *);
282void buf_release(struct buf *);
283int buf_dealloc_mem(struct buf *);
284void buf_fix_mapping(struct buf *, vsize_t);
285void buf_alloc_pages(struct buf *, vsize_t);
286void buf_free_pages(struct buf *);
287int buf_realloc_pages(struct buf *, struct uvm_constraint_range *, int);
288
289void minphys(struct buf *bp);
290int physio(void (*strategy)(struct buf *), dev_t dev, int flags,
291 void (*minphys)(struct buf *), struct uio *uio);
292void brelvp(struct buf *);
293void reassignbuf(struct buf *);
294void bgetvp(struct vnode *, struct buf *);
295
296void buf_replacevnode(struct buf *, struct vnode *);
297void buf_daemon(void *);
298void buf_replacevnode(struct buf *, struct vnode *);
299int bread_cluster(struct vnode *, daddr_t, int, struct buf **);
300
301__END_DECLS
302#endif /* _KERNEL */
303#endif /* !_SYS_BUF_H_ */