Changeset View
Changeset View
Standalone View
Standalone View
head/stand/libsa/zfs/zfs.c
Show First 20 Lines • Show All 357 Lines • ▼ Show 20 Lines | fzap_next: | ||||
return (0); | return (0); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t bytes) | vdev_read(vdev_t *vdev, void *priv, off_t offset, void *buf, size_t bytes) | ||||
{ | { | ||||
int fd, ret; | int fd, ret; | ||||
size_t res, size, remainder, rb_size, blksz; | size_t res, head, tail, total_size, full_sec_size; | ||||
unsigned secsz; | unsigned secsz, do_tail_read; | ||||
off_t off; | off_t start_sec; | ||||
char *bouncebuf, *rb_buf; | char *outbuf, *bouncebuf; | ||||
fd = (uintptr_t) priv; | fd = (uintptr_t) priv; | ||||
outbuf = (char *) buf; | |||||
bouncebuf = NULL; | bouncebuf = NULL; | ||||
ret = ioctl(fd, DIOCGSECTORSIZE, &secsz); | ret = ioctl(fd, DIOCGSECTORSIZE, &secsz); | ||||
if (ret != 0) | if (ret != 0) | ||||
return (ret); | return (ret); | ||||
off = offset / secsz; | /* | ||||
remainder = offset % secsz; | * Handling reads of arbitrary offset and size - multi-sector case | ||||
if (lseek(fd, off * secsz, SEEK_SET) == -1) | * and single-sector case. | ||||
return (errno); | * | ||||
* Multi-sector Case | |||||
* (do_tail_read = true if tail > 0) | |||||
* | |||||
* |<----------------------total_size--------------------->| | |||||
* | | | |||||
* |<--head-->|<--------------bytes------------>|<--tail-->| | |||||
* | | | | | |||||
* | | |<~full_sec_size~>| | | | |||||
* +------------------+ +------------------+ | |||||
* | |0101010| . . . |0101011| | | |||||
* +------------------+ +------------------+ | |||||
* start_sec start_sec + n | |||||
* | |||||
* | |||||
* Single-sector Case | |||||
* (do_tail_read = false) | |||||
* | |||||
* |<------total_size = secsz----->| | |||||
* | | | |||||
* |<-head->|<---bytes--->|<-tail->| | |||||
* +-------------------------------+ | |||||
* | |0101010101010| | | |||||
* +-------------------------------+ | |||||
* start_sec | |||||
*/ | |||||
start_sec = offset / secsz; | |||||
head = offset % secsz; | |||||
total_size = roundup2(head + bytes, secsz); | |||||
tail = total_size - (head + bytes); | |||||
do_tail_read = ((tail > 0) && (head + bytes > secsz)); | |||||
full_sec_size = total_size; | |||||
if (head > 0) | |||||
full_sec_size -= secsz; | |||||
if (do_tail_read) | |||||
full_sec_size -= secsz; | |||||
rb_buf = buf; | /* Return of partial sector data requires a bounce buffer. */ | ||||
rb_size = bytes; | if ((head > 0) || do_tail_read) { | ||||
size = roundup2(bytes + remainder, secsz); | |||||
blksz = size; | |||||
if (remainder != 0 || size != bytes) { | |||||
bouncebuf = zfs_alloc(secsz); | bouncebuf = zfs_alloc(secsz); | ||||
if (bouncebuf == NULL) { | if (bouncebuf == NULL) { | ||||
printf("vdev_read: out of memory\n"); | printf("vdev_read: out of memory\n"); | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
rb_buf = bouncebuf; | |||||
blksz = rb_size - remainder; | |||||
} | } | ||||
while (bytes > 0) { | if (lseek(fd, start_sec * secsz, SEEK_SET) == -1) | ||||
res = read(fd, rb_buf, rb_size); | return (errno); | ||||
if (res != rb_size) { | |||||
/* Partial data return from first sector */ | |||||
if (head > 0) { | |||||
res = read(fd, bouncebuf, secsz); | |||||
if (res != secsz) { | |||||
ret = EIO; | ret = EIO; | ||||
goto error; | goto error; | ||||
} | } | ||||
if (bytes < blksz) | memcpy(outbuf, bouncebuf + head, secsz - head); | ||||
blksz = bytes; | outbuf += secsz - head; | ||||
if (bouncebuf != NULL) | } | ||||
memcpy(buf, rb_buf + remainder, blksz); | |||||
buf = (void *)((uintptr_t)buf + blksz); | /* Full data return from read sectors */ | ||||
bytes -= blksz; | if (full_sec_size > 0) { | ||||
remainder = 0; | res = read(fd, outbuf, full_sec_size); | ||||
blksz = rb_size; | if (res != full_sec_size) { | ||||
ret = EIO; | |||||
goto error; | |||||
} | |||||
outbuf += full_sec_size; | |||||
} | |||||
/* Partial data return from last sector */ | |||||
if (do_tail_read) { | |||||
res = read(fd, bouncebuf, secsz); | |||||
if (res != secsz) { | |||||
ret = EIO; | |||||
goto error; | |||||
} | |||||
memcpy(outbuf, bouncebuf, secsz - tail); | |||||
} | } | ||||
ret = 0; | ret = 0; | ||||
error: | error: | ||||
if (bouncebuf != NULL) | if (bouncebuf != NULL) | ||||
zfs_free(bouncebuf, secsz); | zfs_free(bouncebuf, secsz); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 599 Lines • Show Last 20 Lines |