loader: want mechanism to avoid RA with bcache

While we have mechanisms in place to protect ourselves against the read
behind the disk end, there is still one corner case. As the GPT
partition table has backup table at the end of the disk, and we yet
do not know the size of the disk (if the wrong size is provided by the
firmware/bios), we need to limit the reads to avoid read ahead in such case.

Note: this update does add constant into stand.h, so the incremental build
will need to get local stand.h updated first.

Reviewed by:	allanjude
Differential Revision:	https://reviews.freebsd.org/D10187
This commit is contained in:
Toomas Soome 2017-04-06 15:57:53 +00:00
parent 6ee43aee80
commit ffd08eb064
3 changed files with 18 additions and 4 deletions

View File

@ -194,6 +194,9 @@ extern struct open_file files[];
#define F_WRITE 0x0002 /* file opened for writing */
#define F_RAW 0x0004 /* raw device open - no file system */
#define F_NODEV 0x0008 /* network open - no device */
#define F_MASK 0xFFFF
/* Mode modifier for strategy() */
#define F_NORA (0x01 << 16) /* Disable Read-Ahead */
#define isascii(c) (((c) & ~0x7F) == 0)

View File

@ -295,7 +295,11 @@ read_strategy(void *devdata, int rw, daddr_t blk, size_t size,
* Our choice of 16 read ahead blocks will always fit inside the bcache.
*/
ra = bc->bcache_nblks - BHASH(bc, p_blk + p_size);
if ((rw & F_NORA) == F_NORA)
ra = 0;
else
ra = bc->bcache_nblks - BHASH(bc, p_blk + p_size);
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 */
@ -316,6 +320,7 @@ read_strategy(void *devdata, int rw, daddr_t blk, size_t size,
* in either case we should return the data in bcache and only
* return error if there is no data.
*/
rw &= F_MASK;
result = dd->dv_strategy(dd->dv_devdata, rw, p_blk,
p_size * bcache_blksize, p_buf, &r_size);
@ -381,10 +386,11 @@ bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size,
((size * 2 / bcache_blksize) > bcache_nblks)) {
DEBUG("bypass %zu from %qu", size / bcache_blksize, blk);
bcache_bypasses++;
rw &= F_MASK;
return (dd->dv_strategy(dd->dv_devdata, rw, blk, size, buf, rsize));
}
switch (rw) {
switch (rw & F_MASK) {
case F_READ:
nblk = size / bcache_blksize;
if (size != 0 && nblk == 0)
@ -423,7 +429,7 @@ bcache_strategy(void *devdata, int rw, daddr_t blk, size_t size,
return (ret);
case F_WRITE:
return write_strategy(devdata, rw, blk, size, buf, rsize);
return write_strategy(devdata, F_WRITE, blk, size, buf, rsize);
}
return -1;
}

View File

@ -87,7 +87,12 @@ ptblread(void *d, void *buf, size_t blocks, uint64_t offset)
dev = (struct disk_devdesc *)d;
od = (struct open_disk *)dev->d_opendata;
return (dev->d_dev->dv_strategy(dev, F_READ, offset,
/*
* As the GPT backup partition is located at the end of the disk,
* to avoid reading past disk end, flag bcache not to use RA.
*/
return (dev->d_dev->dv_strategy(dev, F_READ | F_NORA, offset,
blocks * od->sectorsize, (char *)buf, NULL));
}