#ifndef _SYS_BUF_H_
#define _SYS_BUF_H_
#include <sys/queue.h>
#include <sys/tree.h>
#include <sys/mutex.h>
#include <uvm/uvm_extern.h>
#define NOLIST ((struct buf *)0x87654321)
struct buf;
struct vnode;
LIST_HEAD(bufhead, buf);
#define BUFQ_NSCAN_N 128
#define BUFQ_FIFO 0
#define BUFQ_NSCAN 1
#define BUFQ_DEFAULT BUFQ_NSCAN
#define BUFQ_HOWMANY 2
#define BUFQ_HI 128
#define BUFQ_LOW 64
struct bufq_impl;
struct bufq {
SLIST_ENTRY(bufq) bufq_entries;
struct mutex bufq_mtx;
void *bufq_data;
u_int bufq_outstanding;
u_int bufq_hi;
u_int bufq_low;
int bufq_waiting;
int bufq_stop;
int bufq_type;
const struct bufq_impl *bufq_impl;
};
int bufq_init(struct bufq *, int);
void bufq_destroy(struct bufq *);
void bufq_queue(struct bufq *, struct buf *);
struct buf *bufq_dequeue(struct bufq *);
int bufq_peek(struct bufq *);
void bufq_drain(struct bufq *);
void bufq_wait(struct bufq *);
void bufq_done(struct bufq *, struct buf *);
void bufq_quiesce(void);
void bufq_restart(void);
SIMPLEQ_HEAD(bufq_fifo_head, buf);
struct bufq_fifo {
SIMPLEQ_ENTRY(buf) bqf_entries;
};
SIMPLEQ_HEAD(bufq_nscan_head, buf);
struct bufq_nscan {
SIMPLEQ_ENTRY(buf) bqf_entries;
};
union bufq_data {
struct bufq_fifo bufq_data_fifo;
struct bufq_nscan bufq_data_nscan;
};
struct buf {
RBT_ENTRY(buf) b_rbbufs;
LIST_ENTRY(buf) b_list;
LIST_ENTRY(buf) b_vnbufs;
TAILQ_ENTRY(buf) b_freelist;
int cache;
struct proc *b_proc;
volatile long b_flags;
long b_bufsize;
long b_bcount;
size_t b_resid;
int b_error;
dev_t b_dev;
caddr_t b_data;
void *b_saveaddr;
TAILQ_ENTRY(buf) b_valist;
union bufq_data b_bufq;
struct bufq *b_bq;
struct uvm_object *b_pobj;
struct uvm_object b_uobj;
off_t b_poffs;
daddr_t b_lblkno;
daddr_t b_blkno;
void (*b_iodone)(struct buf *);
struct vnode *b_vp;
int b_dirtyoff;
int b_dirtyend;
int b_validoff;
int b_validend;
};
TAILQ_HEAD(bufqueue, buf);
struct bufcache {
int64_t hotbufpages;
int64_t warmbufpages;
int64_t cachepages;
struct bufqueue hotqueue;
struct bufqueue coldqueue;
struct bufqueue warmqueue;
};
#define B_WRITE 0x00000000
#define B_AGE 0x00000001
#define B_NEEDCOMMIT 0x00000002
#define B_ASYNC 0x00000004
#define B_BAD 0x00000008
#define B_BUSY 0x00000010
#define B_CACHE 0x00000020
#define B_CALL 0x00000040
#define B_DELWRI 0x00000080
#define B_DONE 0x00000100
#define B_EINTR 0x00000200
#define B_ERROR 0x00000400
#define B_INVAL 0x00000800
#define B_NOCACHE 0x00001000
#define B_PHYS 0x00002000
#define B_RAW 0x00004000
#define B_READ 0x00008000
#define B_WANTED 0x00010000
#define B_WRITEINPROG 0x00020000
#define B_XXX 0x00040000
#define B_DEFERRED 0x00080000
#define B_SCANNED 0x00100000
#define B_PDAEMON 0x00200000
#define B_RELEASED 0x00400000
#define B_WARM 0x00800000
#define B_COLD 0x01000000
#define B_BC 0x02000000
#define B_DMA 0x04000000
#define B_BITS "\20\001AGE\002NEEDCOMMIT\003ASYNC\004BAD\005BUSY" \
"\006CACHE\007CALL\010DELWRI\011DONE\012EINTR\013ERROR" \
"\014INVAL\015NOCACHE\016PHYS\017RAW\020READ" \
"\021WANTED\022WRITEINPROG\023XXX(FORMAT)\024DEFERRED" \
"\025SCANNED\026DAEMON\027RELEASED\030WARM\031COLD\032BC\033DMA"
#define clrbuf(bp) { \
bzero((bp)->b_data, (bp)->b_bcount); \
(bp)->b_resid = 0; \
}
#define B_CLRBUF 0x01
#define B_SYNC 0x02
struct cluster_info {
daddr_t ci_lastr;
daddr_t ci_lastw;
daddr_t ci_cstart;
daddr_t ci_lasta;
int ci_clen;
int ci_ralen;
daddr_t ci_maxra;
};
#ifdef _KERNEL
__BEGIN_DECLS
#define RESERVE_SLOTS 4
#define RESERVE_PAGES (RESERVE_SLOTS * MAXPHYS / PAGE_SIZE)
#define BCACHE_MIN (RESERVE_PAGES * 2)
#define UNCLEAN_PAGES (bcstats.numbufpages - bcstats.numcleanpages)
extern struct proc *cleanerproc;
extern long bufpages;
extern struct pool bufpool;
extern struct bufhead bufhead;
void bawrite(struct buf *);
void bdwrite(struct buf *);
void biodone(struct buf *);
int biowait(struct buf *);
int bread(struct vnode *, daddr_t, int, struct buf **);
int breadn(struct vnode *, daddr_t, int, daddr_t *, int *, int,
struct buf **);
void brelse(struct buf *);
void bufinit(void);
void buf_dirty(struct buf *);
void buf_undirty(struct buf *);
void buf_adjcnt(struct buf *, long);
int bwrite(struct buf *);
struct buf *getblk(struct vnode *, daddr_t, int, int, uint64_t);
struct buf *geteblk(size_t);
struct buf *incore(struct vnode *, daddr_t);
void bufcache_take(struct buf *);
void bufcache_release(struct buf *);
int buf_flip_high(struct buf *);
void buf_flip_dma(struct buf *);
struct buf *bufcache_getcleanbuf(int, int);
struct buf *bufcache_getdirtybuf(void);
void buf_mem_init(vsize_t);
void buf_acquire(struct buf *);
void buf_acquire_nomap(struct buf *);
void buf_map(struct buf *);
void buf_release(struct buf *);
int buf_dealloc_mem(struct buf *);
void buf_fix_mapping(struct buf *, vsize_t);
void buf_alloc_pages(struct buf *, vsize_t);
void buf_free_pages(struct buf *);
int buf_realloc_pages(struct buf *, struct uvm_constraint_range *, int);
void minphys(struct buf *bp);
int physio(void (*strategy)(struct buf *), dev_t dev, int flags,
void (*minphys)(struct buf *), struct uio *uio);
void brelvp(struct buf *);
void reassignbuf(struct buf *);
void bgetvp(struct vnode *, struct buf *);
void buf_replacevnode(struct buf *, struct vnode *);
void buf_daemon(void *);
void buf_replacevnode(struct buf *, struct vnode *);
int bread_cluster(struct vnode *, daddr_t, int, struct buf **);
__END_DECLS
#endif
#endif