r23977: Im prove the pwrite-patch to tdb_expand_file of r23972:
authorMichael Adam <obnox@samba.org>
Fri, 20 Jul 2007 14:23:12 +0000 (14:23 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:28:51 +0000 (12:28 -0500)
* 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)

source3/lib/tdb/common/io.c

index ea925f38953c7a1cc2b55580b4b96b6416818831..a24b5e24a2d30394bb7d86acc97e73e9d696ccf4 100644 (file)
@@ -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;
 }