From: Rusty Russell Date: Tue, 1 Mar 2011 12:49:20 +0000 (+1030) Subject: tdb2: remove looping for read on normal files. X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=6dbbfabca414018b4c5acb3e6e597d84e2b19caf;hp=1ac26f37368b33e0952e19df05184776c80159c8 tdb2: remove looping for read on normal files. Simply assume that any short read on a TDB in an I/O error. --- diff --git a/ccan/tdb2/io.c b/ccan/tdb2/io.c index 3a261a40..999922b1 100644 --- a/ccan/tdb2/io.c +++ b/ccan/tdb2/io.c @@ -225,44 +225,6 @@ bool tdb_pwrite_all(int fd, const void *buf, size_t len, tdb_off_t off) return true; } -/* Even on files, we can get partial reads due to signals. */ -bool tdb_pread_all(int fd, void *buf, size_t len, tdb_off_t off) -{ - while (len) { - ssize_t ret; - ret = pread(fd, buf, len, off); - if (ret < 0) - return false; - if (ret == 0) { - /* ETOOSHORT? */ - errno = EWOULDBLOCK; - return false; - } - buf = (char *)buf + ret; - off += ret; - len -= ret; - } - return true; -} - -bool tdb_read_all(int fd, void *buf, size_t len) -{ - while (len) { - ssize_t ret; - ret = read(fd, buf, len); - if (ret < 0) - return false; - if (ret == 0) { - /* ETOOSHORT? */ - errno = EWOULDBLOCK; - return false; - } - buf = (char *)buf + ret; - len -= ret; - } - return true; -} - /* write a lump of data at a specified offset */ static int tdb_write(struct tdb_context *tdb, tdb_off_t off, const void *buf, tdb_len_t len) @@ -305,13 +267,14 @@ static int tdb_read(struct tdb_context *tdb, tdb_off_t off, void *buf, if (tdb->map_ptr) { memcpy(buf, off + (char *)tdb->map_ptr, len); } else { - if (!tdb_pread_all(tdb->fd, buf, len, off)) { + ssize_t r = pread(tdb->fd, buf, len, off); + if (r != len) { tdb_logerr(tdb, TDB_ERR_IO, TDB_DEBUG_FATAL, - "tdb_read failed at %zu " + "tdb_read failed with %zi at %zu " "len=%zu (%s) map_size=%zu", - (size_t)off, (size_t)len, - strerror(errno), - (size_t)tdb->map_size); + r, (size_t)off, (size_t)len, + strerror(errno), + (size_t)tdb->map_size); return -1; } } diff --git a/ccan/tdb2/private.h b/ccan/tdb2/private.h index de832af6..1092f171 100644 --- a/ccan/tdb2/private.h +++ b/ccan/tdb2/private.h @@ -476,8 +476,6 @@ tdb_off_t tdb_find_zero_off(struct tdb_context *tdb, tdb_off_t off, /* Even on files, we can get partial writes due to signals. */ bool tdb_pwrite_all(int fd, const void *buf, size_t len, tdb_off_t off); -bool tdb_pread_all(int fd, void *buf, size_t len, tdb_off_t off); -bool tdb_read_all(int fd, void *buf, size_t len); /* Allocate and make a copy of some offset. */ void *tdb_alloc_read(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t len); diff --git a/ccan/tdb2/tdb.c b/ccan/tdb2/tdb.c index dfa68451..e3b579d0 100644 --- a/ccan/tdb2/tdb.c +++ b/ccan/tdb2/tdb.c @@ -22,6 +22,24 @@ static bool tdb_already_open(dev_t device, ino_t ino) return false; } +static bool read_all(int fd, void *buf, size_t len) +{ + while (len) { + ssize_t ret; + ret = read(fd, buf, len); + if (ret < 0) + return false; + if (ret == 0) { + /* ETOOSHORT? */ + errno = EWOULDBLOCK; + return false; + } + buf = (char *)buf + ret; + len -= ret; + } + return true; +} + static uint64_t random_number(struct tdb_context *tdb) { int fd; @@ -30,7 +48,7 @@ static uint64_t random_number(struct tdb_context *tdb) fd = open("/dev/urandom", O_RDONLY); if (fd >= 0) { - if (tdb_read_all(fd, &ret, sizeof(ret))) { + if (read_all(fd, &ret, sizeof(ret))) { tdb_logerr(tdb, TDB_SUCCESS, TDB_DEBUG_TRACE, "tdb_open: random from /dev/urandom"); close(fd); @@ -153,6 +171,7 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, int saved_errno = 0; uint64_t hash_test; unsigned v; + ssize_t rlen; struct tdb_header hdr; struct tdb_attribute_seed *seed = NULL; @@ -253,17 +272,25 @@ struct tdb_context *tdb_open(const char *name, int tdb_flags, goto fail; } - if (!tdb_pread_all(tdb->fd, &hdr, sizeof(hdr), 0) - || strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0) { - if (!(open_flags & O_CREAT)) { - tdb_logerr(tdb, TDB_ERR_IO, TDB_DEBUG_ERROR, - "tdb_open: %s is not a tdb file", name); - goto fail; - } + /* If they used O_TRUNC, read will return 0. */ + rlen = read(tdb->fd, &hdr, sizeof(hdr)); + if (rlen == 0 && (open_flags & O_CREAT)) { if (tdb_new_database(tdb, seed, &hdr) == -1) { goto fail; } - } else if (hdr.version != TDB_VERSION) { + } else if (rlen < 0) { + tdb_logerr(tdb, TDB_ERR_IO, TDB_DEBUG_ERROR, + "tdb_open: error %s reading %s", + strerror(errno), name); + goto fail; + } else if (rlen < sizeof(hdr) + || strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0) { + tdb_logerr(tdb, TDB_ERR_IO, TDB_DEBUG_ERROR, + "tdb_open: %s is not a tdb file", name); + goto fail; + } + + if (hdr.version != TDB_VERSION) { if (hdr.version == bswap_64(TDB_VERSION)) tdb->flags |= TDB_CONVERT; else {