Skip to content

Commit

Permalink
Merge pull request openzfs#302 from zettabot/illumos-sync
Browse files Browse the repository at this point in the history
Merge remote-tracking branch 'illumos/master' into illumos-sync
  • Loading branch information
Prakash Surya authored Feb 16, 2017
2 parents f9d9478 + 87da50e commit 3dce1fe
Show file tree
Hide file tree
Showing 27 changed files with 1,812 additions and 786 deletions.
57 changes: 48 additions & 9 deletions usr/src/boot/sys/boot/common/bcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@

#include <sys/cdefs.h>
#include <sys/param.h>
__FBSDID("$FreeBSD$");

/*
* Simple hashed block cache
Expand Down Expand Up @@ -64,7 +63,7 @@ struct bcachectl
struct bcache {
struct bcachectl *bcache_ctl;
caddr_t bcache_data;
u_int bcache_nblks;
size_t bcache_nblks;
size_t ra;
};

Expand All @@ -86,6 +85,7 @@ static u_int bcache_rablks;
((bc)->bcache_ctl[BHASH((bc), (blkno))].bc_blkno != (blkno))
#define BCACHE_READAHEAD 256
#define BCACHE_MINREADAHEAD 32
#define BCACHE_MARKER 0xdeadbeef

static void bcache_invalidate(struct bcache *bc, daddr_t blkno);
static void bcache_insert(struct bcache *bc, daddr_t blkno);
Expand All @@ -95,7 +95,7 @@ static void bcache_free_instance(struct bcache *bc);
* Initialise the cache for (nblks) of (bsize).
*/
void
bcache_init(u_int nblks, size_t bsize)
bcache_init(size_t nblks, size_t bsize)
{
/* set up control data */
bcache_total_nblks = nblks;
Expand All @@ -122,6 +122,7 @@ bcache_allocate(void)
u_int i;
struct bcache *bc = malloc(sizeof (struct bcache));
int disks = bcache_numdev;
uint32_t *marker;

if (disks == 0)
disks = 1; /* safe guard */
Expand All @@ -140,20 +141,25 @@ bcache_allocate(void)

bc->bcache_nblks = bcache_total_nblks >> i;
bcache_unit_nblks = bc->bcache_nblks;
bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize);
bc->bcache_data = malloc(bc->bcache_nblks * bcache_blksize +
sizeof (uint32_t));
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_data = malloc(bc->bcache_nblks * bcache_blksize +
sizeof (uint32_t));
}

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);
return (NULL);
}
/* Insert cache end marker. */
marker = (uint32_t *)(bc->bcache_data + bc->bcache_nblks * bcache_blksize);
*marker = BCACHE_MARKER;

/* Flush the cache */
for (i = 0; i < bc->bcache_nblks; i++) {
Expand Down Expand Up @@ -215,11 +221,13 @@ read_strategy(void *devdata, int rw, daddr_t blk, size_t size,
int result;
daddr_t p_blk;
caddr_t p_buf;
uint32_t *marker;

if (bc == NULL) {
errno = ENODEV;
return (-1);
}
marker = (uint32_t *)(bc->bcache_data + bc->bcache_nblks * bcache_blksize);

if (rsize != NULL)
*rsize = 0;
Expand Down Expand Up @@ -261,9 +269,34 @@ read_strategy(void *devdata, int rw, daddr_t blk, size_t size,

p_size = MIN(r_size, nblk - i); /* read at least those blocks */

/*
* The read ahead size setup.
* While the read ahead can save us IO, it also can complicate things:
* 1. We do not want to read ahead by wrapping around the
* bcache end - this would complicate the cache management.
* 2. We are using bc->ra as dynamic hint for read ahead size,
* detected cache hits will increase the read-ahead block count, and
* misses will decrease, see the code above.
* 3. The bcache is sized by 512B blocks, however, the underlying device
* may have a larger sector size, and we should perform the IO by
* taking into account these larger sector sizes. We could solve this by
* passing the sector size to bcache_allocate(), or by using ioctl(), but
* in this version we are using the constant, 16 blocks, and are rounding
* read ahead block count down to multiple of 16.
* Using the constant has two reasons, we are not entirely sure if the
* BIOS disk interface is providing the correct value for sector size.
* And secondly, this way we get the most conservative setup for the ra.
*
* The selection of multiple of 16 blocks (8KB) is quite arbitrary, however,
* we want to cover CDs (2K) and 4K disks.
* bcache_allocate() will always fall back to a minimum of 32 blocks.
* Our choice of 16 read ahead blocks will always fit inside the bcache.
*/

ra = bc->bcache_nblks - BHASH(bc, p_blk + p_size);
if (ra != bc->bcache_nblks) { /* do we have RA space? */
ra = MIN(bc->ra, ra);
if (ra != 0 && ra != bc->bcache_nblks) { /* do we have RA space? */
ra = MIN(bc->ra, ra - 1);
ra = rounddown(ra, 16); /* multiple of 16 blocks */
p_size += ra;
}

Expand Down Expand Up @@ -310,6 +343,12 @@ read_strategy(void *devdata, int rw, daddr_t blk, size_t size,
result = 0;
}

if (*marker != BCACHE_MARKER) {
printf("BUG: bcache corruption detected: nblks: %zu p_blk: %lu, "
"p_size: %zu, ra: %zu\n", bc->bcache_nblks,
(long unsigned)BHASH(bc, p_blk), p_size, ra);
}

done:
if ((result == 0) && (rsize != NULL))
*rsize = size;
Expand Down Expand Up @@ -338,7 +377,7 @@ bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size,
/* bypass large requests, or when the cache is inactive */
if (bc == NULL ||
((size * 2 / bcache_blksize) > bcache_nblks)) {
DEBUG("bypass %d from %d", size / bcache_blksize, blk);
DEBUG("bypass %zu from %qu", size / bcache_blksize, blk);
bcache_bypasses++;
return (dd->dv_strategy(dd->dv_devdata, rw, blk, size, buf, rsize));
}
Expand Down
2 changes: 1 addition & 1 deletion usr/src/boot/sys/boot/common/bootstrap.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ 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);

/* bcache.c */
void bcache_init(u_int nblks, size_t bsize);
void bcache_init(size_t nblks, size_t bsize);
void bcache_add_dev(int);
void *bcache_allocate(void);
void bcache_free(void *);
Expand Down
12 changes: 8 additions & 4 deletions usr/src/boot/sys/boot/i386/btx/lib/btxv86.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@
* purpose.
*/

/*
* $FreeBSD$
*/

#ifndef _BTXV86_H_
#define _BTXV86_H_

#include <sys/types.h>
#include <machine/psl.h>

/*
* Real memory buffer space for real mode IO.
* Just one page is not much, but the space is rather limited.
* See ../btx/btx.S for details.
*/
#define V86_IO_BUFFER 0x8000
#define V86_IO_BUFFER_SIZE 0x1000

#define V86_ADDR 0x10000 /* Segment:offset address */
#define V86_CALLF 0x20000 /* Emulate far call */
#define V86_FLAGS 0x40000 /* Return flags */
Expand Down
15 changes: 7 additions & 8 deletions usr/src/boot/sys/boot/i386/libi386/bioscd.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,11 @@
*/

#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");

/*
* BIOS CD device handling for CD's that have been booted off of via no
* emulation booting as defined in the El Torito standard.
*
*
* Ideas and algorithms from:
*
* - FreeBSD libi386/biosdisk.c
Expand Down Expand Up @@ -310,9 +309,6 @@ bc_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
return (0);
}

/* Max number of sectors to bounce-buffer at a time. */
#define CD_BOUNCEBUF 8

/* return negative value for an error, otherwise blocks read */
static int
bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
Expand All @@ -335,13 +331,16 @@ bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)

/* Decide whether we have to bounce */
if (VTOP(dest) >> 20 != 0) {
/*
/*
* The destination buffer is above first 1MB of
* physical memory so we have to arrange a suitable
* bounce buffer.
*/
x = min(CD_BOUNCEBUF, (unsigned)blks);
bbuf = alloca(x * BIOSCD_SECSIZE);
x = V86_IO_BUFFER_SIZE / BIOSCD_SECSIZE;
if (x == 0)
panic("BUG: Real mode buffer is too small\n");
x = min(x, (unsigned)blks);
bbuf = PTOV(V86_IO_BUFFER);
maxfer = x;
} else {
bbuf = NULL;
Expand Down
Loading

0 comments on commit 3dce1fe

Please sign in to comment.