Beispiel #1
0
int
fio_batch_write(struct fio_batch *batch, int fd)
{
	ssize_t bytes_written = fio_writev(fd, batch->iov, batch->iovcnt);
	if (bytes_written <= 0)
		return 0;

	if (bytes_written == batch->bytes)
		return batch->rows; /* returns the number of written rows */

	say_warn("fio_batch_write, [%s]: partial write,"
		 " wrote %jd out of %jd bytes",
		 fio_filename(fd),
		 (intmax_t) bytes_written, (intmax_t) batch->bytes);

	/* Iterate over end of row flags */
	struct bit_iterator bit_it;
	bit_iterator_init(&bit_it, batch->rowflag,
			  batch->max_iov / CHAR_BIT + 1, 1);
	size_t row_last_iov = bit_iterator_next(&bit_it);

	int good_rows = 0; /* the number of fully written rows */
	ssize_t good_bytes = 0; /* the number of bytes in fully written rows */
	ssize_t row_bytes = 0;  /* the number of bytes in the current row */
	struct iovec *iov = batch->iov;
	while (iov < batch->iov + batch->iovcnt) {
		if (good_bytes + row_bytes + iov->iov_len > bytes_written)
			break;
		row_bytes += iov->iov_len;
		if ((iov - batch->iov) == row_last_iov) {
			/* the end of current row  */
			good_bytes += row_bytes;
			row_bytes = 0;
			good_rows++;
			row_last_iov = bit_iterator_next(&bit_it);
		}
		iov++;
	}
	/*
	 * Unwind file position back to ensure we do not leave
	 * partially written rows.
	 */
	off_t good_offset = fio_lseek(fd,
				      good_bytes - bytes_written, SEEK_CUR);
	/*
	 * The caller may choose to close the file right after
	 * a partial write. Don't take chances and make sure that
	 * there is no garbage at the end of file if it happens.
	 */
	if (good_offset != -1)
		(void) fio_truncate(fd, good_offset);
	/*
	 * writev() doesn't set errno in case of a partial write.
	 * If nothing else from the above failed, set errno to
	 * EAGAIN.
	 */
	if (! errno)
		errno = EAGAIN;
	return good_rows;  /* returns the number of written rows */
}
Beispiel #2
0
off_t
fio_lseek(int fd, off_t offset, int whence)
{
	off_t effective_offset = lseek(fd, offset, whence);

	if (effective_offset == -1) {
		say_syserror("lseek, [%s]: offset=%jd, whence=%d",
			     fio_filename(fd), (intmax_t) offset, whence);
	} else if (whence == SEEK_SET && effective_offset != offset) {
		say_error("lseek, [%s]: offset set to unexpected value: "
			  "requested %jd effective %jd",
			  fio_filename(fd),
			  (intmax_t)offset, (intmax_t)effective_offset);
	}
	return effective_offset;
}
Beispiel #3
0
int
fio_truncate(int fd, off_t offset)
{
	int rc = ftruncate(fd, offset);
	if (rc)
		say_syserror("fio_truncate, [%s]: offset=%jd",
			     fio_filename(fd), (intmax_t) offset);
	return rc;
}
Beispiel #4
0
ssize_t
fio_writev(int fd, struct iovec *iov, int iovcnt)
{
	assert(iov && iovcnt >= 0);
	ssize_t nwr;
restart:
	nwr = writev(fd, iov, iovcnt);
	if (nwr < 0) {
		if (errno == EINTR) {
			errno = 0;
			goto restart;
		}
		if (errno != EAGAIN && errno != EWOULDBLOCK)
			say_syserror("writev, [%s]", fio_filename(fd));
	}
	return nwr;
}
Beispiel #5
0
int
fio_batch_write(struct fio_batch *batch, int fd)
{
	ssize_t bytes_written = fio_writev(fd, batch->iov, batch->rows);
	if (bytes_written <= 0)
		return 0;

	if (bytes_written == batch->bytes)
		return batch->rows;

	say_warn("fio_batch_write, [%s]: partial write,"
		 " wrote %jd out of %jd bytes",
		 fio_filename(fd),
		 (intmax_t) bytes_written, (intmax_t) batch->bytes);

	ssize_t good_bytes = 0;
	struct iovec *iov = batch->iov;
	while (iov < batch->iov + batch->rows) {
		if (good_bytes + iov->iov_len > bytes_written)
			break;
		good_bytes += iov->iov_len;
		iov++;
	}
	/*
	 * Unwind file position back to ensure we do not leave
	 * partially written rows.
	 */
	off_t good_offset = fio_lseek(fd,
				      good_bytes - bytes_written, SEEK_CUR);
	/*
	 * The caller may choose to close the file right after
	 * a partial write. Don't take chances and make sure that
	 * there is no garbage at the end of file if it happens.
	 */
	if (good_offset != -1)
		(void) fio_truncate(fd, good_offset);
	/*
	 * writev() doesn't set errno in case of a partial write.
	 * If nothing else from the above failed, set errno to
	 * EAGAIN.
	 */
	if (! errno)
		errno = EAGAIN;
	return iov - batch->iov;
}
Beispiel #6
0
ssize_t
fio_write(int fd, const void *buf, size_t count)
{
	ssize_t to_write = (ssize_t) count;
	while (to_write > 0) {
		ssize_t nwr = write(fd, buf, to_write);
		if (nwr < 0) {
			if (errno == EINTR) {
				errno = 0;
				continue;
			}
			if (errno == EAGAIN || errno == EWOULDBLOCK)
				return count != to_write ? count - to_write : -1;
			say_syserror("write, [%s]", fio_filename(fd));
			return -1; /* XXX: file position is unspecified */
		}
		if (nwr == 0)
			break;

		buf += nwr;
		to_write -= nwr;
	}
	return count - to_write;
}
Beispiel #7
0
ssize_t
fio_read(int fd, void *buf, size_t count)
{
	ssize_t to_read = (ssize_t) count;
	while (to_read > 0) {
		ssize_t nrd = read(fd, buf, to_read);
		if (nrd < 0) {
			if (errno == EINTR) {
				errno = 0;
				continue;
			}
			if (errno == EAGAIN || errno == EWOULDBLOCK)
				return count != to_read ? count - to_read : -1;
			say_syserror("read, [%s]", fio_filename(fd));
			return -1; /* XXX: file position is unspecified */
		}
		if (nrd == 0)
			break;

		buf += nrd;
		to_read -= nrd;
	}
	return count - to_read;
}