f3write: adopt write_all() from libdevs.c

The file system HFS (i.e. "OS X Extended (Journaled)") of
macOS 10.11 may return a number of partial write()'s before
the file system is full.

This POSIX-permited, but unusual behavior was frist reported here:
https://github.com/AltraMayor/f3/issues/111
This commit is contained in:
Michel Machado 2019-03-11 12:22:48 -04:00
parent 3a25af5db3
commit 2766edd4be

View File

@ -485,6 +485,21 @@ static int end_measurement(int fd, struct flow *fw)
return 0; return 0;
} }
/* XXX Avoid duplicate this function, which was copied from libdevs.c. */
static int write_all(int fd, const char *buf, size_t count)
{
size_t done = 0;
do {
ssize_t rc = write(fd, buf + done, count - done);
if (rc < 0) {
/* The write() failed. */
return errno;
}
done += rc;
} while (done < count);
return 0;
}
#define MAX_WRITE_SIZE (1<<21) /* 2MB */ #define MAX_WRITE_SIZE (1<<21) /* 2MB */
/* Return true when disk is full. */ /* Return true when disk is full. */
@ -523,7 +538,6 @@ static int create_and_fill_file(const char *path, long number, size_t size,
remaining = size; remaining = size;
start_measurement(fw); start_measurement(fw);
while (remaining > 0) { while (remaining > 0) {
ssize_t written;
ssize_t write_size = fw->block_size * ssize_t write_size = fw->block_size *
(fw->blocks_per_delay - fw->written_blocks); (fw->blocks_per_delay - fw->written_blocks);
assert(write_size > 0); assert(write_size > 0);
@ -532,23 +546,11 @@ static int create_and_fill_file(const char *path, long number, size_t size,
if ((size_t)write_size > remaining) if ((size_t)write_size > remaining)
write_size = remaining; write_size = remaining;
offset = fill_buffer(buf, write_size, offset); offset = fill_buffer(buf, write_size, offset);
written = write(fd, buf, write_size); saved_errno = write_all(fd, buf, write_size);
if (written < 0) { if (saved_errno)
saved_errno = errno;
break; break;
} remaining -= write_size;
if (written < write_size) { if (measure(fd, fw, write_size) < 0) {
/* It must have filled up the file system.
* errno should be equal to ENOSPC.
*/
assert(write(fd, buf + written, write_size - written)
< 0);
saved_errno = errno;
break;
}
assert(written == write_size);
remaining -= written;
if (measure(fd, fw, written) < 0) {
saved_errno = errno; saved_errno = errno;
break; break;
} }