summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2018-11-16 13:09:29 -0600
committerDavid Teigland <teigland@redhat.com>2018-11-20 09:04:37 -0600
commitcb5405ded86209979eef54433d0b90942b2f976a (patch)
tree239ddbecd16336468681acd8c90c448116e504cd
parentf8ce9bf3bc38df8f89021517d7967d94ace129df (diff)
downloadlvm2-cb5405ded86209979eef54433d0b90942b2f976a.tar.gz
bcache: sync io fixes
fix lseek error check fix read/write error checks handle zero return from read and write don't return an error for short io fix partial read/write loop
-rw-r--r--lib/device/bcache.c69
1 files changed, 47 insertions, 22 deletions
diff --git a/lib/device/bcache.c b/lib/device/bcache.c
index 571ee7a2b..7384a3290 100644
--- a/lib/device/bcache.c
+++ b/lib/device/bcache.c
@@ -328,7 +328,7 @@ struct io_engine *create_async_io_engine(void)
e->aio_context = 0;
r = io_setup(MAX_IO, &e->aio_context);
if (r < 0) {
- log_warn("io_setup failed");
+ log_debug("io_setup failed %d", r);
dm_free(e);
return NULL;
}
@@ -371,8 +371,11 @@ static void _sync_destroy(struct io_engine *ioe)
static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
sector_t sb, sector_t se, void *data, void *context)
{
- int r;
- uint64_t len = (se - sb) * 512, where;
+ int rv;
+ off_t off;
+ uint64_t where;
+ uint64_t pos = 0;
+ uint64_t len = (se - sb) * 512;
struct sync_engine *e = _to_sync(ioe);
struct sync_io *io = malloc(sizeof(*io));
if (!io) {
@@ -381,11 +384,17 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
}
where = sb * 512;
- r = lseek(fd, where, SEEK_SET);
- if (r < 0) {
- log_warn("unable to seek to position %llu", (unsigned long long) where);
- free(io);
- return false;
+
+ off = lseek(fd, where, SEEK_SET);
+ if (off == (off_t) -1) {
+ log_warn("Device seek error %d for offset %llu", errno, (unsigned long long)where);
+ free(io);
+ return false;
+ }
+ if (off != (off_t) where) {
+ log_warn("Device seek failed for offset %llu", (unsigned long long)where);
+ free(io);
+ return false;
}
/*
@@ -430,28 +439,44 @@ static bool _sync_issue(struct io_engine *ioe, enum dir d, int fd,
len = nbytes;
}
- while (len) {
- do {
- if (d == DIR_READ)
- r = read(fd, data, len);
- else
- r = write(fd, data, len);
+ while (pos < len) {
+ if (d == DIR_READ)
+ rv = read(fd, (char *)data + pos, len - pos);
+ else
+ rv = write(fd, (char *)data + pos, len - pos);
- } while ((r < 0) && ((r == EINTR) || (r == EAGAIN)));
+ if (rv == -1 && errno == EINTR)
+ continue;
+ if (rv == -1 && errno == EAGAIN)
+ continue;
+
+ if (!rv)
+ break;
- if (r < 0) {
- log_warn("io failed %d", r);
+ if (rv < 0) {
+ if (d == DIR_READ)
+ log_debug("Device read error %d offset %llu len %llu", errno,
+ (unsigned long long)(where + pos),
+ (unsigned long long)(len - pos));
+ else
+ log_debug("Device write error %d offset %llu len %llu", errno,
+ (unsigned long long)(where + pos),
+ (unsigned long long)(len - pos));
free(io);
return false;
- }
-
- len -= r;
+ }
+ pos += rv;
}
- if (len) {
- log_warn("short io %u bytes remaining", (unsigned) len);
+ if (pos < len) {
+ if (d == DIR_READ)
+ log_warn("Device read short %u bytes remaining", (unsigned)(len - pos));
+ else
+ log_warn("Device write short %u bytes remaining", (unsigned)(len - pos));
+ /*
free(io);
return false;
+ */
}