mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-31 16:57:10 +00:00
zfs.c:vdev_read() needs to be careful about large sectors
Using the same implementation as done in efi/boot1. We must handle smaller than sector size IO etc. Differential Revision: https://reviews.freebsd.org/D12850
This commit is contained in:
parent
73e23ad462
commit
955f7bd709
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=325310
@ -368,17 +368,61 @@ zfs_readdir(struct open_file *f, struct dirent *d)
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t size)
|
||||
vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t bytes)
|
||||
{
|
||||
int fd;
|
||||
int fd, ret;
|
||||
size_t res, size, remainder, rb_size, blksz;
|
||||
unsigned secsz;
|
||||
off_t off;
|
||||
char *bouncebuf, *rb_buf;
|
||||
|
||||
fd = (uintptr_t) priv;
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
if (read(fd, buf, size) == size) {
|
||||
return 0;
|
||||
} else {
|
||||
return (EIO);
|
||||
bouncebuf = NULL;
|
||||
|
||||
ret = ioctl(fd, DIOCGSECTORSIZE, &secsz);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
off = offset / secsz;
|
||||
remainder = offset % secsz;
|
||||
if (lseek(fd, off * secsz, SEEK_SET) == -1)
|
||||
return (errno);
|
||||
|
||||
rb_buf = buf;
|
||||
rb_size = bytes;
|
||||
size = roundup2(bytes + remainder, secsz);
|
||||
blksz = size;
|
||||
if (remainder != 0 || size != bytes) {
|
||||
bouncebuf = zfs_alloc(secsz);
|
||||
if (bouncebuf == NULL) {
|
||||
printf("vdev_read: out of memory\n");
|
||||
return (ENOMEM);
|
||||
}
|
||||
rb_buf = bouncebuf;
|
||||
blksz = rb_size - remainder;
|
||||
}
|
||||
|
||||
while (bytes > 0) {
|
||||
res = read(fd, rb_buf, rb_size);
|
||||
if (res != rb_size) {
|
||||
ret = EIO;
|
||||
goto error;
|
||||
}
|
||||
if (bytes < blksz)
|
||||
blksz = bytes;
|
||||
if (bouncebuf != NULL)
|
||||
memcpy(buf, rb_buf + remainder, blksz);
|
||||
buf = (void *)((uintptr_t)buf + blksz);
|
||||
bytes -= blksz;
|
||||
remainder = 0;
|
||||
blksz = rb_size;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
error:
|
||||
if (bouncebuf != NULL)
|
||||
zfs_free(bouncebuf, secsz);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
|
Loading…
Reference in New Issue
Block a user