Ejemplo n.º 1
0
static ssize_t
fiob_writef(struct fiob *f, const char *buf, size_t count)
{
	int fd = f->fd;
	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]", f->path);
			return -1; /* XXX: file position is unspecified */
		}
		if (nwr == 0)
			break;

		buf += nwr;
		to_write -= nwr;
	}
	return count - to_write;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/**
 * Sets O_NONBLOCK flag in case if lognonblock is set.
 */
static void
log_set_nonblock(struct log *log)
{
	if (!log->nonblock)
		return;
	int flags;
	if ((flags = fcntl(log->fd, F_GETFL, 0)) < 0 ||
	    fcntl(log->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
		say_syserror("fcntl, fd=%i", log->fd);
	}
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 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;
}
Ejemplo n.º 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;
}
Ejemplo n.º 8
0
static ssize_t
fiob_readf(struct fiob *f, char *buf, size_t count)
{
	ssize_t to_read = (ssize_t) count;
	while (to_read > 0) {
		ssize_t nrd = read(f->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]", f->path);
			return -1; /* XXX: file position is unspecified */
		}
		if (nrd == 0)
			break;

		buf += nrd;
		to_read -= nrd;
	}
	return count - to_read;
}
Ejemplo n.º 9
0
static ssize_t
fiob_read(void *cookie, char *buf, size_t count)
#endif
{
	struct fiob *f = (struct fiob *)cookie;
	ssize_t to_read = (ssize_t) count;

	/* The number of starting bytes in f->buf to skip due to alignment */
	off_t skip = 0;
	while (to_read > 0) {
		/* Align `to_read' FIOB_ALIGN to be <= size of f->buf */
		ssize_t to_read_al = MIN(fiob_ceil(to_read), f->bsize);
		/*
		 * Optimistically try to read aligned size into the aligned
		 * buffer. If the current file position is not aligned then
		 * read(2) returns EINVAL. In this case seek to an aligned
		 * position and try again. This trick saves one extra
		 * syscall for general workflow.
		 */
		ssize_t nrd = read(f->fd, f->buf, to_read_al);
		if (nrd < 0) {
			if (errno == EINTR) {
				errno = 0;
				continue;
			} else if (errno == EINVAL && skip == 0) {
				/*
				 * read(2) can return EINVAL only in 3 cases:
				 *  1. read buffer is not aligned - handled in
				 *     fiob_open().
				 *  2. read size is not aligned - handled above
				 *  3. current file position is not aligned -
				 *     handled here.
				 */
				off_t pos = lseek(f->fd, 0, SEEK_CUR);
				if (pos < 0) {
					say_syserror("lseek, [%s]", f->path);
					return -1;
				}
				/* Calculate aligned position */
				skip = pos % FIOB_ALIGN;
				pos -= skip;
				if (skip == 0) {
					/* Position is aligned. */
					errno = EINVAL;
					say_error("read, [%s]", f->path);
					return -1;
				}
				/* Seek to the new position */
				if (lseek(f->fd, pos, SEEK_SET) != pos) {
					say_syserror("lseek, [%s]", f->path);
					return -1;
				}
				/* Try to read again. */
				continue;
			}
			say_syserror("read, [%s]", f->path);
			return -1; /* XXX: file position is unspecified */
		}
		/* Ignore starting bytes if the position was aligned. */
		nrd -= skip;
		if (nrd == 0)
			break;
		if (nrd > to_read) {
			/*
			 * A few more bytes have been read because `to_read'
			 * is not aligned to FIOB_ALIGN. Set the file position
			 * to the expected libc value and ignore extra bytes.
			 */
			if (lseek(f->fd, to_read - nrd, SEEK_CUR) < 0) {
				say_syserror("lseek, [%s]", f->path);
				return -1;
			}
			nrd = to_read;
		}

		memcpy(buf, f->buf + skip, nrd); /* see nrd -= skip */
		skip = 0; /* reset alignment offset */
		buf += nrd;
		to_read -= nrd;
	}
	return count - to_read;
}
Ejemplo n.º 10
0
/** open file. The same as fopen but receives additional open (2) flags */
FILE *
fiob_open(const char *path, const char *mode)
{
	int omode = 0666;
	int flags = 0;
	int save_errno;
	int fd = -1;
	FILE *file = NULL;
#if defined (FIOB_DIRECT)
	struct fiob *f = NULL;
#endif /* defined(FIOB_DIRECT) */
	int um = umask(0722);
	umask(um);
	omode &= ~um;

	if (strchr(mode, 'r')) {
		if (strchr(mode, '+'))
			flags |= O_RDWR;
		else
			flags |= O_RDONLY;
	} else if (strchr(mode, 'w')) {
		flags |= O_TRUNC | O_CREAT;
		if (strchr(mode, '+'))
			flags |= O_RDWR;
		else
			flags |= O_WRONLY;
	} else if (strchr(mode, 'a')) {
		flags |= O_CREAT | O_APPEND;
		if (strchr(mode, '+'))
			flags |= O_RDWR;
		else
			flags |= O_WRONLY;
	} else {
		errno = EINVAL;
		return NULL;
	}

	/* O_EXCL */
#ifdef O_EXCL
	if (strchr(mode, 'x'))
		flags |= O_EXCL;
#endif
	/* O_SYNC */
	if (strchr(mode, 's')) {
		flags |= WAL_SYNC_FLAG;
	}

	fd = open(path, flags, omode);
	if (fd < 0)
		goto error;
#if defined(FIOB_DIRECT)
	if (strchr(mode, 'd') == NULL)
		goto fdopen;

	/* Try to enable O_DIRECT */
	flags = fcntl(fd, F_GETFL);
	if (flags != -1 && fcntl(fd, F_SETFL, flags | O_DIRECT) != -1) {
		say_debug("using O_DIRECT for %s", path);
	} else {
#if defined(NDEBUG) /* Don't use opencookie in release mode without O_DIRECT */
		goto fdopen;
#endif /* defined(NDEBUG) */
	}

	f = (struct fiob *)calloc(1, sizeof(struct fiob));
	if (!f)
		goto error;

	f->fd = fd;
	f->bsize = FIOB_BSIZE;
	if (posix_memalign(&f->buf, FIOB_ALIGN, f->bsize))
		goto error;

	/* for valgrind */
	memset(f->buf, 0, f->bsize);

	f->path = strdup(path);
	if (!f->path)
		goto error;

	f->io.read	= fiob_read;
	f->io.write	= fiob_write;
	f->io.seek	= fiob_seek;
	f->io.close	= fiob_close;

#ifdef HAVE_FUNOPEN
	file = funopen(f,
		       f->io.read, f->io.write, f->io.seek, f->io.close);
#else
	file = fopencookie(f, mode, f->io);
#endif

	if (!file)
		goto error;

#ifdef TARGET_OS_LINUX
	file->_fileno = f->fd;
#else
	file->_file = f->fd;
#endif

	return file;

fdopen:
#endif /* defined(FIOB_DIRECT) */
	/* Fallback to libc implementation */
	file = fdopen(fd, mode);
	if (!file)
		goto error;
	return file;

error:
	save_errno = errno;
	say_syserror("Can't open '%s'", path);
	if (fd >= 0)
		close(fd);

#if defined(FIOB_DIRECT)
	if (f) {
		free(f->buf);
		free(f->path);
		free(f);
	}
#endif /* FIOB_DIRECT */

	errno = save_errno;
	return NULL;
}
Ejemplo n.º 11
0
/** open file. The same as fiob_open but receives additional open (2) flags */
FILE *
fiob_open(const char *path, const char *mode)
{
	int omode = 0666;
	int flags = 0;
	int save_errno;

	size_t bsize = 0;
	void *buf = NULL;

	int um = umask(0722);
	umask(um);
	omode &= ~um;


	if (strchr(mode, 'r')) {
		if (strchr(mode, '+'))
			flags |= O_RDWR;
		else
			flags |= O_RDONLY;
	} else if (strchr(mode, 'w')) {
		flags |= O_TRUNC | O_CREAT;
		if (strchr(mode, '+'))
			flags |= O_RDWR;
		else
			flags |= O_WRONLY;
	} else if (strchr(mode, 'a')) {
		flags |= O_CREAT | O_APPEND;
		if (strchr(mode, '+'))
			flags |= O_RDWR;
		else
			flags |= O_WRONLY;
	} else {
		errno = EINVAL;
		return NULL;
	}

	/* O_EXCL */
#ifdef O_EXCL
	if (strchr(mode, 'x'))
		flags |= O_EXCL;
#endif

	/* O_DIRECT */
	if (strchr(mode, 'd')) {
#ifdef O_DIRECT
		flags |= O_DIRECT;
#endif
		bsize = O_DIRECT_BSIZE;
		posix_memalign(&buf, 4096, bsize);
		if (!buf) {
			errno = ENOMEM;
			return NULL;
		}
		/* for valgrind */
		memset(buf, 0, bsize);
	}

	/* O_SYNC */
	if (strchr(mode, 's')) {
		flags |= WAL_SYNC_FLAG;
	}

	struct fiob *f = (struct fiob *)calloc(1, sizeof(struct fiob));
	if (!f) {
		free(buf);
		errno = ENOMEM;
		return NULL;
	}

	f->path = strdup(path);
	if (!f->path) {
		errno = ENOMEM;
		goto error;
	}

	f->buf = buf;
	f->bsize = bsize;

	f->fd = open(path, flags, omode);
	if (f->fd < 0)
		goto error;



	f->io.read	= fiob_read;
	f->io.write	= fiob_write;
	f->io.seek	= fiob_seek;
	f->io.close	= fiob_close;

	FILE *file;
#ifdef HAVE_FUNOPEN
	file = funopen(f,
		       f->io.read, f->io.write, f->io.seek, f->io.close);
#else
	file = fopencookie(f, mode, f->io);
#endif

	if (!file)
		goto error;

#ifdef TARGET_OS_LINUX
	file->_fileno = f->fd;
#else
	file->_file = f->fd;
#endif

	return file;

error:
	save_errno = errno;
	say_syserror("Can't open '%s'", path);
	if (f->fd > 0)
		close(f->fd);

	free(f->buf);
	free(f->path);
	free(f);

	errno = save_errno;
	return NULL;
}