diff options
author | Michael Adam <obnox@samba.org> | 2007-07-20 14:23:12 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:28:51 -0500 |
commit | e5051dd4a6657e265dd5baab828946d4ab52cc9f (patch) | |
tree | 4ea02c78198a8467c689f8861ca6869eebec4ce4 | |
parent | 8ba1569eef3737b86e7072d1bb65ed6c37a28811 (diff) | |
download | samba-e5051dd4a6657e265dd5baab828946d4ab52cc9f.tar.gz samba-e5051dd4a6657e265dd5baab828946d4ab52cc9f.tar.bz2 samba-e5051dd4a6657e265dd5baab828946d4ab52cc9f.zip |
r23977: Im prove the pwrite-patch to tdb_expand_file of r23972:
* prevent infinite loops due to 0 bytes written:
try once more. if we still get 0 as return,
set errno to ENOSPC and return -1 (error)
* replace int by correct types (ssize_t and size_t).
* print a warning log message in case "written < requested to write"
usually this means, that the next call to pwrite will fail
with return value -1 and set errno accordingly.
Note that the former error condition "written != requested to write"
is not a correct error condition of write/pwrite. If this is due
to an error, a subsequent call to (p)write will reveal the cause
(typically "no space left on device" - ENOSPC).
Michael
(This used to be commit 5b8d53dfe1872621bf28c8351d87bfc53ef6e66b)
-rw-r--r-- | source3/lib/tdb/common/io.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/source3/lib/tdb/common/io.c b/source3/lib/tdb/common/io.c index ea925f3895..a24b5e24a2 100644 --- a/source3/lib/tdb/common/io.c +++ b/source3/lib/tdb/common/io.c @@ -232,15 +232,28 @@ static int tdb_expand_file(struct tdb_context *tdb, tdb_off_t size, tdb_off_t ad disk. This must be done with write, not via mmap */ memset(buf, TDB_PAD_BYTE, sizeof(buf)); while (addition) { - int n = addition>sizeof(buf)?sizeof(buf):addition; - int ret = pwrite(tdb->fd, buf, n, size); - if (ret == -1) { - TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of %d failed (%s)\n", - n, strerror(errno))); + size_t n = addition>sizeof(buf)?sizeof(buf):addition; + ssize_t written = pwrite(tdb->fd, buf, n, size); + if (written == 0) { + /* prevent infinite loops: try _once_ more */ + written = pwrite(tdb->fd, buf, n, size); + } + if (written == 0) { + /* give up, trying to provide a useful errno */ + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write " + "returned 0 twice: giving up!\n")); + errno = ENOSPC; + return -1; + } else if (written == -1) { + TDB_LOG((tdb, TDB_DEBUG_FATAL, "expand_file write of " + "%d bytes failed (%s)\n", n, strerror(errno))); return -1; + } else if (written != n) { + TDB_LOG((tdb, TDB_DEBUG_WARNING, "expand_file: wrote " + "only %d of %d bytes - retrying\n", written,n)); } - addition -= ret; - size += ret; + addition -= written; + size += written; } return 0; } |