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:
parent
6ee43aee80
commit
ffd08eb064
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user