Page MenuHomeFreeBSD

D4713.diff
No OneTemporary

D4713.diff

Index: head/lib/libstand/cd9660.c
===================================================================
--- head/lib/libstand/cd9660.c
+++ head/lib/libstand/cd9660.c
@@ -143,7 +143,7 @@
if (bcmp(sh->type, SUSP_CONTINUATION, 2) == 0) {
shc = (ISO_RRIP_CONT *)sh;
error = f->f_dev->dv_strategy(f->f_devdata, F_READ,
- cdb2devb(isonum_733(shc->location)),
+ cdb2devb(isonum_733(shc->location)), 0,
ISO_DEFAULT_BLOCK_SIZE, susp_buffer, &read);
/* Bail if it fails. */
@@ -288,7 +288,7 @@
for (bno = 16;; bno++) {
twiddle(1);
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
- ISO_DEFAULT_BLOCK_SIZE, buf, &read);
+ 0, ISO_DEFAULT_BLOCK_SIZE, buf, &read);
if (rc)
goto out;
if (read != ISO_DEFAULT_BLOCK_SIZE) {
@@ -322,7 +322,7 @@
twiddle(1);
rc = f->f_dev->dv_strategy
(f->f_devdata, F_READ,
- cdb2devb(bno + boff),
+ cdb2devb(bno + boff), 0,
ISO_DEFAULT_BLOCK_SIZE,
buf, &read);
if (rc)
@@ -381,7 +381,7 @@
bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length);
twiddle(1);
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
- ISO_DEFAULT_BLOCK_SIZE, buf, &read);
+ 0, ISO_DEFAULT_BLOCK_SIZE, buf, &read);
if (rc)
goto out;
if (read != ISO_DEFAULT_BLOCK_SIZE) {
@@ -438,7 +438,8 @@
twiddle(16);
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ,
- cdb2devb(blkno), ISO_DEFAULT_BLOCK_SIZE, fp->f_buf, &read);
+ cdb2devb(blkno), 0, ISO_DEFAULT_BLOCK_SIZE,
+ fp->f_buf, &read);
if (rc)
return (rc);
if (read != ISO_DEFAULT_BLOCK_SIZE)
Index: head/lib/libstand/dosfs.h
===================================================================
--- head/lib/libstand/dosfs.h
+++ head/lib/libstand/dosfs.h
@@ -96,8 +96,6 @@
typedef struct {
struct open_file *fd; /* file descriptor */
- u_char *buf; /* buffer */
- u_int bufsec; /* buffered sector */
u_int links; /* active links to structure */
u_int spc; /* sectors per cluster */
u_int bsize; /* cluster size in bytes */
Index: head/lib/libstand/dosfs.c
===================================================================
--- head/lib/libstand/dosfs.c
+++ head/lib/libstand/dosfs.c
@@ -131,7 +131,18 @@
#define stclus(sz, de) ((sz) != 32 ? cv2((de)->clus) : \
((u_int)cv2((de)->dex.h_clus) << 16) | \
cv2((de)->clus))
-
+
+/*
+ * fat cache metadata
+ */
+struct fatcache {
+ int unit; /* disk unit number */
+ int size; /* buffer (and fat) size in sectors */
+ u_char *buf;
+};
+
+static struct fatcache fat;
+
static int dosunmount(DOS_FS *);
static int parsebs(DOS_FS *, DOS_BS *);
static int namede(DOS_FS *, const char *, DOS_DE **);
@@ -143,8 +154,36 @@
static int fatget(DOS_FS *, u_int *);
static int fatend(u_int, u_int);
static int ioread(DOS_FS *, u_int, void *, u_int);
-static int iobuf(DOS_FS *, u_int);
-static int ioget(struct open_file *, u_int, void *, u_int);
+static int ioget(struct open_file *, daddr_t, size_t, void *, u_int);
+
+static void
+dos_read_fat(DOS_FS *fs, struct open_file *fd)
+{
+ struct devdesc *dd = fd->f_devdata;
+
+ if (fat.buf != NULL) { /* can we reuse old buffer? */
+ if (fat.size != fs->spf) {
+ free(fat.buf); /* no, free old buffer */
+ fat.buf = NULL;
+ }
+ }
+
+ if (fat.buf == NULL)
+ fat.buf = malloc(secbyt(fs->spf));
+
+ if (fat.buf != NULL) {
+ if (ioget(fd, fs->lsnfat, 0, fat.buf, secbyt(fs->spf)) == 0) {
+ fat.size = fs->spf;
+ fat.unit = dd->d_unit;
+ return;
+ }
+ }
+ if (fat.buf != NULL) /* got IO error */
+ free(fat.buf);
+ fat.buf = NULL;
+ fat.unit = -1; /* impossible unit */
+ fat.size = 0;
+}
/*
* Mount DOS filesystem
@@ -153,15 +192,25 @@
dos_mount(DOS_FS *fs, struct open_file *fd)
{
int err;
+ struct devdesc *dd = fd->f_devdata;
+ u_char *buf;
bzero(fs, sizeof(DOS_FS));
fs->fd = fd;
- if ((err = !(fs->buf = malloc(SECSIZ)) ? errno : 0) ||
- (err = ioget(fs->fd, 0, fs->buf, 1)) ||
- (err = parsebs(fs, (DOS_BS *)fs->buf))) {
+
+ if ((err = !(buf = malloc(secbyt(1))) ? errno : 0) ||
+ (err = ioget(fs->fd, 0, 0, buf, secbyt(1))) ||
+ (err = parsebs(fs, (DOS_BS *)buf))) {
+ if (buf != NULL)
+ free(buf);
(void)dosunmount(fs);
return(err);
}
+ free(buf);
+
+ if (fat.buf == NULL || fat.unit != dd->d_unit)
+ dos_read_fat(fs, fd);
+
fs->root = dot[0];
fs->root.name[0] = ' ';
if (fs->fatsz == 32) {
@@ -194,8 +243,6 @@
static int
dosunmount(DOS_FS *fs)
{
- if (fs->buf)
- free(fs->buf);
free(fs);
return(0);
}
@@ -252,42 +299,47 @@
DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
int err = 0;
+ /*
+ * as ioget() can be called *a lot*, use twiddle here.
+ * also 4 seems to be good value not to slow loading down too much:
+ * with 270MB file (~540k ioget() calls, twiddle can easily waste 4-5sec.
+ */
+ twiddle(4);
nb = (u_int)nbyte;
if ((size = fsize(f->fs, &f->de)) == -1)
return EINVAL;
if (nb > (n = size - f->offset))
- nb = n;
+ nb = n;
off = f->offset;
if ((clus = stclus(f->fs->fatsz, &f->de)))
- off &= f->fs->bsize - 1;
+ off &= f->fs->bsize - 1;
c = f->c;
cnt = nb;
while (cnt) {
- n = 0;
- if (!c) {
- if ((c = clus))
- n = bytblk(f->fs, f->offset);
- } else if (!off)
- n++;
- while (n--) {
- if ((err = fatget(f->fs, &c)))
+ n = 0;
+ if (!c) {
+ if ((c = clus))
+ n = bytblk(f->fs, f->offset);
+ } else if (!off)
+ n++;
+ while (n--) {
+ if ((err = fatget(f->fs, &c)))
goto out;
- if (!okclus(f->fs, c)) {
+ if (!okclus(f->fs, c)) {
err = EINVAL;
goto out;
}
- }
- if (!clus || (n = f->fs->bsize - off) > cnt)
- n = cnt;
- if ((err = ioread(f->fs, (c ? blkoff(f->fs, c) :
- secbyt(f->fs->lsndir)) + off,
- buf, n)))
+ }
+ if (!clus || (n = f->fs->bsize - off) > cnt)
+ n = cnt;
+ if ((err = ioread(f->fs, (c ? blkoff(f->fs, c) :
+ secbyt(f->fs->lsndir)) + off, buf, n)))
goto out;
- f->offset += n;
- f->c = c;
- off = 0;
- buf = (char *)buf + n;
- cnt -= n;
+ f->offset += n;
+ f->c = c;
+ off = 0;
+ buf = (char *)buf + n;
+ cnt -= n;
}
out:
if (resid)
@@ -364,6 +416,23 @@
}
static int
+dos_checksum(char *name, char *ext)
+{
+ int x, i;
+ char buf[11];
+
+ bcopy(name, buf, 8);
+ bcopy(ext, buf+8, 3);
+ x = 0;
+ for (i = 0; i < 11; i++) {
+ x = ((x & 1) << 7) | (x >> 1);
+ x += buf[i];
+ x &= 0xff;
+ }
+ return (x);
+}
+
+static int
dos_readdir(struct open_file *fd, struct dirent *d)
{
/* DOS_FILE *f = (DOS_FILE *)fd->f_fsdata; */
@@ -417,12 +486,7 @@
}
} else {
if (xdn == 1) {
- x = 0;
- for (i = 0; i < 11; i++) {
- x = ((x & 1) << 7) | (x >> 1);
- x += dd.de.name[i];
- x &= 0xff;
- }
+ x = dos_checksum(dd.de.name, dd.de.ext);
if (x == chk)
break;
} else {
@@ -555,7 +619,7 @@
else
return EINVAL;
for (sec = 0; sec < nsec; sec++) {
- if ((err = ioget(fs->fd, lsec + sec, dir, 1)))
+ if ((err = ioget(fs->fd, lsec + sec, 0, dir, secbyt(1))))
return err;
for (ent = 0; ent < DEPSEC; ent++) {
if (!*dir[ent].de.name)
@@ -577,9 +641,7 @@
}
} else if (!(dir[ent].de.attr & FA_LABEL)) {
if ((ok = xdn == 1)) {
- for (x = 0, i = 0; i < 11; i++)
- x = ((((x & 1) << 7) | (x >> 1)) +
- dir[ent].de.name[i]) & 0xff;
+ x = dos_checksum(dir[ent].de.name, dir[ent].de.ext);
ok = chk == x &&
!strcasecmp(name, (const char *)lfn);
}
@@ -699,22 +761,52 @@
}
/*
- * Get next cluster in cluster chain
+ * Get next cluster in cluster chain. Use in core fat cache unless another
+ * device replaced it.
*/
static int
fatget(DOS_FS *fs, u_int *c)
{
u_char buf[4];
- u_int x;
- int err;
+ u_char *s;
+ u_int x, offset, off, n, nbyte, lsec;
+ struct devdesc *dd = fs->fd->f_devdata;
+ int err = 0;
+
+ if (fat.unit != dd->d_unit) {
+ /* fat cache was changed to another device, dont use it */
+ err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf,
+ fs->fatsz != 32 ? 2 : 4);
+ if (err)
+ return err;
+ } else {
+ offset = fatoff(fs->fatsz, *c);
+ nbyte = fs->fatsz != 32 ? 2 : 4;
+
+ s = buf;
+ if ((off = offset & (SECSIZ - 1))) {
+ offset -= off;
+ lsec = bytsec(offset);
+ offset += SECSIZ;
+ if ((n = SECSIZ - off) > nbyte)
+ n = nbyte;
+ memcpy(s, fat.buf + secbyt(lsec) + off, n);
+ s += n;
+ nbyte -= n;
+ }
+ n = nbyte & (SECSIZ - 1);
+ if (nbyte -= n) {
+ memcpy(s, fat.buf + secbyt(bytsec(offset)), nbyte);
+ offset += nbyte;
+ s += nbyte;
+ }
+ if (n)
+ memcpy(s, fat.buf + secbyt(bytsec(offset)), n);
+ }
- err = ioread(fs, secbyt(fs->lsnfat) + fatoff(fs->fatsz, *c), buf,
- fs->fatsz != 32 ? 2 : 4);
- if (err)
- return err;
x = fs->fatsz != 32 ? cv2(buf) : cv4(buf);
*c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x;
- return 0;
+ return (0);
}
/*
@@ -739,42 +831,24 @@
s = buf;
if ((off = offset & (SECSIZ - 1))) {
offset -= off;
- if ((err = iobuf(fs, bytsec(offset))))
- return err;
- offset += SECSIZ;
if ((n = SECSIZ - off) > nbyte)
n = nbyte;
- memcpy(s, fs->buf + off, n);
+ if ((err = ioget(fs->fd, bytsec(offset), off, s, n)))
+ return err;
+ offset += SECSIZ;
s += n;
nbyte -= n;
}
n = nbyte & (SECSIZ - 1);
if (nbyte -= n) {
- if ((err = ioget(fs->fd, bytsec(offset), s, bytsec(nbyte))))
+ if ((err = ioget(fs->fd, bytsec(offset), 0, s, nbyte)))
return err;
offset += nbyte;
s += nbyte;
}
if (n) {
- if ((err = iobuf(fs, bytsec(offset))))
- return err;
- memcpy(s, fs->buf, n);
- }
- return 0;
-}
-
-/*
- * Buffered sector-based I/O primitive
- */
-static int
-iobuf(DOS_FS *fs, u_int lsec)
-{
- int err;
-
- if (fs->bufsec != lsec) {
- if ((err = ioget(fs->fd, lsec, fs->buf, 1)))
+ if ((err = ioget(fs->fd, bytsec(offset), 0, s, n)))
return err;
- fs->bufsec = lsec;
}
return 0;
}
@@ -783,13 +857,8 @@
* Sector-based I/O primitive
*/
static int
-ioget(struct open_file *fd, u_int lsec, void *buf, u_int nsec)
+ioget(struct open_file *fd, daddr_t lsec, size_t offset, void *buf, u_int size)
{
- int err;
-
- twiddle(1);
- if ((err = (fd->f_dev->dv_strategy)(fd->f_devdata, F_READ, lsec,
- secbyt(nsec), buf, NULL)))
- return(err);
- return(0);
+ return ((fd->f_dev->dv_strategy)(fd->f_devdata, F_READ, lsec, offset,
+ size, buf, NULL));
}
Index: head/lib/libstand/ext2fs.c
===================================================================
--- head/lib/libstand/ext2fs.c
+++ head/lib/libstand/ext2fs.c
@@ -355,7 +355,7 @@
fp->f_fs = fs;
twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- EXT2_SBLOCK, EXT2_SBSIZE, (char *)fs, &buf_size);
+ EXT2_SBLOCK, 0, EXT2_SBSIZE, (char *)fs, &buf_size);
if (error)
goto out;
@@ -397,7 +397,7 @@
fp->f_bg = malloc(len);
twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- EXT2_SBLOCK + EXT2_SBSIZE / DEV_BSIZE, len,
+ EXT2_SBLOCK + EXT2_SBSIZE / DEV_BSIZE, 0, len,
(char *)fp->f_bg, &buf_size);
if (error)
goto out;
@@ -509,7 +509,7 @@
twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata,
- F_READ, fsb_to_db(fs, disk_block),
+ F_READ, fsb_to_db(fs, disk_block), 0,
fs->fs_bsize, buf, &buf_size);
if (error)
goto out;
@@ -570,7 +570,7 @@
buf = malloc(fs->fs_bsize);
twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- ino_to_db(fs, fp->f_bg, inumber), fs->fs_bsize, buf, &rsize);
+ ino_to_db(fs, fp->f_bg, inumber), 0, fs->fs_bsize, buf, &rsize);
if (error)
goto out;
if (rsize != fs->fs_bsize) {
@@ -667,7 +667,7 @@
malloc(fs->fs_bsize);
twiddle(1);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- fsb_to_db(fp->f_fs, ind_block_num), fs->fs_bsize,
+ fsb_to_db(fp->f_fs, ind_block_num), 0, fs->fs_bsize,
fp->f_blk[level], &fp->f_blksize[level]);
if (error)
return (error);
@@ -725,7 +725,7 @@
} else {
twiddle(4);
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- fsb_to_db(fs, disk_block), block_size,
+ fsb_to_db(fs, disk_block), 0, block_size,
fp->f_buf, &fp->f_buf_size);
if (error)
goto done;
Index: head/lib/libstand/read.c
===================================================================
--- head/lib/libstand/read.c
+++ head/lib/libstand/read.c
@@ -79,7 +79,7 @@
if (f->f_flags & F_RAW) {
twiddle(4);
errno = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- btodb(f->f_offset), bcount, dest, &resid);
+ btodb(f->f_offset), 0, bcount, dest, &resid);
if (errno)
return (-1);
f->f_offset += resid;
Index: head/lib/libstand/stand.h
===================================================================
--- head/lib/libstand/stand.h
+++ head/lib/libstand/stand.h
@@ -138,8 +138,8 @@
const char dv_name[8];
int dv_type; /* opaque type constant, arch-dependant */
int (*dv_init)(void); /* early probe call */
- int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size,
- char *buf, size_t *rsize);
+ int (*dv_strategy)(void *devdata, int rw, daddr_t blk,
+ size_t offset, size_t size, char *buf, size_t *rsize);
int (*dv_open)(struct open_file *f, ...);
int (*dv_close)(struct open_file *f);
int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data);
@@ -154,6 +154,24 @@
extern int errno;
+/*
+ * Generic device specifier; architecture-dependent
+ * versions may be larger, but should be allowed to
+ * overlap.
+ */
+struct devdesc
+{
+ struct devsw *d_dev;
+ int d_type;
+#define DEVT_NONE 0
+#define DEVT_DISK 1
+#define DEVT_NET 2
+#define DEVT_CD 3
+#define DEVT_ZFS 4
+ int d_unit;
+ void *d_opendata;
+};
+
struct open_file {
int f_flags; /* see F_* below */
struct devsw *f_dev; /* pointer to device operations */
Index: head/lib/libstand/ufs.c
===================================================================
--- head/lib/libstand/ufs.c
+++ head/lib/libstand/ufs.c
@@ -157,7 +157,7 @@
buf = malloc(fs->fs_bsize);
twiddle(1);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- fsbtodb(fs, ino_to_fsba(fs, inumber)), fs->fs_bsize,
+ fsbtodb(fs, ino_to_fsba(fs, inumber)), 0, fs->fs_bsize,
buf, &rsize);
if (rc)
goto out;
@@ -267,7 +267,7 @@
malloc(fs->fs_bsize);
twiddle(1);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- fsbtodb(fp->f_fs, ind_block_num),
+ fsbtodb(fp->f_fs, ind_block_num), 0,
fs->fs_bsize,
fp->f_blk[level],
&fp->f_blksize[level]);
@@ -348,7 +348,7 @@
twiddle(4);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- fsbtodb(fs, disk_block),
+ fsbtodb(fs, disk_block), 0,
block_size, fp->f_buf, &fp->f_buf_size);
if (rc)
return (rc);
@@ -367,7 +367,7 @@
twiddle(4);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
- fsbtodb(fs, disk_block),
+ fsbtodb(fs, disk_block), 0,
block_size, fp->f_buf, &fp->f_buf_size);
return (rc);
}
@@ -408,7 +408,7 @@
} else {
twiddle(4);
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- fsbtodb(fs, disk_block),
+ fsbtodb(fs, disk_block), 0,
block_size, fp->f_buf, &fp->f_buf_size);
if (rc)
return (rc);
@@ -521,7 +521,7 @@
*/
for (i = 0; sblock_try[i] != -1; i++) {
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
+ sblock_try[i] / DEV_BSIZE, 0, SBLOCKSIZE,
(char *)fs, &buf_size);
if (rc)
goto out;
@@ -651,7 +651,7 @@
twiddle(1);
rc = (f->f_dev->dv_strategy)(f->f_devdata,
- F_READ, fsbtodb(fs, disk_block),
+ F_READ, fsbtodb(fs, disk_block), 0,
fs->fs_bsize, buf, &buf_size);
if (rc)
goto out;
Index: head/lib/libstand/write.c
===================================================================
--- head/lib/libstand/write.c
+++ head/lib/libstand/write.c
@@ -82,7 +82,7 @@
if (f->f_flags & F_RAW) {
twiddle(4);
errno = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
- btodb(f->f_offset), bcount, dest, &resid);
+ btodb(f->f_offset), 0, bcount, dest, &resid);
if (errno)
return (-1);
f->f_offset += resid;
Index: head/sys/boot/common/bcache.c
===================================================================
--- head/sys/boot/common/bcache.c
+++ head/sys/boot/common/bcache.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
+ * Copyright 2015 Toomas Soome <tsoome@me.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,99 +26,155 @@
*/
#include <sys/cdefs.h>
+#include <sys/param.h>
__FBSDID("$FreeBSD$");
/*
- * Simple LRU block cache
+ * Simple hashed block cache
*/
#include <sys/stdint.h>
#include <stand.h>
#include <string.h>
-#include <bitstring.h>
+#include <strings.h>
#include "bootstrap.h"
/* #define BCACHE_DEBUG */
#ifdef BCACHE_DEBUG
-#define BCACHE_TIMEOUT 10
# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
#else
-#define BCACHE_TIMEOUT 2
# define DEBUG(fmt, args...)
#endif
-
struct bcachectl
{
daddr_t bc_blkno;
- time_t bc_stamp;
int bc_count;
};
-static struct bcachectl *bcache_ctl;
-static caddr_t bcache_data;
-static bitstr_t *bcache_miss;
-static u_int bcache_nblks;
-static u_int bcache_blksize;
-static u_int bcache_hits, bcache_misses, bcache_ops, bcache_bypasses;
-static u_int bcache_flushes;
-static u_int bcache_bcount;
-
-static void bcache_invalidate(daddr_t blkno);
-static void bcache_insert(caddr_t buf, daddr_t blkno);
-static int bcache_lookup(caddr_t buf, daddr_t blkno);
+/*
+ * bcache per device node. cache is allocated on device first open and freed
+ * on last close, to save memory. The issue there is the size; biosdisk
+ * supports up to 31 (0x1f) devices. Classic setup would use single disk
+ * to boot from, but this has changed with zfs.
+ */
+struct bcache {
+ struct bcachectl *bcache_ctl;
+ caddr_t bcache_data;
+ u_int bcache_nblks;
+ size_t ra;
+};
+
+static u_int bcache_total_nblks; /* set by bcache_init */
+static u_int bcache_blksize; /* set by bcache_init */
+static u_int bcache_numdev; /* set by bcache_add_dev */
+/* statistics */
+static u_int bcache_units; /* number of devices with cache */
+static u_int bcache_unit_nblks; /* nblocks per unit */
+static u_int bcache_hits;
+static u_int bcache_misses;
+static u_int bcache_ops;
+static u_int bcache_bypasses;
+static u_int bcache_bcount;
+static u_int bcache_rablks;
+
+#define BHASH(bc, blkno) ((blkno) & ((bc)->bcache_nblks - 1))
+#define BCACHE_LOOKUP(bc, blkno) \
+ ((bc)->bcache_ctl[BHASH((bc), (blkno))].bc_blkno != (blkno))
+#define BCACHE_READAHEAD 256
+#define BCACHE_MINREADAHEAD 32
+
+static void bcache_invalidate(struct bcache *bc, daddr_t blkno);
+static void bcache_insert(struct bcache *bc, daddr_t blkno);
+static void bcache_free_instance(struct bcache *bc);
/*
* Initialise the cache for (nblks) of (bsize).
*/
-int
+void
bcache_init(u_int nblks, size_t bsize)
{
- /* discard any old contents */
- if (bcache_data != NULL) {
- free(bcache_data);
- bcache_data = NULL;
- free(bcache_ctl);
- }
-
- /* Allocate control structures */
- bcache_nblks = nblks;
+ /* set up control data */
+ bcache_total_nblks = nblks;
bcache_blksize = bsize;
- bcache_data = malloc(bcache_nblks * bcache_blksize);
- bcache_ctl = (struct bcachectl *)malloc(bcache_nblks * sizeof(struct bcachectl));
- bcache_miss = bit_alloc((bcache_nblks + 1) / 2);
- if ((bcache_data == NULL) || (bcache_ctl == NULL) || (bcache_miss == NULL)) {
- if (bcache_miss)
- free(bcache_miss);
- if (bcache_ctl)
- free(bcache_ctl);
- if (bcache_data)
- free(bcache_data);
- bcache_data = NULL;
- return(ENOMEM);
- }
-
- return(0);
}
/*
- * Flush the cache
+ * add number of devices to bcache. we have to divide cache space
+ * between the devices, so bcache_add_dev() can be used to set up the
+ * number. The issue is, we need to get the number before actual allocations.
+ * bcache_add_dev() is supposed to be called from device init() call, so the
+ * assumption is, devsw dv_init is called for plain devices first, and
+ * for zfs, last.
*/
void
-bcache_flush(void)
+bcache_add_dev(int devices)
{
- u_int i;
+ bcache_numdev += devices;
+}
- bcache_flushes++;
+void *
+bcache_allocate(void)
+{
+ u_int i;
+ struct bcache *bc = malloc(sizeof (struct bcache));
+ int disks = bcache_numdev;
+
+ if (disks == 0)
+ disks = 1; /* safe guard */
+
+ if (bc == NULL) {
+ errno = ENOMEM;
+ return (bc);
+ }
+
+ /*
+ * the bcache block count must be power of 2 for hash function
+ */
+ i = fls(disks) - 1; /* highbit - 1 */
+ if (disks > (1 << i)) /* next power of 2 */
+ i++;
+
+ bc->bcache_nblks = bcache_total_nblks >> i;
+ bcache_unit_nblks = bc->bcache_nblks;
+ bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize);
+ if (bc->bcache_data == NULL) {
+ /* dont error out yet. fall back to 32 blocks and try again */
+ bc->bcache_nblks = 32;
+ bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize);
+ }
+
+ bc->bcache_ctl = malloc(bc->bcache_nblks * sizeof(struct bcachectl));
+
+ if ((bc->bcache_data == NULL) || (bc->bcache_ctl == NULL)) {
+ bcache_free_instance(bc);
+ errno = ENOMEM;
+ return(NULL);
+ }
/* Flush the cache */
- for (i = 0; i < bcache_nblks; i++) {
- bcache_ctl[i].bc_count = -1;
- bcache_ctl[i].bc_blkno = -1;
- }
+ for (i = 0; i < bc->bcache_nblks; i++) {
+ bc->bcache_ctl[i].bc_count = -1;
+ bc->bcache_ctl[i].bc_blkno = -1;
+ }
+ bcache_units++;
+ bc->ra = BCACHE_READAHEAD; /* optimistic read ahead */
+ return (bc);
+}
+
+void
+bcache_free(void *cache)
+{
+ struct bcache *bc = cache;
+
+ if (bc == NULL)
+ return;
+
+ bcache_free_instance(bc);
+ bcache_units--;
}
/*
@@ -125,31 +182,22 @@
* cache with the new values.
*/
static int
-write_strategy(void *devdata, int unit, int rw, daddr_t blk, size_t size,
- char *buf, size_t *rsize)
+write_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
struct bcache_devdata *dd = (struct bcache_devdata *)devdata;
+ struct bcache *bc = dd->dv_cache;
daddr_t i, nblk;
- int err;
nblk = size / bcache_blksize;
/* Invalidate the blocks being written */
for (i = 0; i < nblk; i++) {
- bcache_invalidate(blk + i);
+ bcache_invalidate(bc, blk + i);
}
/* Write the blocks */
- err = dd->dv_strategy(dd->dv_devdata, rw, blk, size, buf, rsize);
-
- /* Populate the block cache with the new data */
- if (err == 0) {
- for (i = 0; i < nblk; i++) {
- bcache_insert(buf + (i * bcache_blksize),blk + i);
- }
- }
-
- return err;
+ return (dd->dv_strategy(dd->dv_devdata, rw, blk, offset, size, buf, rsize));
}
/*
@@ -158,61 +206,87 @@
* device I/O and then use the I/O results to populate the cache.
*/
static int
-read_strategy(void *devdata, int unit, int rw, daddr_t blk, size_t size,
- char *buf, size_t *rsize)
+read_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
struct bcache_devdata *dd = (struct bcache_devdata *)devdata;
- int p_size, result;
- daddr_t p_blk, i, j, nblk;
+ struct bcache *bc = dd->dv_cache;
+ size_t i, nblk, p_size, r_size, complete, ra;
+ int result;
+ daddr_t p_blk;
caddr_t p_buf;
+ if (bc == NULL) {
+ errno = ENODEV;
+ return (-1);
+ }
+
+ if (rsize != NULL)
+ *rsize = 0;
+
nblk = size / bcache_blksize;
+ if ((nblk == 0 && size != 0) || offset != 0)
+ nblk++;
result = 0;
+ complete = 1;
- /* Satisfy any cache hits up front */
+ /* Satisfy any cache hits up front, break on first miss */
for (i = 0; i < nblk; i++) {
- if (bcache_lookup(buf + (bcache_blksize * i), blk + i)) {
- bit_set(bcache_miss, i); /* cache miss */
- bcache_misses++;
+ if (BCACHE_LOOKUP(bc, (daddr_t)(blk + i))) {
+ bcache_misses += (nblk - i);
+ complete = 0;
+ if (nblk - i > BCACHE_MINREADAHEAD && bc->ra > BCACHE_MINREADAHEAD)
+ bc->ra >>= 1; /* reduce read ahead */
+ break;
} else {
- bit_clear(bcache_miss, i); /* cache hit */
bcache_hits++;
}
}
- /* Go back and fill in any misses XXX optimise */
- p_blk = -1;
- p_buf = NULL;
- p_size = 0;
- for (i = 0; i < nblk; i++) {
- if (bit_test(bcache_miss, i)) {
- /* miss, add to pending transfer */
- if (p_blk == -1) {
- p_blk = blk + i;
- p_buf = buf + (bcache_blksize * i);
- p_size = 1;
- } else {
- p_size++;
- }
- } else if (p_blk != -1) {
- /* hit, complete pending transfer */
- result = dd->dv_strategy(dd->dv_devdata, rw, p_blk, p_size * bcache_blksize, p_buf, NULL);
- if (result != 0)
- goto done;
- for (j = 0; j < p_size; j++)
- bcache_insert(p_buf + (j * bcache_blksize), p_blk + j);
- p_blk = -1;
- }
- }
- if (p_blk != -1) {
- /* pending transfer left */
- result = dd->dv_strategy(dd->dv_devdata, rw, p_blk, p_size * bcache_blksize, p_buf, NULL);
- if (result != 0)
- goto done;
- for (j = 0; j < p_size; j++)
- bcache_insert(p_buf + (j * bcache_blksize), p_blk + j);
- }
-
+ if (complete) { /* whole set was in cache, return it */
+ if (bc->ra < BCACHE_READAHEAD)
+ bc->ra <<= 1; /* increase read ahead */
+ bcopy(bc->bcache_data + (bcache_blksize * BHASH(bc, blk)) + offset,
+ buf, size);
+ goto done;
+ }
+
+ /*
+ * Fill in any misses. From check we have i pointing to first missing
+ * block, read in all remaining blocks + readahead.
+ * We have space at least for nblk - i before bcache wraps.
+ */
+ p_blk = blk + i;
+ p_buf = bc->bcache_data + (bcache_blksize * BHASH(bc, p_blk));
+ r_size = bc->bcache_nblks - BHASH(bc, p_blk); /* remaining blocks */
+
+ p_size = MIN(r_size, nblk - i); /* read at least those blocks */
+
+ ra = bc->bcache_nblks - BHASH(bc, p_blk + p_size);
+ if (ra != bc->bcache_nblks) { /* do we have RA space? */
+ ra = MIN(bc->ra, ra);
+ p_size += ra;
+ }
+
+ /* invalidate bcache */
+ for (i = 0; i < p_size; i++) {
+ bcache_invalidate(bc, p_blk + i);
+ }
+ r_size = 0;
+ result = dd->dv_strategy(dd->dv_devdata, rw, p_blk, 0,
+ p_size * bcache_blksize, p_buf, &r_size);
+
+ if (result)
+ goto done;
+
+ r_size /= bcache_blksize;
+ for (i = 0; i < r_size; i++)
+ bcache_insert(bc, p_blk + i);
+
+ bcache_rablks += ra;
+ bcopy(bc->bcache_data + (bcache_blksize * BHASH(bc, blk)) + offset, buf,
+ size);
+
done:
if ((result == 0) && (rsize != NULL))
*rsize = size;
@@ -220,130 +294,144 @@
}
/*
- * Requests larger than 1/2 the cache size will be bypassed and go
+ * Requests larger than 1/2 cache size will be bypassed and go
* directly to the disk. XXX tune this.
*/
int
-bcache_strategy(void *devdata, int unit, int rw, daddr_t blk, size_t size,
- char *buf, size_t *rsize)
+bcache_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
- static int bcache_unit = -1;
struct bcache_devdata *dd = (struct bcache_devdata *)devdata;
+ struct bcache *bc = dd->dv_cache;
+ u_int bcache_nblks = 0;
+ int nblk, cblk, ret;
+ size_t csize, isize, total;
bcache_ops++;
- if(bcache_unit != unit) {
- bcache_flush();
- bcache_unit = unit;
- }
+ if (bc != NULL)
+ bcache_nblks = bc->bcache_nblks;
/* bypass large requests, or when the cache is inactive */
- if ((bcache_data == NULL) || ((size * 2 / bcache_blksize) > bcache_nblks)) {
+ if (bc == NULL ||
+ (offset == 0 && ((size * 2 / bcache_blksize) > bcache_nblks))) {
DEBUG("bypass %d from %d", size / bcache_blksize, blk);
bcache_bypasses++;
- return(dd->dv_strategy(dd->dv_devdata, rw, blk, size, buf, rsize));
+ return (dd->dv_strategy(dd->dv_devdata, rw, blk, offset, size, buf,
+ rsize));
+ }
+
+ /* normalize offset */
+ while (offset >= bcache_blksize) {
+ blk++;
+ offset -= bcache_blksize;
}
switch (rw) {
case F_READ:
- return read_strategy(devdata, unit, rw, blk, size, buf, rsize);
+ nblk = size / bcache_blksize;
+ if (offset || (size != 0 && nblk == 0))
+ nblk++; /* read at least one block */
+
+ ret = 0;
+ total = 0;
+ while(size) {
+ cblk = bcache_nblks - BHASH(bc, blk); /* # of blocks left */
+ cblk = MIN(cblk, nblk);
+
+ if (size <= bcache_blksize)
+ csize = size;
+ else {
+ csize = cblk * bcache_blksize;
+ if (offset)
+ csize -= (bcache_blksize - offset);
+ }
+
+ ret = read_strategy(devdata, rw, blk, offset,
+ csize, buf+total, &isize);
+ if (ret != 0)
+ return (ret);
+ blk += (offset+isize) / bcache_blksize;
+ offset = 0;
+ total += isize;
+ size -= isize;
+ nblk = size / bcache_blksize;
+ }
+
+ if (rsize)
+ *rsize = total;
+
+ return (ret);
case F_WRITE:
- return write_strategy(devdata, unit, rw, blk, size, buf, rsize);
+ return write_strategy(devdata, rw, blk, offset, size, buf, rsize);
}
return -1;
}
-
/*
- * Insert a block into the cache. Retire the oldest block to do so, if required.
- *
- * XXX the LRU algorithm will fail after 2^31 blocks have been transferred.
+ * Free allocated bcache instance
*/
static void
-bcache_insert(caddr_t buf, daddr_t blkno)
+bcache_free_instance(struct bcache *bc)
{
- time_t now;
- int cand, ocount;
- u_int i;
-
- time(&now);
- cand = 0; /* assume the first block */
- ocount = bcache_ctl[0].bc_count;
-
- /* find the oldest block */
- for (i = 1; i < bcache_nblks; i++) {
- if (bcache_ctl[i].bc_blkno == blkno) {
- /* reuse old entry */
- cand = i;
- break;
- }
- if (bcache_ctl[i].bc_count < ocount) {
- ocount = bcache_ctl[i].bc_count;
- cand = i;
- }
+ if (bc != NULL) {
+ if (bc->bcache_ctl)
+ free(bc->bcache_ctl);
+ if (bc->bcache_data)
+ free(bc->bcache_data);
+ free(bc);
}
-
- DEBUG("insert blk %d -> %d @ %d # %d", blkno, cand, now, bcache_bcount);
- bcopy(buf, bcache_data + (bcache_blksize * cand), bcache_blksize);
- bcache_ctl[cand].bc_blkno = blkno;
- bcache_ctl[cand].bc_stamp = now;
- bcache_ctl[cand].bc_count = bcache_bcount++;
}
/*
- * Look for a block in the cache. Blocks more than BCACHE_TIMEOUT seconds old
- * may be stale (removable media) and thus are discarded. Copy the block out
- * if successful and return zero, or return nonzero on failure.
+ * Insert a block into the cache.
*/
-static int
-bcache_lookup(caddr_t buf, daddr_t blkno)
+static void
+bcache_insert(struct bcache *bc, daddr_t blkno)
{
- time_t now;
- u_int i;
+ u_int cand;
- time(&now);
+ cand = BHASH(bc, blkno);
- for (i = 0; i < bcache_nblks; i++)
- /* cache hit? */
- if ((bcache_ctl[i].bc_blkno == blkno) && ((bcache_ctl[i].bc_stamp + BCACHE_TIMEOUT) >= now)) {
- bcopy(bcache_data + (bcache_blksize * i), buf, bcache_blksize);
- DEBUG("hit blk %d <- %d (now %d then %d)", blkno, i, now, bcache_ctl[i].bc_stamp);
- return(0);
- }
- return(ENOENT);
+ DEBUG("insert blk %llu -> %u # %d", blkno, cand, bcache_bcount);
+ bc->bcache_ctl[cand].bc_blkno = blkno;
+ bc->bcache_ctl[cand].bc_count = bcache_bcount++;
}
/*
* Invalidate a block from the cache.
*/
static void
-bcache_invalidate(daddr_t blkno)
+bcache_invalidate(struct bcache *bc, daddr_t blkno)
{
u_int i;
- for (i = 0; i < bcache_nblks; i++) {
- if (bcache_ctl[i].bc_blkno == blkno) {
- bcache_ctl[i].bc_count = -1;
- bcache_ctl[i].bc_blkno = -1;
- DEBUG("invalidate blk %d", blkno);
- break;
- }
+ i = BHASH(bc, blkno);
+ if (bc->bcache_ctl[i].bc_blkno == blkno) {
+ bc->bcache_ctl[i].bc_count = -1;
+ bc->bcache_ctl[i].bc_blkno = -1;
+ DEBUG("invalidate blk %llu", blkno);
}
}
+#ifndef BOOT2
COMMAND_SET(bcachestat, "bcachestat", "get disk block cache stats", command_bcache);
static int
command_bcache(int argc, char *argv[])
{
- u_int i;
-
- for (i = 0; i < bcache_nblks; i++) {
- printf("%08jx %04x %04x|", (uintmax_t)bcache_ctl[i].bc_blkno, (unsigned int)bcache_ctl[i].bc_stamp & 0xffff, bcache_ctl[i].bc_count & 0xffff);
- if (((i + 1) % 4) == 0)
- printf("\n");
+ if (argc != 1) {
+ command_errmsg = "wrong number of arguments";
+ return(CMD_ERROR);
}
- printf("\n%d ops %d bypasses %d hits %d misses %d flushes\n", bcache_ops, bcache_bypasses, bcache_hits, bcache_misses, bcache_flushes);
+
+ printf("\ncache blocks: %d\n", bcache_total_nblks);
+ printf("cache blocksz: %d\n", bcache_blksize);
+ printf("cache readahead: %d\n", bcache_rablks);
+ printf("unit cache blocks: %d\n", bcache_unit_nblks);
+ printf("cached units: %d\n", bcache_units);
+ printf("%d ops %d bypasses %d hits %d misses\n", bcache_ops,
+ bcache_bypasses, bcache_hits, bcache_misses);
return(CMD_OK);
}
-
+#endif
Index: head/sys/boot/common/bootstrap.h
===================================================================
--- head/sys/boot/common/bootstrap.h
+++ head/sys/boot/common/bootstrap.h
@@ -33,24 +33,6 @@
#include <sys/queue.h>
#include <sys/linker_set.h>
-/*
- * Generic device specifier; architecture-dependant
- * versions may be larger, but should be allowed to
- * overlap.
- */
-struct devdesc
-{
- struct devsw *d_dev;
- int d_type;
-#define DEVT_NONE 0
-#define DEVT_DISK 1
-#define DEVT_NET 2
-#define DEVT_CD 3
-#define DEVT_ZFS 4
- int d_unit;
- void *d_opendata;
-};
-
/* Commands and return values; nonzero return sets command_errmsg != NULL */
typedef int (bootblk_cmd_t)(int argc, char *argv[]);
extern char *command_errmsg;
@@ -90,9 +72,11 @@
void *alloc_pread(int fd, off_t off, size_t len);
/* bcache.c */
-int bcache_init(u_int nblks, size_t bsize);
-void bcache_flush(void);
-int bcache_strategy(void *devdata, int unit, int rw, daddr_t blk,
+void bcache_init(u_int nblks, size_t bsize);
+void bcache_add_dev(int);
+void *bcache_allocate(void);
+void bcache_free(void *);
+int bcache_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
size_t size, char *buf, size_t *rsize);
/*
@@ -100,8 +84,10 @@
*/
struct bcache_devdata
{
- int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size, char *buf, size_t *rsize);
+ int (*dv_strategy)(void *devdata, int rw, daddr_t blk,
+ size_t offset, size_t size, char *buf, size_t *rsize);
void *dv_devdata;
+ void *dv_cache;
};
/*
Index: head/sys/boot/common/disk.c
===================================================================
--- head/sys/boot/common/disk.c
+++ head/sys/boot/common/disk.c
@@ -178,7 +178,7 @@
dev = (struct disk_devdesc *)d;
od = (struct open_disk *)dev->d_opendata;
- return (dev->d_dev->dv_strategy(dev, F_READ, offset,
+ return (dev->d_dev->dv_strategy(dev, F_READ, offset, 0,
blocks * od->sectorsize, (char *)buf, NULL));
}
@@ -239,7 +239,7 @@
int ret;
od = (struct open_disk *)dev->d_opendata;
- ret = dev->d_dev->dv_strategy(dev, F_READ, dev->d_offset + offset,
+ ret = dev->d_dev->dv_strategy(dev, F_READ, dev->d_offset + offset, 0,
blocks * od->sectorsize, buf, NULL);
return (ret);
@@ -252,7 +252,7 @@
int ret;
od = (struct open_disk *)dev->d_opendata;
- ret = dev->d_dev->dv_strategy(dev, F_WRITE, dev->d_offset + offset,
+ ret = dev->d_dev->dv_strategy(dev, F_WRITE, dev->d_offset + offset, 0,
blocks * od->sectorsize, buf, NULL);
return (ret);
Index: head/sys/boot/common/md.c
===================================================================
--- head/sys/boot/common/md.c
+++ head/sys/boot/common/md.c
@@ -60,7 +60,7 @@
/* devsw I/F */
static int md_init(void);
-static int md_strategy(void *, int, daddr_t, size_t, char *, size_t *);
+static int md_strategy(void *, int, daddr_t, size_t, size_t, char *, size_t *);
static int md_open(struct open_file *, ...);
static int md_close(struct open_file *);
static void md_print(int);
@@ -84,8 +84,8 @@
}
static int
-md_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
- size_t *rsize)
+md_strategy(void *devdata, int rw, daddr_t blk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
{
struct devdesc *dev = (struct devdesc *)devdata;
size_t ofs;
Index: head/sys/boot/common/module.c
===================================================================
--- head/sys/boot/common/module.c
+++ head/sys/boot/common/module.c
@@ -769,7 +769,7 @@
intp = (int*)recptr;
reclen = *intp++;
ival = *intp++;
- cp = (char*)intp;
+ cp = (u_char*)intp;
switch (ival) {
case MDT_VERSION:
clen = *cp++;
@@ -801,9 +801,9 @@
* Finally check if KLD is in the place
*/
if (found)
- result = file_lookup(mdp->d_path, cp, clen, NULL);
+ result = file_lookup(mdp->d_path, (const char *)cp, clen, NULL);
else if (best)
- result = file_lookup(mdp->d_path, best, blen, NULL);
+ result = file_lookup(mdp->d_path, (const char *)best, blen, NULL);
bad:
/*
* If nothing found or hints is absent - fallback to the old way
Index: head/sys/boot/efi/libefi/efipart.c
===================================================================
--- head/sys/boot/efi/libefi/efipart.c
+++ head/sys/boot/efi/libefi/efipart.c
@@ -42,7 +42,10 @@
static EFI_GUID devpath_guid = DEVICE_PATH_PROTOCOL;
static int efipart_init(void);
-static int efipart_strategy(void *, int, daddr_t, size_t, char *, size_t *);
+static int efipart_strategy(void *, int, daddr_t, size_t, size_t, char *,
+ size_t *);
+static int efipart_realstrategy(void *, int, daddr_t, size_t, size_t, char *,
+ size_t *);
static int efipart_open(struct open_file *, ...);
static int efipart_close(struct open_file *);
static void efipart_print(int);
@@ -59,6 +62,21 @@
.dv_cleanup = NULL
};
+/*
+ * info structure to support bcache
+ */
+#define MAXPDDEV 31 /* see MAXDEV in libi386.h */
+
+static struct pdinfo
+{
+ int pd_unit; /* unit number */
+ int pd_open; /* reference counter */
+ void *pd_bcache; /* buffer cache data */
+} pdinfo [MAXPDDEV];
+static int npdinfo = 0;
+
+#define PD(dev) (pdinfo[(dev)->d_unit])
+
static int
efipart_init(void)
{
@@ -140,8 +158,13 @@
} else
hout[nout] = hin[n];
nout++;
+ pdinfo[npdinfo].pd_open = 0;
+ pdinfo[npdinfo].pd_bcache = NULL;
+ pdinfo[npdinfo].pd_unit = npdinfo;
+ npdinfo++;
}
+ bcache_add_dev(npdinfo);
err = efi_register_handles(&efipart_dev, hout, aliases, nout);
free(hin);
return (err);
@@ -173,7 +196,7 @@
}
}
-static int
+static int
efipart_open(struct open_file *f, ...)
{
va_list args;
@@ -198,10 +221,13 @@
return (EAGAIN);
dev->d_opendata = blkio;
+ PD(dev).pd_open++;
+ if (PD(dev).pd_bcache == NULL)
+ PD(dev).pd_bcache = bcache_allocate();
return (0);
}
-static int
+static int
efipart_close(struct open_file *f)
{
struct devdesc *dev;
@@ -211,6 +237,11 @@
return (EINVAL);
dev->d_opendata = NULL;
+ PD(dev).pd_open--;
+ if (PD(dev).pd_open == 0) {
+ bcache_free(PD(dev).pd_bcache);
+ PD(dev).pd_bcache = NULL;
+ }
return (0);
}
@@ -254,9 +285,24 @@
return (efi_status_to_errno(status));
}
-static int
-efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
- size_t *rsize)
+static int
+efipart_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
+{
+ struct bcache_devdata bcd;
+ struct devdesc *dev;
+
+ dev = (struct devdesc *)devdata;
+ bcd.dv_strategy = efipart_realstrategy;
+ bcd.dv_devdata = devdata;
+ bcd.dv_cache = PD(dev).pd_bcache;
+ return (bcache_strategy(&bcd, rw, blk, offset, size,
+ buf, rsize));
+}
+
+static int
+efipart_realstrategy(void *devdata, int rw, daddr_t blk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
struct devdesc *dev = (struct devdesc *)devdata;
EFI_BLOCK_IO *blkio;
Index: head/sys/boot/efi/libefi/libefi.c
===================================================================
--- head/sys/boot/efi/libefi/libefi.c
+++ head/sys/boot/efi/libefi/libefi.c
@@ -102,7 +102,7 @@
(void)console_control->SetMode(console_control,
EfiConsoleControlScreenText);
- heapsize = 3 * 1024 * 1024;
+ heapsize = 64 * 1024 * 1024;
status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
EFI_SIZE_TO_PAGES(heapsize), &heap);
if (status != EFI_SUCCESS)
Index: head/sys/boot/efi/loader/main.c
===================================================================
--- head/sys/boot/efi/loader/main.c
+++ head/sys/boot/efi/loader/main.c
@@ -210,6 +210,11 @@
cons_probe();
/*
+ * Initialise the block cache. Set the upper limit.
+ */
+ bcache_init(32768, 512);
+
+ /*
* Parse the args to set the console settings, etc
* boot1.efi passes these in, if it can read /boot.config or /boot/config
* or iPXE may be setup to pass these in.
Index: head/sys/boot/i386/libfirewire/firewire.c
===================================================================
--- head/sys/boot/i386/libfirewire/firewire.c
+++ head/sys/boot/i386/libfirewire/firewire.c
@@ -66,7 +66,7 @@
static int fw_init(void);
static int fw_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int fw_open(struct open_file *f, ...);
static int fw_close(struct open_file *f);
static void fw_print(int verbose);
@@ -201,7 +201,8 @@
}
static int
-fw_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize)
+fw_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
{
return (EIO);
}
Index: head/sys/boot/i386/libi386/bioscd.c
===================================================================
--- head/sys/boot/i386/libi386/bioscd.c
+++ head/sys/boot/i386/libi386/bioscd.c
@@ -85,13 +85,19 @@
static struct bcinfo {
int bc_unit; /* BIOS unit number */
struct specification_packet bc_sp;
+ int bc_open; /* reference counter */
+ void *bc_bcache; /* buffer cache data */
} bcinfo [MAXBCDEV];
static int nbcinfo = 0;
+#define BC(dev) (bcinfo[(dev)->d_unit])
+
static int bc_read(int unit, daddr_t dblk, int blks, caddr_t dest);
static int bc_init(void);
static int bc_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
+static int bc_realstrategy(void *devdata, int flag, daddr_t dblk,
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int bc_open(struct open_file *f, ...);
static int bc_close(struct open_file *f);
static void bc_print(int verbose);
@@ -164,6 +170,7 @@
printf("BIOS CD is cd%d\n", nbcinfo);
nbcinfo++;
+ bcache_add_dev(nbcinfo); /* register cd device in bcache */
return(0);
}
@@ -200,19 +207,44 @@
return(ENXIO);
}
+ BC(dev).bc_open++;
+ if (BC(dev).bc_bcache == NULL)
+ BC(dev).bc_bcache = bcache_allocate();
return(0);
}
static int
bc_close(struct open_file *f)
{
+ struct i386_devdesc *dev;
+ dev = (struct i386_devdesc *)f->f_devdata;
+ BC(dev).bc_open--;
+ if (BC(dev).bc_open == 0) {
+ bcache_free(BC(dev).bc_bcache);
+ BC(dev).bc_bcache = NULL;
+ }
return(0);
}
+static int
+bc_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
+{
+ struct bcache_devdata bcd;
+ struct i386_devdesc *dev;
+
+ dev = (struct i386_devdesc *)devdata;
+ bcd.dv_strategy = bc_realstrategy;
+ bcd.dv_devdata = devdata;
+ bcd.dv_cache = BC(dev).bc_bcache;
+
+ return (bcache_strategy(&bcd, rw, dblk, offset, size, buf, rsize));
+}
+
static int
-bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
- size_t *rsize)
+bc_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
{
struct i386_devdesc *dev;
int unit;
Index: head/sys/boot/i386/libi386/biosdisk.c
===================================================================
--- head/sys/boot/i386/libi386/biosdisk.c
+++ head/sys/boot/i386/libi386/biosdisk.c
@@ -114,6 +114,8 @@
int bd_type; /* BIOS 'drive type' (floppy only) */
uint16_t bd_sectorsize; /* Sector size */
uint64_t bd_sectors; /* Disk size */
+ int bd_open; /* reference counter */
+ void *bd_bcache; /* buffer cache data */
} bdinfo [MAXBDDEV];
static int nbdinfo = 0;
@@ -126,9 +128,9 @@
static int bd_int13probe(struct bdinfo *bd);
static int bd_init(void);
-static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
- char *buf, size_t *rsize);
-static int bd_realstrategy(void *devdata, int flag, daddr_t dblk,
+static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsize);
+static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t offset,
size_t size, char *buf, size_t *rsize);
static int bd_open(struct open_file *f, ...);
static int bd_close(struct open_file *f);
@@ -209,6 +211,8 @@
(nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES)))
break;
#endif
+ bdinfo[nbdinfo].bd_open = 0;
+ bdinfo[nbdinfo].bd_bcache = NULL;
bdinfo[nbdinfo].bd_unit = unit;
bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0;
if (!bd_int13probe(&bdinfo[nbdinfo]))
@@ -222,6 +226,7 @@
nfd++;
}
}
+ bcache_add_dev(nbdinfo);
return(0);
}
@@ -352,7 +357,9 @@
if (dev->d_unit < 0 || dev->d_unit >= nbdinfo)
return (EIO);
-
+ BD(dev).bd_open++;
+ if (BD(dev).bd_bcache == NULL)
+ BD(dev).bd_bcache = bcache_allocate();
err = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
BD(dev).bd_sectorsize, (BD(dev).bd_flags & BD_FLOPPY) ?
DISK_F_NOCACHE: 0);
@@ -438,6 +445,11 @@
struct disk_devdesc *dev;
dev = (struct disk_devdesc *)f->f_devdata;
+ BD(dev).bd_open--;
+ if (BD(dev).bd_open == 0) {
+ bcache_free(BD(dev).bd_bcache);
+ BD(dev).bd_bcache = NULL;
+ }
return (disk_close(dev));
}
@@ -461,8 +473,8 @@
}
static int
-bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
- size_t *rsize)
+bd_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
{
struct bcache_devdata bcd;
struct disk_devdesc *dev;
@@ -470,13 +482,14 @@
dev = (struct disk_devdesc *)devdata;
bcd.dv_strategy = bd_realstrategy;
bcd.dv_devdata = devdata;
- return (bcache_strategy(&bcd, BD(dev).bd_unit, rw, dblk + dev->d_offset,
+ bcd.dv_cache = BD(dev).bd_bcache;
+ return (bcache_strategy(&bcd, rw, dblk + dev->d_offset, offset,
size, buf, rsize));
}
static int
-bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
- size_t *rsize)
+bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
{
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
int blks;
Index: head/sys/boot/i386/libi386/biosmem.c
===================================================================
--- head/sys/boot/i386/libi386/biosmem.c
+++ head/sys/boot/i386/libi386/biosmem.c
@@ -56,7 +56,7 @@
/*
* The minimum amount of memory to reserve in bios_extmem for the heap.
*/
-#define HEAP_MIN (3 * 1024 * 1024)
+#define HEAP_MIN (64 * 1024 * 1024)
/*
* Products in this list need quirks to detect
Index: head/sys/boot/i386/libi386/pxe.c
===================================================================
--- head/sys/boot/i386/libi386/pxe.c
+++ head/sys/boot/i386/libi386/pxe.c
@@ -72,7 +72,7 @@
static int pxe_init(void);
static int pxe_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int pxe_open(struct open_file *f, ...);
static int pxe_close(struct open_file *f);
static void pxe_print(int verbose);
@@ -247,7 +247,7 @@
static int
-pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
+pxe_strategy(void *devdata, int flag, daddr_t dblk, size_t offset, size_t size,
char *buf, size_t *rsize)
{
return (EIO);
Index: head/sys/boot/i386/loader/main.c
===================================================================
--- head/sys/boot/i386/loader/main.c
+++ head/sys/boot/i386/loader/main.c
@@ -141,9 +141,9 @@
cons_probe();
/*
- * Initialise the block cache
+ * Initialise the block cache. Set the upper limit.
*/
- bcache_init(32, 512); /* 16k cache XXX tune this */
+ bcache_init(32768, 512);
/*
* Special handling for PXE and CD booting.
Index: head/sys/boot/mips/beri/loader/beri_disk_cfi.c
===================================================================
--- head/sys/boot/mips/beri/loader/beri_disk_cfi.c
+++ head/sys/boot/mips/beri/loader/beri_disk_cfi.c
@@ -45,8 +45,8 @@
static int beri_cfi_disk_open(struct open_file *, ...);
static int beri_cfi_disk_close(struct open_file *);
static void beri_cfi_disk_cleanup(void);
-static int beri_cfi_disk_strategy(void *, int, daddr_t, size_t, char *,
- size_t *);
+static int beri_cfi_disk_strategy(void *, int, daddr_t, size_t, size_t,
+ char *, size_t *);
static void beri_cfi_disk_print(int);
struct devsw beri_cfi_disk = {
@@ -69,8 +69,8 @@
}
static int
-beri_cfi_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
- char *buf, size_t *rsizep)
+beri_cfi_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsizep)
{
int error;
Index: head/sys/boot/mips/beri/loader/beri_disk_sdcard.c
===================================================================
--- head/sys/boot/mips/beri/loader/beri_disk_sdcard.c
+++ head/sys/boot/mips/beri/loader/beri_disk_sdcard.c
@@ -45,8 +45,8 @@
static int beri_sdcard_disk_open(struct open_file *, ...);
static int beri_sdcard_disk_close(struct open_file *);
static void beri_sdcard_disk_cleanup(void);
-static int beri_sdcard_disk_strategy(void *, int, daddr_t, size_t, char *,
- size_t *);
+static int beri_sdcard_disk_strategy(void *, int, daddr_t, size_t, size_t,
+ char *, size_t *);
static void beri_sdcard_disk_print(int);
struct devsw beri_sdcard_disk = {
@@ -69,8 +69,8 @@
}
static int
-beri_sdcard_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
- char *buf, size_t *rsizep)
+beri_sdcard_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsizep)
{
int error;
Index: head/sys/boot/ofw/libofw/ofw_disk.c
===================================================================
--- head/sys/boot/ofw/libofw/ofw_disk.c
+++ head/sys/boot/ofw/libofw/ofw_disk.c
@@ -43,7 +43,7 @@
static int ofwd_init(void);
static int ofwd_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int ofwd_open(struct open_file *f, ...);
static int ofwd_close(struct open_file *f);
static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data);
@@ -83,8 +83,8 @@
}
static int
-ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t size,
- char *buf, size_t *rsize)
+ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata;
daddr_t pos;
Index: head/sys/boot/pc98/libpc98/bioscd.c
===================================================================
--- head/sys/boot/pc98/libpc98/bioscd.c
+++ head/sys/boot/pc98/libpc98/bioscd.c
@@ -84,13 +84,19 @@
static struct bcinfo {
int bc_unit; /* BIOS unit number */
struct specification_packet bc_sp;
+ int bc_open; /* reference counter */
+ void *bc_bcache; /* buffer cache data */
} bcinfo [MAXBCDEV];
static int nbcinfo = 0;
+#define BC(dev) (bcinfo[(dev)->d_unit])
+
static int bc_read(int unit, daddr_t dblk, int blks, caddr_t dest);
static int bc_init(void);
static int bc_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
+static int bc_realstrategy(void *devdata, int flag, daddr_t dblk,
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int bc_open(struct open_file *f, ...);
static int bc_close(struct open_file *f);
static void bc_print(int verbose);
@@ -160,6 +166,7 @@
printf("BIOS CD is cd%d\n", nbcinfo);
nbcinfo++;
+ bcache_add_dev(nbcinfo); /* register cd device in bcache */
return(0);
}
@@ -196,19 +203,44 @@
return(ENXIO);
}
+ BC(dev).bc_open++;
+ if (BC(dev).bc_bcache == NULL)
+ BC(dev).bc_bcache = bcache_allocate();
return(0);
}
static int
bc_close(struct open_file *f)
{
+ struct i386_devdesc *dev;
+ dev = (struct i386_devdesc *)f->f_devdata;
+ BC(dev).bc_open--;
+ if (BC(dev).bc_open == 0) {
+ bcache_free(BC(dev).bc_bcache);
+ BC(dev).bc_bcache = NULL;
+ }
return(0);
}
+static int
+bc_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
+{
+ struct bcache_devdata bcd;
+ struct i386_devdesc *dev;
+
+ dev = (struct i386_devdesc *)devdata;
+ bcd.dv_strategy = bc_realstrategy;
+ bcd.dv_devdata = devdata;
+ bcd.dv_cache = BC(dev).bc_bcache;
+
+ return (bcache_strategy(&bcd, rw, dblk, offset, size, buf, rsize));
+}
+
static int
-bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
- size_t *rsize)
+bc_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
{
struct i386_devdesc *dev;
int unit;
Index: head/sys/boot/pc98/libpc98/biosdisk.c
===================================================================
--- head/sys/boot/pc98/libpc98/biosdisk.c
+++ head/sys/boot/pc98/libpc98/biosdisk.c
@@ -96,9 +96,13 @@
int bd_flags;
int bd_type; /* BIOS 'drive type' (floppy only) */
int bd_da_unit; /* kernel unit number for da */
+ int bd_open; /* reference counter */
+ void *bd_bcache; /* buffer cache data */
} bdinfo [MAXBDDEV];
static int nbdinfo = 0;
+#define BD(dev) (bdinfo[(dev)->d_unit])
+
static int bd_getgeom(struct open_disk *od);
static int bd_read(struct open_disk *od, daddr_t dblk, int blks,
caddr_t dest);
@@ -176,6 +180,8 @@
/* sequence 0x90, 0x80, 0xa0 */
for (base = 0x90; base <= 0xa0; base += n, n += 0x30) {
for (unit = base; (nbdinfo < MAXBDDEV) || ((unit & 0x0f) < 4); unit++) {
+ bdinfo[nbdinfo].bd_open = 0;
+ bdinfo[nbdinfo].bd_bcache = NULL;
bdinfo[nbdinfo].bd_unit = unit;
bdinfo[nbdinfo].bd_flags = (unit & 0xf0) == 0x90 ? BD_FLOPPY : 0;
@@ -205,6 +211,7 @@
nbdinfo++;
}
}
+ bcache_add_dev(nbdinfo);
return(0);
}
@@ -427,6 +434,10 @@
if ((error = bd_opendisk(&od, dev)))
return(error);
+ BD(dev).bd_open++;
+ if (BD(dev).bd_bcache == NULL)
+ BD(dev).bd_bcache = bcache_allocate();
+
/*
* Save our context
*/
@@ -696,7 +707,14 @@
static int
bd_close(struct open_file *f)
{
- struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data);
+ struct i386_devdesc *dev = f->f_devdata;
+ struct open_disk *od = (struct open_disk *)(dev->d_kind.biosdisk.data);
+
+ BD(dev).bd_open--;
+ if (BD(dev).bd_open == 0) {
+ bcache_free(BD(dev).bd_bcache);
+ BD(dev).bd_bcache = NULL;
+ }
bd_closedisk(od);
return(0);
@@ -715,18 +733,23 @@
}
static int
-bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize)
+bd_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
{
struct bcache_devdata bcd;
- struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data);
+ struct i386_devdesc *dev = f->f_devdata;
+ struct open_disk *od = (struct open_disk *)(dev->d_kind.biosdisk.data);
bcd.dv_strategy = bd_realstrategy;
bcd.dv_devdata = devdata;
- return(bcache_strategy(&bcd, od->od_unit, rw, dblk+od->od_boff, size, buf, rsize));
+ bcd.dv_cache = BD(dev).bd_bcache;
+ return(bcache_strategy(&bcd, od->od_unit, rw, dblk+od->od_boff, offset,
+ size, buf, rsize));
}
static int
-bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize)
+bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data);
int blks;
Index: head/sys/boot/pc98/libpc98/biosmem.c
===================================================================
--- head/sys/boot/pc98/libpc98/biosmem.c
+++ head/sys/boot/pc98/libpc98/biosmem.c
@@ -40,7 +40,7 @@
/*
* The minimum amount of memory to reserve in bios_extmem for the heap.
*/
-#define HEAP_MIN (3 * 1024 * 1024)
+#define HEAP_MIN (64 * 1024 * 1024)
void
bios_getmem(void)
Index: head/sys/boot/pc98/loader/main.c
===================================================================
--- head/sys/boot/pc98/loader/main.c
+++ head/sys/boot/pc98/loader/main.c
@@ -147,9 +147,9 @@
cons_probe();
/*
- * Initialise the block cache
+ * Initialise the block cache. Set the upper limit.
*/
- bcache_init(32, 512); /* 16k cache XXX tune this */
+ bcache_init(32768, 512);
/*
* Special handling for PXE and CD booting.
Index: head/sys/boot/powerpc/kboot/hostdisk.c
===================================================================
--- head/sys/boot/powerpc/kboot/hostdisk.c
+++ head/sys/boot/powerpc/kboot/hostdisk.c
@@ -33,7 +33,7 @@
static int hostdisk_init(void);
static int hostdisk_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int hostdisk_open(struct open_file *f, ...);
static int hostdisk_close(struct open_file *f);
static int hostdisk_ioctl(struct open_file *f, u_long cmd, void *data);
@@ -58,8 +58,8 @@
}
static int
-hostdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
- char *buf, size_t *rsize)
+hostdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
struct devdesc *desc = devdata;
daddr_t pos;
Index: head/sys/boot/powerpc/ps3/ps3cdrom.c
===================================================================
--- head/sys/boot/powerpc/ps3/ps3cdrom.c
+++ head/sys/boot/powerpc/ps3/ps3cdrom.c
@@ -46,7 +46,7 @@
static int ps3cdrom_init(void);
static int ps3cdrom_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int ps3cdrom_open(struct open_file *f, ...);
static int ps3cdrom_close(struct open_file *f);
static void ps3cdrom_print(int verbose);
@@ -76,7 +76,7 @@
}
static int ps3cdrom_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize)
+ size_t offset, size_t size, char *buf, size_t *rsize)
{
struct ps3_devdesc *dev = (struct ps3_devdesc *) devdata;
int err;
Index: head/sys/boot/powerpc/ps3/ps3disk.c
===================================================================
--- head/sys/boot/powerpc/ps3/ps3disk.c
+++ head/sys/boot/powerpc/ps3/ps3disk.c
@@ -58,7 +58,7 @@
static int ps3disk_init(void);
static int ps3disk_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int ps3disk_open(struct open_file *f, ...);
static int ps3disk_close(struct open_file *f);
static void ps3disk_print(int verbose);
@@ -109,7 +109,7 @@
}
static int ps3disk_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize)
+ size_t offset, size_t size, char *buf, size_t *rsize)
{
struct ps3_devdesc *dev = (struct ps3_devdesc *) devdata;
struct open_dev *od = (struct open_dev *) dev->d_disk.data;
Index: head/sys/boot/uboot/lib/disk.c
===================================================================
--- head/sys/boot/uboot/lib/disk.c
+++ head/sys/boot/uboot/lib/disk.c
@@ -73,7 +73,8 @@
/* devsw I/F */
static int stor_init(void);
-static int stor_strategy(void *, int, daddr_t, size_t, char *, size_t *);
+static int stor_strategy(void *, int, daddr_t, size_t, size_t, char *,
+ size_t *);
static int stor_open(struct open_file *, ...);
static int stor_close(struct open_file *);
static int stor_ioctl(struct open_file *f, u_long cmd, void *data);
@@ -143,8 +144,8 @@
}
static int
-stor_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
- size_t *rsize)
+stor_strategy(void *devdata, int rw, daddr_t blk, size_t offset, size_t size,
+ char *buf, size_t *rsize)
{
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
daddr_t bcount;
Index: head/sys/boot/usb/storage/umass_loader.c
===================================================================
--- head/sys/boot/usb/storage/umass_loader.c
+++ head/sys/boot/usb/storage/umass_loader.c
@@ -48,7 +48,8 @@
static int umass_disk_close(struct open_file *);
static void umass_disk_cleanup(void);
static int umass_disk_ioctl(struct open_file *, u_long, void *);
-static int umass_disk_strategy(void *, int, daddr_t, size_t, char *, size_t *);
+static int umass_disk_strategy(void *, int, daddr_t, size_t, size_t, char *,
+ size_t *);
static void umass_disk_print(int);
struct devsw umass_disk = {
@@ -84,8 +85,8 @@
}
static int
-umass_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
- char *buf, size_t *rsizep)
+umass_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsizep)
{
if (umass_uaa.device == NULL)
return (ENXIO);
Index: head/sys/boot/userboot/userboot/host.c
===================================================================
--- head/sys/boot/userboot/userboot/host.c
+++ head/sys/boot/userboot/userboot/host.c
@@ -167,8 +167,8 @@
}
static int
-host_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
- char *buf, size_t *rsize)
+host_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
return (ENOSYS);
Index: head/sys/boot/userboot/userboot/main.c
===================================================================
--- head/sys/boot/userboot/userboot/main.c
+++ head/sys/boot/userboot/userboot/main.c
@@ -131,6 +131,10 @@
#endif
/*
+ * Initialise the block cache. Set the upper limit.
+ */
+ bcache_init(32768, 512);
+ /*
* March through the device switch probing for things.
*/
for (i = 0; devsw[i] != NULL; i++)
Index: head/sys/boot/userboot/userboot/userboot_disk.c
===================================================================
--- head/sys/boot/userboot/userboot/userboot_disk.c
+++ head/sys/boot/userboot/userboot/userboot_disk.c
@@ -42,6 +42,8 @@
struct userdisk_info {
uint64_t mediasize;
uint16_t sectorsize;
+ int ud_open; /* reference counter */
+ void *ud_bcache; /* buffer cache data */
};
int userboot_disk_maxunit = 0;
@@ -52,7 +54,9 @@
static int userdisk_init(void);
static void userdisk_cleanup(void);
static int userdisk_strategy(void *devdata, int flag, daddr_t dblk,
- size_t size, char *buf, size_t *rsize);
+ size_t offset, size_t size, char *buf, size_t *rsize);
+static int userdisk_realstrategy(void *devdata, int flag, daddr_t dblk,
+ size_t offset, size_t size, char *buf, size_t *rsize);
static int userdisk_open(struct open_file *f, ...);
static int userdisk_close(struct open_file *f);
static int userdisk_ioctl(struct open_file *f, u_long cmd, void *data);
@@ -92,9 +96,11 @@
return (ENXIO);
ud_info[i].mediasize = mediasize;
ud_info[i].sectorsize = sectorsize;
+ ud_info[i].ud_open = 0;
+ ud_info[i].ud_bcache = NULL;
}
}
-
+ bcache_add_dev(userdisk_maxunit);
return(0);
}
@@ -148,7 +154,9 @@
if (dev->d_unit < 0 || dev->d_unit >= userdisk_maxunit)
return (EIO);
-
+ ud_info[dev->d_unit].ud_open++;
+ if (ud_info[dev->d_unit].ud_bcache == NULL)
+ ud_info[dev->d_unit].ud_bcache = bcache_allocate();
return (disk_open(dev, ud_info[dev->d_unit].mediasize,
ud_info[dev->d_unit].sectorsize, 0));
}
@@ -159,12 +167,32 @@
struct disk_devdesc *dev;
dev = (struct disk_devdesc *)f->f_devdata;
+ ud_info[dev->d_unit].ud_open--;
+ if (ud_info[dev->d_unit].ud_open == 0) {
+ bcache_free(ud_info[dev->d_unit].ud_bcache);
+ ud_info[dev->d_unit].ud_bcache = NULL;
+ }
return (disk_close(dev));
}
static int
-userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
- char *buf, size_t *rsize)
+userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
+{
+ struct bcache_devdata bcd;
+ struct disk_devdesc *dev;
+
+ dev = (struct disk_devdesc *)devdata;
+ bcd.dv_strategy = userdisk_realstrategy;
+ bcd.dv_devdata = devdata;
+ bcd.dv_cache = ud_info[dev->d_unit].ud_bcache;
+ return (bcache_strategy(&bcd, rw, dblk + dev->d_offset, offset,
+ size, buf, rsize));
+}
+
+static int
+userdisk_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset,
+ size_t size, char *buf, size_t *rsize)
{
struct disk_devdesc *dev = devdata;
uint64_t off;
@@ -177,7 +205,7 @@
return (EINVAL);
if (rsize)
*rsize = 0;
- off = (dblk + dev->d_offset) * ud_info[dev->d_unit].sectorsize;
+ off = dblk * ud_info[dev->d_unit].sectorsize;
rc = CALLBACK(diskread, dev->d_unit, off, buf, size, &resid);
if (rc)
return (rc);
Index: head/sys/boot/zfs/zfs.c
===================================================================
--- head/sys/boot/zfs/zfs.c
+++ head/sys/boot/zfs/zfs.c
@@ -578,7 +578,7 @@
}
static int
-zfs_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, size_t *rsize)
+zfs_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size, char *buf, size_t *rsize)
{
return (ENOSYS);

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 25, 7:45 PM (58 m, 29 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
24186836
Default Alt Text
D4713.diff (65 KB)

Event Timeline