From edcad9c1c88e6e698040855d7518d0c27dfc4489 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Thu, 1 Oct 2015 15:53:47 -0400 Subject: [PATCH] Port: implement posix_fallocate wrapper MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathieu Desnoyers Signed-off-by: Jérémie Galarneau --- configure.ac | 7 ++ formats/ctf/ctf.c | 3 +- formats/ctf/writer/event-fields.c | 3 +- include/Makefile.am | 1 + include/babeltrace/compat/fcntl.h | 143 ++++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 include/babeltrace/compat/fcntl.h diff --git a/configure.ac b/configure.ac index 75bc9af4..c4faf6e5 100644 --- a/configure.ac +++ b/configure.ac @@ -133,6 +133,13 @@ AC_CHECK_LIB([c], [open_memstream], ] ) +# Check for posix_fallocate +AC_CHECK_LIB([c], [posix_fallocate], +[ + AC_DEFINE_UNQUOTED([BABELTRACE_HAVE_POSIX_FALLOCATE], 1, [Has posix_fallocate support.]) +] +) + AC_CHECK_LIB([popt], [poptGetContext], [], [AC_MSG_ERROR([Cannot find popt.])] ) diff --git a/formats/ctf/ctf.c b/formats/ctf/ctf.c index 865e2c2e..af1809ef 100644 --- a/formats/ctf/ctf.c +++ b/formats/ctf/ctf.c @@ -53,6 +53,7 @@ #include "metadata/ctf-ast.h" #include "events-private.h" #include +#include #define LOG2_CHAR_BIT 3 @@ -906,7 +907,7 @@ void ctf_packet_seek(struct bt_stream_pos *stream_pos, size_t index, int whence) } pos->content_size = -1U; /* Unknown at this point */ pos->packet_size = WRITE_PACKET_LEN; - off = posix_fallocate(pos->fd, pos->mmap_offset, + off = bt_posix_fallocate(pos->fd, pos->mmap_offset, pos->packet_size / CHAR_BIT); assert(off == 0); pos->offset = 0; diff --git a/formats/ctf/writer/event-fields.c b/formats/ctf/writer/event-fields.c index 461888f9..9eff2dca 100644 --- a/formats/ctf/writer/event-fields.c +++ b/formats/ctf/writer/event-fields.c @@ -30,6 +30,7 @@ #include #include #include +#include #define PACKET_LEN_INCREMENT (getpagesize() * 8 * CHAR_BIT) @@ -1241,7 +1242,7 @@ int increase_packet_size(struct ctf_stream_pos *pos) } pos->packet_size += PACKET_LEN_INCREMENT; - ret = posix_fallocate(pos->fd, pos->mmap_offset, + ret = bt_posix_fallocate(pos->fd, pos->mmap_offset, pos->packet_size / CHAR_BIT); if (ret) { goto end; diff --git a/include/Makefile.am b/include/Makefile.am index 9109642d..d183dbe0 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -54,5 +54,6 @@ noinst_HEADERS = \ babeltrace/compat/utc.h \ babeltrace/compat/limits.h \ babeltrace/compat/send.h \ + babeltrace/compat/fcntl.h \ babeltrace/endian.h \ babeltrace/mmap-align.h diff --git a/include/babeltrace/compat/fcntl.h b/include/babeltrace/compat/fcntl.h new file mode 100644 index 00000000..59060ff5 --- /dev/null +++ b/include/babeltrace/compat/fcntl.h @@ -0,0 +1,143 @@ +#ifndef _BABELTRACE_COMPAT_FCNTL_H +#define _BABELTRACE_COMPAT_FCNTL_H + +/* + * babeltrace/compat/fcntl.h + * + * Copyright 2015 (c) - Jérémie Galarneau + * + * fcntl compatibility layer. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +#ifdef BABELTRACE_HAVE_POSIX_FALLOCATE + +#include + +static inline +int bt_posix_fallocate(int fd, off_t offset, off_t len) +{ + return posix_fallocate(fd, offset, len); +} + +#else /* #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */ + +#include +#include +#include + +#define BABELTRACE_FALLOCATE_BUFLEN 256 + +#ifndef min_t +#define min_t(type, a, b) \ + ((type) (a) < (type) (b) ? (type) (a) : (type) (b)) +#endif + +static inline +int bt_posix_fallocate(int fd, off_t offset, off_t len) +{ + int ret = 0; + ssize_t copy_len; + char buf[BABELTRACE_FALLOCATE_BUFLEN]; + off_t i, file_pos, orig_end_offset, range_end; + + if (offset < 0 || len < 0) { + ret = EINVAL; + goto end; + } + + range_end = offset + len; + if (range_end < 0) { + ret = EFBIG; + goto end; + } + + file_pos = lseek(fd, 0, SEEK_CUR); + if (file_pos < 0) { + ret = errno; + goto end; + } + + orig_end_offset = lseek(fd, 0, SEEK_END); + if (orig_end_offset < 0) { + ret = errno; + goto end; + } + + /* Seek back to original position. */ + ret = lseek(fd, file_pos, SEEK_SET); + if (ret) { + ret = errno; + goto end; + } + + /* + * The file may not need to grow, but we want to ensure the + * space has actually been reserved by the file system. First, copy + * the "existing" region of the file, then grow the file if needed. + */ + for (i = file_pos; i < min_t(off_t, range_end, orig_end_offset); + i += copy_len) { + ssize_t copy_ret; + + copy_len = min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN, + min_t(off_t, range_end - i, + orig_end_offset - i)); + copy_ret = pread(fd, &buf, copy_len, i); + if (copy_ret < copy_len) { + /* + * The caller must handle any EINTR. + * POSIX_FALLOCATE(3) does not mention EINTR. + * However, glibc does forward to fallocate() + * directly on Linux, which may be interrupted. + */ + ret = errno; + goto end; + } + + copy_ret = pwrite(fd, &buf, copy_len, i); + if (copy_ret < copy_len) { + /* Same caveat as noted at pread() */ + ret = errno; + goto end; + } + } + + /* Grow file, as necessary. */ + memset(&buf, 0, BABELTRACE_FALLOCATE_BUFLEN); + for (i = orig_end_offset; i < range_end; i += copy_len) { + ssize_t write_ret; + + copy_len = min_t(size_t, BABELTRACE_FALLOCATE_BUFLEN, + range_end - i); + write_ret = pwrite(fd, &buf, copy_len, i); + if (write_ret < copy_len) { + ret = errno; + goto end; + } + } +end: + return ret; +} +#endif /* #else #ifdef BABELTRACE_HAVE_POSIX_FALLOCATE */ + +#endif /* _BABELTRACE_COMPAT_FCNTL_H */ -- 2.34.1