A new implementation of the loader block cache
The block cache implementation in loader has proven to be almost useless, and in worst case even slowing down the disk reads due to insufficient cache size and extra memory copy. Also the current cache implementation does not cache reads from CDs, or work with zfs built on top of multiple disks. Instead of an LRU, this code uses a simple hash (O(1) read from cache), and instead of a single global cache, a separate cache per block device. The cache also implements limited read-ahead to increase performance. To simplify read ahead management, the read ahead will not wrap over bcache end, so in worst case, single block physical read will be performed to fill the last block in bcache. Booting from a virtual CD over IPMI: 0ms latency, before: 27 second, after: 7 seconds 60ms latency, before: over 12 minutes, after: under 5 minutes. Submitted by: Toomas Soome <tsoome@me.com> Reviewed by: delphij (previous version), emaste (previous version) Relnotes: yes Differential Revision: https://reviews.freebsd.org/D4713
This commit is contained in:
parent
30e2910007
commit
87ed2b7f5a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=298230
@ -143,7 +143,7 @@ susp_lookup_record(struct open_file *f, const char *identifier,
|
|||||||
if (bcmp(sh->type, SUSP_CONTINUATION, 2) == 0) {
|
if (bcmp(sh->type, SUSP_CONTINUATION, 2) == 0) {
|
||||||
shc = (ISO_RRIP_CONT *)sh;
|
shc = (ISO_RRIP_CONT *)sh;
|
||||||
error = f->f_dev->dv_strategy(f->f_devdata, F_READ,
|
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);
|
ISO_DEFAULT_BLOCK_SIZE, susp_buffer, &read);
|
||||||
|
|
||||||
/* Bail if it fails. */
|
/* Bail if it fails. */
|
||||||
@ -288,7 +288,7 @@ cd9660_open(const char *path, struct open_file *f)
|
|||||||
for (bno = 16;; bno++) {
|
for (bno = 16;; bno++) {
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
|
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)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
if (read != ISO_DEFAULT_BLOCK_SIZE) {
|
if (read != ISO_DEFAULT_BLOCK_SIZE) {
|
||||||
@ -322,7 +322,7 @@ cd9660_open(const char *path, struct open_file *f)
|
|||||||
twiddle(1);
|
twiddle(1);
|
||||||
rc = f->f_dev->dv_strategy
|
rc = f->f_dev->dv_strategy
|
||||||
(f->f_devdata, F_READ,
|
(f->f_devdata, F_READ,
|
||||||
cdb2devb(bno + boff),
|
cdb2devb(bno + boff), 0,
|
||||||
ISO_DEFAULT_BLOCK_SIZE,
|
ISO_DEFAULT_BLOCK_SIZE,
|
||||||
buf, &read);
|
buf, &read);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -381,7 +381,7 @@ cd9660_open(const char *path, struct open_file *f)
|
|||||||
bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length);
|
bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length);
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno),
|
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)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
if (read != ISO_DEFAULT_BLOCK_SIZE) {
|
if (read != ISO_DEFAULT_BLOCK_SIZE) {
|
||||||
@ -438,7 +438,8 @@ buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
|
|||||||
|
|
||||||
twiddle(16);
|
twiddle(16);
|
||||||
rc = f->f_dev->dv_strategy(f->f_devdata, F_READ,
|
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)
|
if (rc)
|
||||||
return (rc);
|
return (rc);
|
||||||
if (read != ISO_DEFAULT_BLOCK_SIZE)
|
if (read != ISO_DEFAULT_BLOCK_SIZE)
|
||||||
|
@ -132,6 +132,17 @@ static DOS_DE dot[2] = {
|
|||||||
((u_int)cv2((de)->dex.h_clus) << 16) | \
|
((u_int)cv2((de)->dex.h_clus) << 16) | \
|
||||||
cv2((de)->clus))
|
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 dosunmount(DOS_FS *);
|
||||||
static int parsebs(DOS_FS *, DOS_BS *);
|
static int parsebs(DOS_FS *, DOS_BS *);
|
||||||
static int namede(DOS_FS *, const char *, DOS_DE **);
|
static int namede(DOS_FS *, const char *, DOS_DE **);
|
||||||
@ -143,8 +154,36 @@ static int fatcnt(DOS_FS *, u_int);
|
|||||||
static int fatget(DOS_FS *, u_int *);
|
static int fatget(DOS_FS *, u_int *);
|
||||||
static int fatend(u_int, u_int);
|
static int fatend(u_int, u_int);
|
||||||
static int ioread(DOS_FS *, u_int, void *, 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 *, daddr_t, size_t, void *, u_int);
|
||||||
static int ioget(struct open_file *, u_int, 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
|
* Mount DOS filesystem
|
||||||
@ -153,15 +192,25 @@ static int
|
|||||||
dos_mount(DOS_FS *fs, struct open_file *fd)
|
dos_mount(DOS_FS *fs, struct open_file *fd)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
struct devdesc *dd = fd->f_devdata;
|
||||||
|
u_char *buf;
|
||||||
|
|
||||||
bzero(fs, sizeof(DOS_FS));
|
bzero(fs, sizeof(DOS_FS));
|
||||||
fs->fd = fd;
|
fs->fd = fd;
|
||||||
if ((err = !(fs->buf = malloc(SECSIZ)) ? errno : 0) ||
|
|
||||||
(err = ioget(fs->fd, 0, fs->buf, 1)) ||
|
if ((err = !(buf = malloc(secbyt(1))) ? errno : 0) ||
|
||||||
(err = parsebs(fs, (DOS_BS *)fs->buf))) {
|
(err = ioget(fs->fd, 0, 0, buf, secbyt(1))) ||
|
||||||
|
(err = parsebs(fs, (DOS_BS *)buf))) {
|
||||||
|
if (buf != NULL)
|
||||||
|
free(buf);
|
||||||
(void)dosunmount(fs);
|
(void)dosunmount(fs);
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
if (fat.buf == NULL || fat.unit != dd->d_unit)
|
||||||
|
dos_read_fat(fs, fd);
|
||||||
|
|
||||||
fs->root = dot[0];
|
fs->root = dot[0];
|
||||||
fs->root.name[0] = ' ';
|
fs->root.name[0] = ' ';
|
||||||
if (fs->fatsz == 32) {
|
if (fs->fatsz == 32) {
|
||||||
@ -194,8 +243,6 @@ dos_unmount(DOS_FS *fs)
|
|||||||
static int
|
static int
|
||||||
dosunmount(DOS_FS *fs)
|
dosunmount(DOS_FS *fs)
|
||||||
{
|
{
|
||||||
if (fs->buf)
|
|
||||||
free(fs->buf);
|
|
||||||
free(fs);
|
free(fs);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
@ -252,42 +299,47 @@ dos_read(struct open_file *fd, void *buf, size_t nbyte, size_t *resid)
|
|||||||
DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
|
DOS_FILE *f = (DOS_FILE *)fd->f_fsdata;
|
||||||
int err = 0;
|
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;
|
nb = (u_int)nbyte;
|
||||||
if ((size = fsize(f->fs, &f->de)) == -1)
|
if ((size = fsize(f->fs, &f->de)) == -1)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
if (nb > (n = size - f->offset))
|
if (nb > (n = size - f->offset))
|
||||||
nb = n;
|
nb = n;
|
||||||
off = f->offset;
|
off = f->offset;
|
||||||
if ((clus = stclus(f->fs->fatsz, &f->de)))
|
if ((clus = stclus(f->fs->fatsz, &f->de)))
|
||||||
off &= f->fs->bsize - 1;
|
off &= f->fs->bsize - 1;
|
||||||
c = f->c;
|
c = f->c;
|
||||||
cnt = nb;
|
cnt = nb;
|
||||||
while (cnt) {
|
while (cnt) {
|
||||||
n = 0;
|
n = 0;
|
||||||
if (!c) {
|
if (!c) {
|
||||||
if ((c = clus))
|
if ((c = clus))
|
||||||
n = bytblk(f->fs, f->offset);
|
n = bytblk(f->fs, f->offset);
|
||||||
} else if (!off)
|
} else if (!off)
|
||||||
n++;
|
n++;
|
||||||
while (n--) {
|
while (n--) {
|
||||||
if ((err = fatget(f->fs, &c)))
|
if ((err = fatget(f->fs, &c)))
|
||||||
goto out;
|
goto out;
|
||||||
if (!okclus(f->fs, c)) {
|
if (!okclus(f->fs, c)) {
|
||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!clus || (n = f->fs->bsize - off) > cnt)
|
if (!clus || (n = f->fs->bsize - off) > cnt)
|
||||||
n = cnt;
|
n = cnt;
|
||||||
if ((err = ioread(f->fs, (c ? blkoff(f->fs, c) :
|
if ((err = ioread(f->fs, (c ? blkoff(f->fs, c) :
|
||||||
secbyt(f->fs->lsndir)) + off,
|
secbyt(f->fs->lsndir)) + off, buf, n)))
|
||||||
buf, n)))
|
|
||||||
goto out;
|
goto out;
|
||||||
f->offset += n;
|
f->offset += n;
|
||||||
f->c = c;
|
f->c = c;
|
||||||
off = 0;
|
off = 0;
|
||||||
buf = (char *)buf + n;
|
buf = (char *)buf + n;
|
||||||
cnt -= n;
|
cnt -= n;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (resid)
|
if (resid)
|
||||||
@ -363,6 +415,23 @@ dos_stat(struct open_file *fd, struct stat *sb)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static int
|
||||||
dos_readdir(struct open_file *fd, struct dirent *d)
|
dos_readdir(struct open_file *fd, struct dirent *d)
|
||||||
{
|
{
|
||||||
@ -417,12 +486,7 @@ dos_readdir(struct open_file *fd, struct dirent *d)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (xdn == 1) {
|
if (xdn == 1) {
|
||||||
x = 0;
|
x = dos_checksum(dd.de.name, dd.de.ext);
|
||||||
for (i = 0; i < 11; i++) {
|
|
||||||
x = ((x & 1) << 7) | (x >> 1);
|
|
||||||
x += dd.de.name[i];
|
|
||||||
x &= 0xff;
|
|
||||||
}
|
|
||||||
if (x == chk)
|
if (x == chk)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@ -555,7 +619,7 @@ lookup(DOS_FS *fs, u_int clus, const char *name, DOS_DE **dep)
|
|||||||
else
|
else
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
for (sec = 0; sec < nsec; sec++) {
|
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;
|
return err;
|
||||||
for (ent = 0; ent < DEPSEC; ent++) {
|
for (ent = 0; ent < DEPSEC; ent++) {
|
||||||
if (!*dir[ent].de.name)
|
if (!*dir[ent].de.name)
|
||||||
@ -577,9 +641,7 @@ lookup(DOS_FS *fs, u_int clus, const char *name, DOS_DE **dep)
|
|||||||
}
|
}
|
||||||
} else if (!(dir[ent].de.attr & FA_LABEL)) {
|
} else if (!(dir[ent].de.attr & FA_LABEL)) {
|
||||||
if ((ok = xdn == 1)) {
|
if ((ok = xdn == 1)) {
|
||||||
for (x = 0, i = 0; i < 11; i++)
|
x = dos_checksum(dir[ent].de.name, dir[ent].de.ext);
|
||||||
x = ((((x & 1) << 7) | (x >> 1)) +
|
|
||||||
dir[ent].de.name[i]) & 0xff;
|
|
||||||
ok = chk == x &&
|
ok = chk == x &&
|
||||||
!strcasecmp(name, (const char *)lfn);
|
!strcasecmp(name, (const char *)lfn);
|
||||||
}
|
}
|
||||||
@ -699,22 +761,52 @@ fatcnt(DOS_FS *fs, u_int c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get next cluster in cluster chain
|
* Get next cluster in cluster chain. Use in core fat cache unless another
|
||||||
|
* device replaced it.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
fatget(DOS_FS *fs, u_int *c)
|
fatget(DOS_FS *fs, u_int *c)
|
||||||
{
|
{
|
||||||
u_char buf[4];
|
u_char buf[4];
|
||||||
u_int x;
|
u_char *s;
|
||||||
int err;
|
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);
|
x = fs->fatsz != 32 ? cv2(buf) : cv4(buf);
|
||||||
*c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x;
|
*c = fs->fatsz == 12 ? *c & 1 ? x >> 4 : x & 0xfff : x;
|
||||||
return 0;
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -739,42 +831,24 @@ ioread(DOS_FS *fs, u_int offset, void *buf, u_int nbyte)
|
|||||||
s = buf;
|
s = buf;
|
||||||
if ((off = offset & (SECSIZ - 1))) {
|
if ((off = offset & (SECSIZ - 1))) {
|
||||||
offset -= off;
|
offset -= off;
|
||||||
if ((err = iobuf(fs, bytsec(offset))))
|
|
||||||
return err;
|
|
||||||
offset += SECSIZ;
|
|
||||||
if ((n = SECSIZ - off) > nbyte)
|
if ((n = SECSIZ - off) > nbyte)
|
||||||
n = 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;
|
s += n;
|
||||||
nbyte -= n;
|
nbyte -= n;
|
||||||
}
|
}
|
||||||
n = nbyte & (SECSIZ - 1);
|
n = nbyte & (SECSIZ - 1);
|
||||||
if (nbyte -= n) {
|
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;
|
return err;
|
||||||
offset += nbyte;
|
offset += nbyte;
|
||||||
s += nbyte;
|
s += nbyte;
|
||||||
}
|
}
|
||||||
if (n) {
|
if (n) {
|
||||||
if ((err = iobuf(fs, bytsec(offset))))
|
if ((err = ioget(fs->fd, bytsec(offset), 0, s, n)))
|
||||||
return err;
|
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)))
|
|
||||||
return err;
|
|
||||||
fs->bufsec = lsec;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -783,13 +857,8 @@ iobuf(DOS_FS *fs, u_int lsec)
|
|||||||
* Sector-based I/O primitive
|
* Sector-based I/O primitive
|
||||||
*/
|
*/
|
||||||
static int
|
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;
|
return ((fd->f_dev->dv_strategy)(fd->f_devdata, F_READ, lsec, offset,
|
||||||
|
size, buf, NULL));
|
||||||
twiddle(1);
|
|
||||||
if ((err = (fd->f_dev->dv_strategy)(fd->f_devdata, F_READ, lsec,
|
|
||||||
secbyt(nsec), buf, NULL)))
|
|
||||||
return(err);
|
|
||||||
return(0);
|
|
||||||
}
|
}
|
||||||
|
@ -96,8 +96,6 @@ typedef union {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct open_file *fd; /* file descriptor */
|
struct open_file *fd; /* file descriptor */
|
||||||
u_char *buf; /* buffer */
|
|
||||||
u_int bufsec; /* buffered sector */
|
|
||||||
u_int links; /* active links to structure */
|
u_int links; /* active links to structure */
|
||||||
u_int spc; /* sectors per cluster */
|
u_int spc; /* sectors per cluster */
|
||||||
u_int bsize; /* cluster size in bytes */
|
u_int bsize; /* cluster size in bytes */
|
||||||
|
@ -355,7 +355,7 @@ ext2fs_open(const char *upath, struct open_file *f)
|
|||||||
fp->f_fs = fs;
|
fp->f_fs = fs;
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -397,7 +397,7 @@ ext2fs_open(const char *upath, struct open_file *f)
|
|||||||
fp->f_bg = malloc(len);
|
fp->f_bg = malloc(len);
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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);
|
(char *)fp->f_bg, &buf_size);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
@ -509,7 +509,7 @@ ext2fs_open(const char *upath, struct open_file *f)
|
|||||||
|
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
error = (f->f_dev->dv_strategy)(f->f_devdata,
|
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);
|
fs->fs_bsize, buf, &buf_size);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
@ -570,7 +570,7 @@ read_inode(ino_t inumber, struct open_file *f)
|
|||||||
buf = malloc(fs->fs_bsize);
|
buf = malloc(fs->fs_bsize);
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
if (rsize != fs->fs_bsize) {
|
if (rsize != fs->fs_bsize) {
|
||||||
@ -667,7 +667,7 @@ block_map(struct open_file *f, daddr_t file_block, daddr_t *disk_block_p)
|
|||||||
malloc(fs->fs_bsize);
|
malloc(fs->fs_bsize);
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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]);
|
fp->f_blk[level], &fp->f_blksize[level]);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
@ -725,7 +725,7 @@ buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
|
|||||||
} else {
|
} else {
|
||||||
twiddle(4);
|
twiddle(4);
|
||||||
error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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);
|
fp->f_buf, &fp->f_buf_size);
|
||||||
if (error)
|
if (error)
|
||||||
goto done;
|
goto done;
|
||||||
|
@ -79,7 +79,7 @@ read(int fd, void *dest, size_t bcount)
|
|||||||
if (f->f_flags & F_RAW) {
|
if (f->f_flags & F_RAW) {
|
||||||
twiddle(4);
|
twiddle(4);
|
||||||
errno = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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)
|
if (errno)
|
||||||
return (-1);
|
return (-1);
|
||||||
f->f_offset += resid;
|
f->f_offset += resid;
|
||||||
|
@ -138,8 +138,8 @@ struct devsw {
|
|||||||
const char dv_name[8];
|
const char dv_name[8];
|
||||||
int dv_type; /* opaque type constant, arch-dependant */
|
int dv_type; /* opaque type constant, arch-dependant */
|
||||||
int (*dv_init)(void); /* early probe call */
|
int (*dv_init)(void); /* early probe call */
|
||||||
int (*dv_strategy)(void *devdata, int rw, daddr_t blk, size_t size,
|
int (*dv_strategy)(void *devdata, int rw, daddr_t blk,
|
||||||
char *buf, size_t *rsize);
|
size_t offset, size_t size, char *buf, size_t *rsize);
|
||||||
int (*dv_open)(struct open_file *f, ...);
|
int (*dv_open)(struct open_file *f, ...);
|
||||||
int (*dv_close)(struct open_file *f);
|
int (*dv_close)(struct open_file *f);
|
||||||
int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data);
|
int (*dv_ioctl)(struct open_file *f, u_long cmd, void *data);
|
||||||
@ -154,6 +154,24 @@ extern struct devsw netdev;
|
|||||||
|
|
||||||
extern int errno;
|
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 {
|
struct open_file {
|
||||||
int f_flags; /* see F_* below */
|
int f_flags; /* see F_* below */
|
||||||
struct devsw *f_dev; /* pointer to device operations */
|
struct devsw *f_dev; /* pointer to device operations */
|
||||||
|
@ -157,7 +157,7 @@ read_inode(inumber, f)
|
|||||||
buf = malloc(fs->fs_bsize);
|
buf = malloc(fs->fs_bsize);
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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);
|
buf, &rsize);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
@ -267,7 +267,7 @@ block_map(f, file_block, disk_block_p)
|
|||||||
malloc(fs->fs_bsize);
|
malloc(fs->fs_bsize);
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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,
|
fs->fs_bsize,
|
||||||
fp->f_blk[level],
|
fp->f_blk[level],
|
||||||
&fp->f_blksize[level]);
|
&fp->f_blksize[level]);
|
||||||
@ -348,7 +348,7 @@ buf_write_file(f, buf_p, size_p)
|
|||||||
|
|
||||||
twiddle(4);
|
twiddle(4);
|
||||||
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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);
|
block_size, fp->f_buf, &fp->f_buf_size);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (rc);
|
return (rc);
|
||||||
@ -367,7 +367,7 @@ buf_write_file(f, buf_p, size_p)
|
|||||||
|
|
||||||
twiddle(4);
|
twiddle(4);
|
||||||
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
|
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);
|
block_size, fp->f_buf, &fp->f_buf_size);
|
||||||
return (rc);
|
return (rc);
|
||||||
}
|
}
|
||||||
@ -408,7 +408,7 @@ buf_read_file(f, buf_p, size_p)
|
|||||||
} else {
|
} else {
|
||||||
twiddle(4);
|
twiddle(4);
|
||||||
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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);
|
block_size, fp->f_buf, &fp->f_buf_size);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (rc);
|
return (rc);
|
||||||
@ -521,7 +521,7 @@ ufs_open(upath, f)
|
|||||||
*/
|
*/
|
||||||
for (i = 0; sblock_try[i] != -1; i++) {
|
for (i = 0; sblock_try[i] != -1; i++) {
|
||||||
rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
|
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);
|
(char *)fs, &buf_size);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
@ -651,7 +651,7 @@ ufs_open(upath, f)
|
|||||||
|
|
||||||
twiddle(1);
|
twiddle(1);
|
||||||
rc = (f->f_dev->dv_strategy)(f->f_devdata,
|
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);
|
fs->fs_bsize, buf, &buf_size);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -82,7 +82,7 @@ write(fd, dest, bcount)
|
|||||||
if (f->f_flags & F_RAW) {
|
if (f->f_flags & F_RAW) {
|
||||||
twiddle(4);
|
twiddle(4);
|
||||||
errno = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
|
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)
|
if (errno)
|
||||||
return (-1);
|
return (-1);
|
||||||
f->f_offset += resid;
|
f->f_offset += resid;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*-
|
/*-
|
||||||
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
|
* Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
|
||||||
|
* Copyright 2015 Toomas Soome <tsoome@me.com>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -25,99 +26,155 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/param.h>
|
||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simple LRU block cache
|
* Simple hashed block cache
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/stdint.h>
|
#include <sys/stdint.h>
|
||||||
|
|
||||||
#include <stand.h>
|
#include <stand.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <bitstring.h>
|
#include <strings.h>
|
||||||
|
|
||||||
#include "bootstrap.h"
|
#include "bootstrap.h"
|
||||||
|
|
||||||
/* #define BCACHE_DEBUG */
|
/* #define BCACHE_DEBUG */
|
||||||
|
|
||||||
#ifdef BCACHE_DEBUG
|
#ifdef BCACHE_DEBUG
|
||||||
#define BCACHE_TIMEOUT 10
|
|
||||||
# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
|
# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __func__ , ## args)
|
||||||
#else
|
#else
|
||||||
#define BCACHE_TIMEOUT 2
|
|
||||||
# define DEBUG(fmt, args...)
|
# define DEBUG(fmt, args...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct bcachectl
|
struct bcachectl
|
||||||
{
|
{
|
||||||
daddr_t bc_blkno;
|
daddr_t bc_blkno;
|
||||||
time_t bc_stamp;
|
|
||||||
int bc_count;
|
int bc_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bcachectl *bcache_ctl;
|
/*
|
||||||
static caddr_t bcache_data;
|
* bcache per device node. cache is allocated on device first open and freed
|
||||||
static bitstr_t *bcache_miss;
|
* on last close, to save memory. The issue there is the size; biosdisk
|
||||||
static u_int bcache_nblks;
|
* supports up to 31 (0x1f) devices. Classic setup would use single disk
|
||||||
static u_int bcache_blksize;
|
* to boot from, but this has changed with zfs.
|
||||||
static u_int bcache_hits, bcache_misses, bcache_ops, bcache_bypasses;
|
*/
|
||||||
static u_int bcache_flushes;
|
struct bcache {
|
||||||
static u_int bcache_bcount;
|
struct bcachectl *bcache_ctl;
|
||||||
|
caddr_t bcache_data;
|
||||||
|
u_int bcache_nblks;
|
||||||
|
size_t ra;
|
||||||
|
};
|
||||||
|
|
||||||
static void bcache_invalidate(daddr_t blkno);
|
static u_int bcache_total_nblks; /* set by bcache_init */
|
||||||
static void bcache_insert(caddr_t buf, daddr_t blkno);
|
static u_int bcache_blksize; /* set by bcache_init */
|
||||||
static int bcache_lookup(caddr_t buf, daddr_t blkno);
|
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).
|
* Initialise the cache for (nblks) of (bsize).
|
||||||
*/
|
*/
|
||||||
int
|
void
|
||||||
bcache_init(u_int nblks, size_t bsize)
|
bcache_init(u_int nblks, size_t bsize)
|
||||||
{
|
{
|
||||||
/* discard any old contents */
|
/* set up control data */
|
||||||
if (bcache_data != NULL) {
|
bcache_total_nblks = nblks;
|
||||||
free(bcache_data);
|
|
||||||
bcache_data = NULL;
|
|
||||||
free(bcache_ctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate control structures */
|
|
||||||
bcache_nblks = nblks;
|
|
||||||
bcache_blksize = bsize;
|
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
|
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 */
|
/* Flush the cache */
|
||||||
for (i = 0; i < bcache_nblks; i++) {
|
for (i = 0; i < bc->bcache_nblks; i++) {
|
||||||
bcache_ctl[i].bc_count = -1;
|
bc->bcache_ctl[i].bc_count = -1;
|
||||||
bcache_ctl[i].bc_blkno = -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 @@ bcache_flush(void)
|
|||||||
* cache with the new values.
|
* cache with the new values.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
write_strategy(void *devdata, int unit, int rw, daddr_t blk, size_t size,
|
write_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
|
||||||
char *buf, size_t *rsize)
|
size_t size, char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct bcache_devdata *dd = (struct bcache_devdata *)devdata;
|
struct bcache_devdata *dd = (struct bcache_devdata *)devdata;
|
||||||
|
struct bcache *bc = dd->dv_cache;
|
||||||
daddr_t i, nblk;
|
daddr_t i, nblk;
|
||||||
int err;
|
|
||||||
|
|
||||||
nblk = size / bcache_blksize;
|
nblk = size / bcache_blksize;
|
||||||
|
|
||||||
/* Invalidate the blocks being written */
|
/* Invalidate the blocks being written */
|
||||||
for (i = 0; i < nblk; i++) {
|
for (i = 0; i < nblk; i++) {
|
||||||
bcache_invalidate(blk + i);
|
bcache_invalidate(bc, blk + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write the blocks */
|
/* Write the blocks */
|
||||||
err = dd->dv_strategy(dd->dv_devdata, rw, blk, size, buf, rsize);
|
return (dd->dv_strategy(dd->dv_devdata, rw, blk, offset, 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -158,60 +206,86 @@ write_strategy(void *devdata, int unit, int rw, daddr_t blk, size_t size,
|
|||||||
* device I/O and then use the I/O results to populate the cache.
|
* device I/O and then use the I/O results to populate the cache.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
read_strategy(void *devdata, int unit, int rw, daddr_t blk, size_t size,
|
read_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
|
||||||
char *buf, size_t *rsize)
|
size_t size, char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct bcache_devdata *dd = (struct bcache_devdata *)devdata;
|
struct bcache_devdata *dd = (struct bcache_devdata *)devdata;
|
||||||
int p_size, result;
|
struct bcache *bc = dd->dv_cache;
|
||||||
daddr_t p_blk, i, j, nblk;
|
size_t i, nblk, p_size, r_size, complete, ra;
|
||||||
|
int result;
|
||||||
|
daddr_t p_blk;
|
||||||
caddr_t p_buf;
|
caddr_t p_buf;
|
||||||
|
|
||||||
nblk = size / bcache_blksize;
|
if (bc == NULL) {
|
||||||
result = 0;
|
errno = ENODEV;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Satisfy any cache hits up front */
|
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, break on first miss */
|
||||||
for (i = 0; i < nblk; i++) {
|
for (i = 0; i < nblk; i++) {
|
||||||
if (bcache_lookup(buf + (bcache_blksize * i), blk + i)) {
|
if (BCACHE_LOOKUP(bc, (daddr_t)(blk + i))) {
|
||||||
bit_set(bcache_miss, i); /* cache miss */
|
bcache_misses += (nblk - i);
|
||||||
bcache_misses++;
|
complete = 0;
|
||||||
|
if (nblk - i > BCACHE_MINREADAHEAD && bc->ra > BCACHE_MINREADAHEAD)
|
||||||
|
bc->ra >>= 1; /* reduce read ahead */
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
bit_clear(bcache_miss, i); /* cache hit */
|
|
||||||
bcache_hits++;
|
bcache_hits++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Go back and fill in any misses XXX optimise */
|
if (complete) { /* whole set was in cache, return it */
|
||||||
p_blk = -1;
|
if (bc->ra < BCACHE_READAHEAD)
|
||||||
p_buf = NULL;
|
bc->ra <<= 1; /* increase read ahead */
|
||||||
p_size = 0;
|
bcopy(bc->bcache_data + (bcache_blksize * BHASH(bc, blk)) + offset,
|
||||||
for (i = 0; i < nblk; i++) {
|
buf, size);
|
||||||
if (bit_test(bcache_miss, i)) {
|
goto done;
|
||||||
/* miss, add to pending transfer */
|
}
|
||||||
if (p_blk == -1) {
|
|
||||||
p_blk = blk + i;
|
/*
|
||||||
p_buf = buf + (bcache_blksize * i);
|
* Fill in any misses. From check we have i pointing to first missing
|
||||||
p_size = 1;
|
* block, read in all remaining blocks + readahead.
|
||||||
} else {
|
* We have space at least for nblk - i before bcache wraps.
|
||||||
p_size++;
|
*/
|
||||||
}
|
p_blk = blk + i;
|
||||||
} else if (p_blk != -1) {
|
p_buf = bc->bcache_data + (bcache_blksize * BHASH(bc, p_blk));
|
||||||
/* hit, complete pending transfer */
|
r_size = bc->bcache_nblks - BHASH(bc, p_blk); /* remaining blocks */
|
||||||
result = dd->dv_strategy(dd->dv_devdata, rw, p_blk, p_size * bcache_blksize, p_buf, NULL);
|
|
||||||
if (result != 0)
|
p_size = MIN(r_size, nblk - i); /* read at least those blocks */
|
||||||
goto done;
|
|
||||||
for (j = 0; j < p_size; j++)
|
ra = bc->bcache_nblks - BHASH(bc, p_blk + p_size);
|
||||||
bcache_insert(p_buf + (j * bcache_blksize), p_blk + j);
|
if (ra != bc->bcache_nblks) { /* do we have RA space? */
|
||||||
p_blk = -1;
|
ra = MIN(bc->ra, ra);
|
||||||
}
|
p_size += ra;
|
||||||
}
|
}
|
||||||
if (p_blk != -1) {
|
|
||||||
/* pending transfer left */
|
/* invalidate bcache */
|
||||||
result = dd->dv_strategy(dd->dv_devdata, rw, p_blk, p_size * bcache_blksize, p_buf, NULL);
|
for (i = 0; i < p_size; i++) {
|
||||||
if (result != 0)
|
bcache_invalidate(bc, p_blk + i);
|
||||||
goto done;
|
|
||||||
for (j = 0; j < p_size; j++)
|
|
||||||
bcache_insert(p_buf + (j * bcache_blksize), p_blk + j);
|
|
||||||
}
|
}
|
||||||
|
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:
|
done:
|
||||||
if ((result == 0) && (rsize != NULL))
|
if ((result == 0) && (rsize != NULL))
|
||||||
@ -220,130 +294,144 @@ read_strategy(void *devdata, int unit, int rw, daddr_t blk, size_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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.
|
* directly to the disk. XXX tune this.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
bcache_strategy(void *devdata, int unit, int rw, daddr_t blk, size_t size,
|
bcache_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
|
||||||
char *buf, size_t *rsize)
|
size_t size, char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
static int bcache_unit = -1;
|
|
||||||
struct bcache_devdata *dd = (struct bcache_devdata *)devdata;
|
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++;
|
bcache_ops++;
|
||||||
|
|
||||||
if(bcache_unit != unit) {
|
if (bc != NULL)
|
||||||
bcache_flush();
|
bcache_nblks = bc->bcache_nblks;
|
||||||
bcache_unit = unit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* bypass large requests, or when the cache is inactive */
|
/* 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);
|
DEBUG("bypass %d from %d", size / bcache_blksize, blk);
|
||||||
bcache_bypasses++;
|
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) {
|
switch (rw) {
|
||||||
case F_READ:
|
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:
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Insert a block into the cache. Retire the oldest block to do so, if required.
|
* Free allocated bcache instance
|
||||||
*
|
|
||||||
* XXX the LRU algorithm will fail after 2^31 blocks have been transferred.
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
bcache_insert(caddr_t buf, daddr_t blkno)
|
bcache_free_instance(struct bcache *bc)
|
||||||
{
|
{
|
||||||
time_t now;
|
if (bc != NULL) {
|
||||||
int cand, ocount;
|
if (bc->bcache_ctl)
|
||||||
u_int i;
|
free(bc->bcache_ctl);
|
||||||
|
if (bc->bcache_data)
|
||||||
time(&now);
|
free(bc->bcache_data);
|
||||||
cand = 0; /* assume the first block */
|
free(bc);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
* Insert a block into the cache.
|
||||||
* may be stale (removable media) and thus are discarded. Copy the block out
|
|
||||||
* if successful and return zero, or return nonzero on failure.
|
|
||||||
*/
|
*/
|
||||||
static int
|
static void
|
||||||
bcache_lookup(caddr_t buf, daddr_t blkno)
|
bcache_insert(struct bcache *bc, daddr_t blkno)
|
||||||
{
|
{
|
||||||
time_t now;
|
u_int cand;
|
||||||
u_int i;
|
|
||||||
|
|
||||||
time(&now);
|
cand = BHASH(bc, blkno);
|
||||||
|
|
||||||
for (i = 0; i < bcache_nblks; i++)
|
DEBUG("insert blk %llu -> %u # %d", blkno, cand, bcache_bcount);
|
||||||
/* cache hit? */
|
bc->bcache_ctl[cand].bc_blkno = blkno;
|
||||||
if ((bcache_ctl[i].bc_blkno == blkno) && ((bcache_ctl[i].bc_stamp + BCACHE_TIMEOUT) >= now)) {
|
bc->bcache_ctl[cand].bc_count = bcache_bcount++;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Invalidate a block from the cache.
|
* Invalidate a block from the cache.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
bcache_invalidate(daddr_t blkno)
|
bcache_invalidate(struct bcache *bc, daddr_t blkno)
|
||||||
{
|
{
|
||||||
u_int i;
|
u_int i;
|
||||||
|
|
||||||
for (i = 0; i < bcache_nblks; i++) {
|
i = BHASH(bc, blkno);
|
||||||
if (bcache_ctl[i].bc_blkno == blkno) {
|
if (bc->bcache_ctl[i].bc_blkno == blkno) {
|
||||||
bcache_ctl[i].bc_count = -1;
|
bc->bcache_ctl[i].bc_count = -1;
|
||||||
bcache_ctl[i].bc_blkno = -1;
|
bc->bcache_ctl[i].bc_blkno = -1;
|
||||||
DEBUG("invalidate blk %d", blkno);
|
DEBUG("invalidate blk %llu", blkno);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef BOOT2
|
||||||
COMMAND_SET(bcachestat, "bcachestat", "get disk block cache stats", command_bcache);
|
COMMAND_SET(bcachestat, "bcachestat", "get disk block cache stats", command_bcache);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
command_bcache(int argc, char *argv[])
|
command_bcache(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
u_int i;
|
if (argc != 1) {
|
||||||
|
command_errmsg = "wrong number of arguments";
|
||||||
for (i = 0; i < bcache_nblks; i++) {
|
return(CMD_ERROR);
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
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);
|
return(CMD_OK);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -33,24 +33,6 @@
|
|||||||
#include <sys/queue.h>
|
#include <sys/queue.h>
|
||||||
#include <sys/linker_set.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 */
|
/* Commands and return values; nonzero return sets command_errmsg != NULL */
|
||||||
typedef int (bootblk_cmd_t)(int argc, char *argv[]);
|
typedef int (bootblk_cmd_t)(int argc, char *argv[]);
|
||||||
extern char *command_errmsg;
|
extern char *command_errmsg;
|
||||||
@ -90,9 +72,11 @@ int kern_pread(int fd, vm_offset_t dest, size_t len, off_t off);
|
|||||||
void *alloc_pread(int fd, off_t off, size_t len);
|
void *alloc_pread(int fd, off_t off, size_t len);
|
||||||
|
|
||||||
/* bcache.c */
|
/* bcache.c */
|
||||||
int bcache_init(u_int nblks, size_t bsize);
|
void bcache_init(u_int nblks, size_t bsize);
|
||||||
void bcache_flush(void);
|
void bcache_add_dev(int);
|
||||||
int bcache_strategy(void *devdata, int unit, int rw, daddr_t blk,
|
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);
|
size_t size, char *buf, size_t *rsize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -100,8 +84,10 @@ int bcache_strategy(void *devdata, int unit, int rw, daddr_t blk,
|
|||||||
*/
|
*/
|
||||||
struct bcache_devdata
|
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_devdata;
|
||||||
|
void *dv_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -178,7 +178,7 @@ ptblread(void *d, void *buf, size_t blocks, off_t offset)
|
|||||||
|
|
||||||
dev = (struct disk_devdesc *)d;
|
dev = (struct disk_devdesc *)d;
|
||||||
od = (struct open_disk *)dev->d_opendata;
|
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));
|
blocks * od->sectorsize, (char *)buf, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +239,7 @@ disk_read(struct disk_devdesc *dev, void *buf, off_t offset, u_int blocks)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
od = (struct open_disk *)dev->d_opendata;
|
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);
|
blocks * od->sectorsize, buf, NULL);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
@ -252,7 +252,7 @@ disk_write(struct disk_devdesc *dev, void *buf, off_t offset, u_int blocks)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
od = (struct open_disk *)dev->d_opendata;
|
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);
|
blocks * od->sectorsize, buf, NULL);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -60,7 +60,7 @@ static struct {
|
|||||||
|
|
||||||
/* devsw I/F */
|
/* devsw I/F */
|
||||||
static int md_init(void);
|
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_open(struct open_file *, ...);
|
||||||
static int md_close(struct open_file *);
|
static int md_close(struct open_file *);
|
||||||
static void md_print(int);
|
static void md_print(int);
|
||||||
@ -84,8 +84,8 @@ md_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
md_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
|
md_strategy(void *devdata, int rw, daddr_t blk, size_t offset, size_t size,
|
||||||
size_t *rsize)
|
char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct devdesc *dev = (struct devdesc *)devdata;
|
struct devdesc *dev = (struct devdesc *)devdata;
|
||||||
size_t ofs;
|
size_t ofs;
|
||||||
|
@ -769,7 +769,7 @@ mod_search_hints(struct moduledir *mdp, const char *modname,
|
|||||||
intp = (int*)recptr;
|
intp = (int*)recptr;
|
||||||
reclen = *intp++;
|
reclen = *intp++;
|
||||||
ival = *intp++;
|
ival = *intp++;
|
||||||
cp = (char*)intp;
|
cp = (u_char*)intp;
|
||||||
switch (ival) {
|
switch (ival) {
|
||||||
case MDT_VERSION:
|
case MDT_VERSION:
|
||||||
clen = *cp++;
|
clen = *cp++;
|
||||||
@ -801,9 +801,9 @@ mod_search_hints(struct moduledir *mdp, const char *modname,
|
|||||||
* Finally check if KLD is in the place
|
* Finally check if KLD is in the place
|
||||||
*/
|
*/
|
||||||
if (found)
|
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)
|
else if (best)
|
||||||
result = file_lookup(mdp->d_path, best, blen, NULL);
|
result = file_lookup(mdp->d_path, (const char *)best, blen, NULL);
|
||||||
bad:
|
bad:
|
||||||
/*
|
/*
|
||||||
* If nothing found or hints is absent - fallback to the old way
|
* If nothing found or hints is absent - fallback to the old way
|
||||||
|
@ -42,7 +42,10 @@ static EFI_GUID blkio_guid = BLOCK_IO_PROTOCOL;
|
|||||||
static EFI_GUID devpath_guid = DEVICE_PATH_PROTOCOL;
|
static EFI_GUID devpath_guid = DEVICE_PATH_PROTOCOL;
|
||||||
|
|
||||||
static int efipart_init(void);
|
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_open(struct open_file *, ...);
|
||||||
static int efipart_close(struct open_file *);
|
static int efipart_close(struct open_file *);
|
||||||
static void efipart_print(int);
|
static void efipart_print(int);
|
||||||
@ -59,6 +62,21 @@ struct devsw efipart_dev = {
|
|||||||
.dv_cleanup = NULL
|
.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
|
static int
|
||||||
efipart_init(void)
|
efipart_init(void)
|
||||||
{
|
{
|
||||||
@ -140,8 +158,13 @@ efipart_init(void)
|
|||||||
} else
|
} else
|
||||||
hout[nout] = hin[n];
|
hout[nout] = hin[n];
|
||||||
nout++;
|
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);
|
err = efi_register_handles(&efipart_dev, hout, aliases, nout);
|
||||||
free(hin);
|
free(hin);
|
||||||
return (err);
|
return (err);
|
||||||
@ -198,6 +221,9 @@ efipart_open(struct open_file *f, ...)
|
|||||||
return (EAGAIN);
|
return (EAGAIN);
|
||||||
|
|
||||||
dev->d_opendata = blkio;
|
dev->d_opendata = blkio;
|
||||||
|
PD(dev).pd_open++;
|
||||||
|
if (PD(dev).pd_bcache == NULL)
|
||||||
|
PD(dev).pd_bcache = bcache_allocate();
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +237,11 @@ efipart_close(struct open_file *f)
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
|
||||||
dev->d_opendata = NULL;
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,8 +286,23 @@ efipart_readwrite(EFI_BLOCK_IO *blkio, int rw, daddr_t blk, daddr_t nblks,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
efipart_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
|
efipart_strategy(void *devdata, int rw, daddr_t blk, size_t offset,
|
||||||
size_t *rsize)
|
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;
|
struct devdesc *dev = (struct devdesc *)devdata;
|
||||||
EFI_BLOCK_IO *blkio;
|
EFI_BLOCK_IO *blkio;
|
||||||
|
@ -102,7 +102,7 @@ efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
|
|||||||
(void)console_control->SetMode(console_control,
|
(void)console_control->SetMode(console_control,
|
||||||
EfiConsoleControlScreenText);
|
EfiConsoleControlScreenText);
|
||||||
|
|
||||||
heapsize = 3 * 1024 * 1024;
|
heapsize = 64 * 1024 * 1024;
|
||||||
status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
|
status = BS->AllocatePages(AllocateAnyPages, EfiLoaderData,
|
||||||
EFI_SIZE_TO_PAGES(heapsize), &heap);
|
EFI_SIZE_TO_PAGES(heapsize), &heap);
|
||||||
if (status != EFI_SUCCESS)
|
if (status != EFI_SUCCESS)
|
||||||
|
@ -209,6 +209,11 @@ main(int argc, CHAR16 *argv[])
|
|||||||
*/
|
*/
|
||||||
cons_probe();
|
cons_probe();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise the block cache. Set the upper limit.
|
||||||
|
*/
|
||||||
|
bcache_init(32768, 512);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse the args to set the console settings, etc
|
* Parse the args to set the console settings, etc
|
||||||
* boot1.efi passes these in, if it can read /boot.config or /boot/config
|
* boot1.efi passes these in, if it can read /boot.config or /boot/config
|
||||||
|
@ -66,7 +66,7 @@ struct crom_src_buf {
|
|||||||
|
|
||||||
static int fw_init(void);
|
static int fw_init(void);
|
||||||
static int fw_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int fw_close(struct open_file *f);
|
static int fw_close(struct open_file *f);
|
||||||
static void fw_print(int verbose);
|
static void fw_print(int verbose);
|
||||||
@ -201,7 +201,8 @@ fw_cleanup()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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);
|
return (EIO);
|
||||||
}
|
}
|
||||||
|
@ -85,13 +85,19 @@ struct specification_packet {
|
|||||||
static struct bcinfo {
|
static struct bcinfo {
|
||||||
int bc_unit; /* BIOS unit number */
|
int bc_unit; /* BIOS unit number */
|
||||||
struct specification_packet bc_sp;
|
struct specification_packet bc_sp;
|
||||||
|
int bc_open; /* reference counter */
|
||||||
|
void *bc_bcache; /* buffer cache data */
|
||||||
} bcinfo [MAXBCDEV];
|
} bcinfo [MAXBCDEV];
|
||||||
static int nbcinfo = 0;
|
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_read(int unit, daddr_t dblk, int blks, caddr_t dest);
|
||||||
static int bc_init(void);
|
static int bc_init(void);
|
||||||
static int bc_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int bc_close(struct open_file *f);
|
static int bc_close(struct open_file *f);
|
||||||
static void bc_print(int verbose);
|
static void bc_print(int verbose);
|
||||||
@ -164,6 +170,7 @@ bc_add(int biosdev)
|
|||||||
|
|
||||||
printf("BIOS CD is cd%d\n", nbcinfo);
|
printf("BIOS CD is cd%d\n", nbcinfo);
|
||||||
nbcinfo++;
|
nbcinfo++;
|
||||||
|
bcache_add_dev(nbcinfo); /* register cd device in bcache */
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,19 +207,44 @@ bc_open(struct open_file *f, ...)
|
|||||||
return(ENXIO);
|
return(ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BC(dev).bc_open++;
|
||||||
|
if (BC(dev).bc_bcache == NULL)
|
||||||
|
BC(dev).bc_bcache = bcache_allocate();
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bc_close(struct open_file *f)
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
|
bc_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
|
||||||
size_t *rsize)
|
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_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
|
||||||
|
char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct i386_devdesc *dev;
|
struct i386_devdesc *dev;
|
||||||
int unit;
|
int unit;
|
||||||
|
@ -114,6 +114,8 @@ static struct bdinfo
|
|||||||
int bd_type; /* BIOS 'drive type' (floppy only) */
|
int bd_type; /* BIOS 'drive type' (floppy only) */
|
||||||
uint16_t bd_sectorsize; /* Sector size */
|
uint16_t bd_sectorsize; /* Sector size */
|
||||||
uint64_t bd_sectors; /* Disk size */
|
uint64_t bd_sectors; /* Disk size */
|
||||||
|
int bd_open; /* reference counter */
|
||||||
|
void *bd_bcache; /* buffer cache data */
|
||||||
} bdinfo [MAXBDDEV];
|
} bdinfo [MAXBDDEV];
|
||||||
static int nbdinfo = 0;
|
static int nbdinfo = 0;
|
||||||
|
|
||||||
@ -126,9 +128,9 @@ static int bd_write(struct disk_devdesc *dev, daddr_t dblk, int blks,
|
|||||||
static int bd_int13probe(struct bdinfo *bd);
|
static int bd_int13probe(struct bdinfo *bd);
|
||||||
|
|
||||||
static int bd_init(void);
|
static int bd_init(void);
|
||||||
static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
|
static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
|
||||||
char *buf, size_t *rsize);
|
size_t size, char *buf, size_t *rsize);
|
||||||
static int bd_realstrategy(void *devdata, int flag, daddr_t dblk,
|
static int bd_realstrategy(void *devdata, int flag, daddr_t dblk, size_t offset,
|
||||||
size_t size, char *buf, size_t *rsize);
|
size_t size, char *buf, size_t *rsize);
|
||||||
static int bd_open(struct open_file *f, ...);
|
static int bd_open(struct open_file *f, ...);
|
||||||
static int bd_close(struct open_file *f);
|
static int bd_close(struct open_file *f);
|
||||||
@ -209,6 +211,8 @@ bd_init(void)
|
|||||||
(nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES)))
|
(nfd >= *(unsigned char *)PTOV(BIOS_NUMDRIVES)))
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
bdinfo[nbdinfo].bd_open = 0;
|
||||||
|
bdinfo[nbdinfo].bd_bcache = NULL;
|
||||||
bdinfo[nbdinfo].bd_unit = unit;
|
bdinfo[nbdinfo].bd_unit = unit;
|
||||||
bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0;
|
bdinfo[nbdinfo].bd_flags = unit < 0x80 ? BD_FLOPPY: 0;
|
||||||
if (!bd_int13probe(&bdinfo[nbdinfo]))
|
if (!bd_int13probe(&bdinfo[nbdinfo]))
|
||||||
@ -222,6 +226,7 @@ bd_init(void)
|
|||||||
nfd++;
|
nfd++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bcache_add_dev(nbdinfo);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +357,9 @@ bd_open(struct open_file *f, ...)
|
|||||||
|
|
||||||
if (dev->d_unit < 0 || dev->d_unit >= nbdinfo)
|
if (dev->d_unit < 0 || dev->d_unit >= nbdinfo)
|
||||||
return (EIO);
|
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,
|
err = disk_open(dev, BD(dev).bd_sectors * BD(dev).bd_sectorsize,
|
||||||
BD(dev).bd_sectorsize, (BD(dev).bd_flags & BD_FLOPPY) ?
|
BD(dev).bd_sectorsize, (BD(dev).bd_flags & BD_FLOPPY) ?
|
||||||
DISK_F_NOCACHE: 0);
|
DISK_F_NOCACHE: 0);
|
||||||
@ -438,6 +445,11 @@ bd_close(struct open_file *f)
|
|||||||
struct disk_devdesc *dev;
|
struct disk_devdesc *dev;
|
||||||
|
|
||||||
dev = (struct disk_devdesc *)f->f_devdata;
|
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));
|
return (disk_close(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,8 +473,8 @@ bd_ioctl(struct open_file *f, u_long cmd, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
|
bd_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
|
||||||
size_t *rsize)
|
char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct bcache_devdata bcd;
|
struct bcache_devdata bcd;
|
||||||
struct disk_devdesc *dev;
|
struct disk_devdesc *dev;
|
||||||
@ -470,13 +482,14 @@ bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
|
|||||||
dev = (struct disk_devdesc *)devdata;
|
dev = (struct disk_devdesc *)devdata;
|
||||||
bcd.dv_strategy = bd_realstrategy;
|
bcd.dv_strategy = bd_realstrategy;
|
||||||
bcd.dv_devdata = devdata;
|
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));
|
size, buf, rsize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
|
bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
|
||||||
size_t *rsize)
|
char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
|
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
|
||||||
int blks;
|
int blks;
|
||||||
|
@ -56,7 +56,7 @@ static uint8_t b_bios_probed;
|
|||||||
/*
|
/*
|
||||||
* The minimum amount of memory to reserve in bios_extmem for the heap.
|
* 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
|
* Products in this list need quirks to detect
|
||||||
|
@ -72,7 +72,7 @@ static void bangpxe_call(int func);
|
|||||||
|
|
||||||
static int pxe_init(void);
|
static int pxe_init(void);
|
||||||
static int pxe_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int pxe_close(struct open_file *f);
|
static int pxe_close(struct open_file *f);
|
||||||
static void pxe_print(int verbose);
|
static void pxe_print(int verbose);
|
||||||
@ -247,7 +247,7 @@ pxe_init(void)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
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)
|
char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
return (EIO);
|
return (EIO);
|
||||||
|
@ -141,9 +141,9 @@ main(void)
|
|||||||
cons_probe();
|
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.
|
* Special handling for PXE and CD booting.
|
||||||
|
@ -45,8 +45,8 @@ static int beri_cfi_disk_init(void);
|
|||||||
static int beri_cfi_disk_open(struct open_file *, ...);
|
static int beri_cfi_disk_open(struct open_file *, ...);
|
||||||
static int beri_cfi_disk_close(struct open_file *);
|
static int beri_cfi_disk_close(struct open_file *);
|
||||||
static void beri_cfi_disk_cleanup(void);
|
static void beri_cfi_disk_cleanup(void);
|
||||||
static int beri_cfi_disk_strategy(void *, int, daddr_t, size_t, char *,
|
static int beri_cfi_disk_strategy(void *, int, daddr_t, size_t, size_t,
|
||||||
size_t *);
|
char *, size_t *);
|
||||||
static void beri_cfi_disk_print(int);
|
static void beri_cfi_disk_print(int);
|
||||||
|
|
||||||
struct devsw beri_cfi_disk = {
|
struct devsw beri_cfi_disk = {
|
||||||
@ -69,8 +69,8 @@ beri_cfi_disk_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
beri_cfi_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
|
beri_cfi_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
|
||||||
char *buf, size_t *rsizep)
|
size_t size, char *buf, size_t *rsizep)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ static int beri_sdcard_disk_init(void);
|
|||||||
static int beri_sdcard_disk_open(struct open_file *, ...);
|
static int beri_sdcard_disk_open(struct open_file *, ...);
|
||||||
static int beri_sdcard_disk_close(struct open_file *);
|
static int beri_sdcard_disk_close(struct open_file *);
|
||||||
static void beri_sdcard_disk_cleanup(void);
|
static void beri_sdcard_disk_cleanup(void);
|
||||||
static int beri_sdcard_disk_strategy(void *, int, daddr_t, size_t, char *,
|
static int beri_sdcard_disk_strategy(void *, int, daddr_t, size_t, size_t,
|
||||||
size_t *);
|
char *, size_t *);
|
||||||
static void beri_sdcard_disk_print(int);
|
static void beri_sdcard_disk_print(int);
|
||||||
|
|
||||||
struct devsw beri_sdcard_disk = {
|
struct devsw beri_sdcard_disk = {
|
||||||
@ -69,8 +69,8 @@ beri_sdcard_disk_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
beri_sdcard_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
|
beri_sdcard_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
|
||||||
char *buf, size_t *rsizep)
|
size_t size, char *buf, size_t *rsizep)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
static int ofwd_init(void);
|
static int ofwd_init(void);
|
||||||
static int ofwd_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int ofwd_close(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);
|
static int ofwd_ioctl(struct open_file *f, u_long cmd, void *data);
|
||||||
@ -83,8 +83,8 @@ ofwd_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t size,
|
ofwd_strategy(void *devdata, int flag __unused, daddr_t dblk, size_t offset,
|
||||||
char *buf, size_t *rsize)
|
size_t size, char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata;
|
struct ofw_devdesc *dp = (struct ofw_devdesc *)devdata;
|
||||||
daddr_t pos;
|
daddr_t pos;
|
||||||
|
@ -84,13 +84,19 @@ struct specification_packet {
|
|||||||
static struct bcinfo {
|
static struct bcinfo {
|
||||||
int bc_unit; /* BIOS unit number */
|
int bc_unit; /* BIOS unit number */
|
||||||
struct specification_packet bc_sp;
|
struct specification_packet bc_sp;
|
||||||
|
int bc_open; /* reference counter */
|
||||||
|
void *bc_bcache; /* buffer cache data */
|
||||||
} bcinfo [MAXBCDEV];
|
} bcinfo [MAXBCDEV];
|
||||||
static int nbcinfo = 0;
|
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_read(int unit, daddr_t dblk, int blks, caddr_t dest);
|
||||||
static int bc_init(void);
|
static int bc_init(void);
|
||||||
static int bc_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int bc_close(struct open_file *f);
|
static int bc_close(struct open_file *f);
|
||||||
static void bc_print(int verbose);
|
static void bc_print(int verbose);
|
||||||
@ -160,6 +166,7 @@ bc_add(int biosdev)
|
|||||||
|
|
||||||
printf("BIOS CD is cd%d\n", nbcinfo);
|
printf("BIOS CD is cd%d\n", nbcinfo);
|
||||||
nbcinfo++;
|
nbcinfo++;
|
||||||
|
bcache_add_dev(nbcinfo); /* register cd device in bcache */
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,19 +203,44 @@ bc_open(struct open_file *f, ...)
|
|||||||
return(ENXIO);
|
return(ENXIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BC(dev).bc_open++;
|
||||||
|
if (BC(dev).bc_bcache == NULL)
|
||||||
|
BC(dev).bc_bcache = bcache_allocate();
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bc_close(struct open_file *f)
|
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);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
|
bc_strategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
|
||||||
size_t *rsize)
|
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_realstrategy(void *devdata, int rw, daddr_t dblk, size_t offset, size_t size,
|
||||||
|
char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct i386_devdesc *dev;
|
struct i386_devdesc *dev;
|
||||||
int unit;
|
int unit;
|
||||||
|
@ -96,9 +96,13 @@ static struct bdinfo
|
|||||||
int bd_flags;
|
int bd_flags;
|
||||||
int bd_type; /* BIOS 'drive type' (floppy only) */
|
int bd_type; /* BIOS 'drive type' (floppy only) */
|
||||||
int bd_da_unit; /* kernel unit number for da */
|
int bd_da_unit; /* kernel unit number for da */
|
||||||
|
int bd_open; /* reference counter */
|
||||||
|
void *bd_bcache; /* buffer cache data */
|
||||||
} bdinfo [MAXBDDEV];
|
} bdinfo [MAXBDDEV];
|
||||||
static int nbdinfo = 0;
|
static int nbdinfo = 0;
|
||||||
|
|
||||||
|
#define BD(dev) (bdinfo[(dev)->d_unit])
|
||||||
|
|
||||||
static int bd_getgeom(struct open_disk *od);
|
static int bd_getgeom(struct open_disk *od);
|
||||||
static int bd_read(struct open_disk *od, daddr_t dblk, int blks,
|
static int bd_read(struct open_disk *od, daddr_t dblk, int blks,
|
||||||
caddr_t dest);
|
caddr_t dest);
|
||||||
@ -176,6 +180,8 @@ bd_init(void)
|
|||||||
/* sequence 0x90, 0x80, 0xa0 */
|
/* sequence 0x90, 0x80, 0xa0 */
|
||||||
for (base = 0x90; base <= 0xa0; base += n, n += 0x30) {
|
for (base = 0x90; base <= 0xa0; base += n, n += 0x30) {
|
||||||
for (unit = base; (nbdinfo < MAXBDDEV) || ((unit & 0x0f) < 4); unit++) {
|
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_unit = unit;
|
||||||
bdinfo[nbdinfo].bd_flags = (unit & 0xf0) == 0x90 ? BD_FLOPPY : 0;
|
bdinfo[nbdinfo].bd_flags = (unit & 0xf0) == 0x90 ? BD_FLOPPY : 0;
|
||||||
|
|
||||||
@ -205,6 +211,7 @@ bd_init(void)
|
|||||||
nbdinfo++;
|
nbdinfo++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bcache_add_dev(nbdinfo);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,6 +434,10 @@ bd_open(struct open_file *f, ...)
|
|||||||
if ((error = bd_opendisk(&od, dev)))
|
if ((error = bd_opendisk(&od, dev)))
|
||||||
return(error);
|
return(error);
|
||||||
|
|
||||||
|
BD(dev).bd_open++;
|
||||||
|
if (BD(dev).bd_bcache == NULL)
|
||||||
|
BD(dev).bd_bcache = bcache_allocate();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Save our context
|
* Save our context
|
||||||
*/
|
*/
|
||||||
@ -696,7 +707,14 @@ bd_bestslice(struct open_disk *od)
|
|||||||
static int
|
static int
|
||||||
bd_close(struct open_file *f)
|
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);
|
bd_closedisk(od);
|
||||||
return(0);
|
return(0);
|
||||||
@ -715,18 +733,23 @@ bd_closedisk(struct open_disk *od)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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 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_strategy = bd_realstrategy;
|
||||||
bcd.dv_devdata = devdata;
|
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
|
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);
|
struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data);
|
||||||
int blks;
|
int blks;
|
||||||
|
@ -40,7 +40,7 @@ uint32_t bios_basemem, bios_extmem, high_heap_size;
|
|||||||
/*
|
/*
|
||||||
* The minimum amount of memory to reserve in bios_extmem for the heap.
|
* 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
|
void
|
||||||
bios_getmem(void)
|
bios_getmem(void)
|
||||||
|
@ -147,9 +147,9 @@ main(void)
|
|||||||
cons_probe();
|
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.
|
* Special handling for PXE and CD booting.
|
||||||
|
@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
static int hostdisk_init(void);
|
static int hostdisk_init(void);
|
||||||
static int hostdisk_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int hostdisk_close(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);
|
static int hostdisk_ioctl(struct open_file *f, u_long cmd, void *data);
|
||||||
@ -58,8 +58,8 @@ hostdisk_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
hostdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
|
hostdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
|
||||||
char *buf, size_t *rsize)
|
size_t size, char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct devdesc *desc = devdata;
|
struct devdesc *desc = devdata;
|
||||||
daddr_t pos;
|
daddr_t pos;
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
static int ps3cdrom_init(void);
|
static int ps3cdrom_init(void);
|
||||||
static int ps3cdrom_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int ps3cdrom_close(struct open_file *f);
|
static int ps3cdrom_close(struct open_file *f);
|
||||||
static void ps3cdrom_print(int verbose);
|
static void ps3cdrom_print(int verbose);
|
||||||
@ -76,7 +76,7 @@ static int ps3cdrom_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ps3cdrom_strategy(void *devdata, int flag, daddr_t dblk,
|
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;
|
struct ps3_devdesc *dev = (struct ps3_devdesc *) devdata;
|
||||||
int err;
|
int err;
|
||||||
|
@ -58,7 +58,7 @@ static void ps3disk_uuid_letoh(uuid_t *uuid);
|
|||||||
|
|
||||||
static int ps3disk_init(void);
|
static int ps3disk_init(void);
|
||||||
static int ps3disk_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int ps3disk_close(struct open_file *f);
|
static int ps3disk_close(struct open_file *f);
|
||||||
static void ps3disk_print(int verbose);
|
static void ps3disk_print(int verbose);
|
||||||
@ -109,7 +109,7 @@ static int ps3disk_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int ps3disk_strategy(void *devdata, int flag, daddr_t dblk,
|
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 ps3_devdesc *dev = (struct ps3_devdesc *) devdata;
|
||||||
struct open_dev *od = (struct open_dev *) dev->d_disk.data;
|
struct open_dev *od = (struct open_dev *) dev->d_disk.data;
|
||||||
|
@ -73,7 +73,8 @@ static int stor_readdev(struct disk_devdesc *, daddr_t, size_t, char *);
|
|||||||
|
|
||||||
/* devsw I/F */
|
/* devsw I/F */
|
||||||
static int stor_init(void);
|
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_open(struct open_file *, ...);
|
||||||
static int stor_close(struct open_file *);
|
static int stor_close(struct open_file *);
|
||||||
static int stor_ioctl(struct open_file *f, u_long cmd, void *data);
|
static int stor_ioctl(struct open_file *f, u_long cmd, void *data);
|
||||||
@ -143,8 +144,8 @@ stor_cleanup(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
stor_strategy(void *devdata, int rw, daddr_t blk, size_t size, char *buf,
|
stor_strategy(void *devdata, int rw, daddr_t blk, size_t offset, size_t size,
|
||||||
size_t *rsize)
|
char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
|
struct disk_devdesc *dev = (struct disk_devdesc *)devdata;
|
||||||
daddr_t bcount;
|
daddr_t bcount;
|
||||||
|
@ -48,7 +48,8 @@ static int umass_disk_open(struct open_file *,...);
|
|||||||
static int umass_disk_close(struct open_file *);
|
static int umass_disk_close(struct open_file *);
|
||||||
static void umass_disk_cleanup(void);
|
static void umass_disk_cleanup(void);
|
||||||
static int umass_disk_ioctl(struct open_file *, u_long, 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);
|
static void umass_disk_print(int);
|
||||||
|
|
||||||
struct devsw umass_disk = {
|
struct devsw umass_disk = {
|
||||||
@ -84,8 +85,8 @@ umass_disk_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
umass_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
|
umass_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t offset,
|
||||||
char *buf, size_t *rsizep)
|
size_t size, char *buf, size_t *rsizep)
|
||||||
{
|
{
|
||||||
if (umass_uaa.device == NULL)
|
if (umass_uaa.device == NULL)
|
||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
|
@ -167,8 +167,8 @@ host_dev_close(struct open_file *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
host_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
|
host_dev_strategy(void *devdata, int rw, daddr_t dblk, size_t offset,
|
||||||
char *buf, size_t *rsize)
|
size_t size, char *buf, size_t *rsize)
|
||||||
{
|
{
|
||||||
|
|
||||||
return (ENOSYS);
|
return (ENOSYS);
|
||||||
|
@ -130,6 +130,10 @@ loader_main(struct loader_callbacks *cb, void *arg, int version, int ndisks)
|
|||||||
archsw.arch_zfs_probe = userboot_zfs_probe;
|
archsw.arch_zfs_probe = userboot_zfs_probe;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialise the block cache. Set the upper limit.
|
||||||
|
*/
|
||||||
|
bcache_init(32768, 512);
|
||||||
/*
|
/*
|
||||||
* March through the device switch probing for things.
|
* March through the device switch probing for things.
|
||||||
*/
|
*/
|
||||||
|
@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$");
|
|||||||
struct userdisk_info {
|
struct userdisk_info {
|
||||||
uint64_t mediasize;
|
uint64_t mediasize;
|
||||||
uint16_t sectorsize;
|
uint16_t sectorsize;
|
||||||
|
int ud_open; /* reference counter */
|
||||||
|
void *ud_bcache; /* buffer cache data */
|
||||||
};
|
};
|
||||||
|
|
||||||
int userboot_disk_maxunit = 0;
|
int userboot_disk_maxunit = 0;
|
||||||
@ -52,7 +54,9 @@ static struct userdisk_info *ud_info;
|
|||||||
static int userdisk_init(void);
|
static int userdisk_init(void);
|
||||||
static void userdisk_cleanup(void);
|
static void userdisk_cleanup(void);
|
||||||
static int userdisk_strategy(void *devdata, int flag, daddr_t dblk,
|
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_open(struct open_file *f, ...);
|
||||||
static int userdisk_close(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);
|
static int userdisk_ioctl(struct open_file *f, u_long cmd, void *data);
|
||||||
@ -92,9 +96,11 @@ userdisk_init(void)
|
|||||||
return (ENXIO);
|
return (ENXIO);
|
||||||
ud_info[i].mediasize = mediasize;
|
ud_info[i].mediasize = mediasize;
|
||||||
ud_info[i].sectorsize = sectorsize;
|
ud_info[i].sectorsize = sectorsize;
|
||||||
|
ud_info[i].ud_open = 0;
|
||||||
|
ud_info[i].ud_bcache = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bcache_add_dev(userdisk_maxunit);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,7 +154,9 @@ userdisk_open(struct open_file *f, ...)
|
|||||||
|
|
||||||
if (dev->d_unit < 0 || dev->d_unit >= userdisk_maxunit)
|
if (dev->d_unit < 0 || dev->d_unit >= userdisk_maxunit)
|
||||||
return (EIO);
|
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,
|
return (disk_open(dev, ud_info[dev->d_unit].mediasize,
|
||||||
ud_info[dev->d_unit].sectorsize, 0));
|
ud_info[dev->d_unit].sectorsize, 0));
|
||||||
}
|
}
|
||||||
@ -159,12 +167,32 @@ userdisk_close(struct open_file *f)
|
|||||||
struct disk_devdesc *dev;
|
struct disk_devdesc *dev;
|
||||||
|
|
||||||
dev = (struct disk_devdesc *)f->f_devdata;
|
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));
|
return (disk_close(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
|
userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t offset,
|
||||||
char *buf, size_t *rsize)
|
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;
|
struct disk_devdesc *dev = devdata;
|
||||||
uint64_t off;
|
uint64_t off;
|
||||||
@ -177,7 +205,7 @@ userdisk_strategy(void *devdata, int rw, daddr_t dblk, size_t size,
|
|||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
if (rsize)
|
if (rsize)
|
||||||
*rsize = 0;
|
*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);
|
rc = CALLBACK(diskread, dev->d_unit, off, buf, size, &resid);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (rc);
|
return (rc);
|
||||||
|
@ -578,7 +578,7 @@ zfs_dev_close(struct open_file *f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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);
|
return (ENOSYS);
|
||||||
|
Loading…
Reference in New Issue
Block a user