Add ability to invoke fallocate() FALLOC_FL_KEEP_SIZE.
Linux offers fallocate() and the FALLOC_FL_KEEP_SIZE option as
an alternative to posix_fallocate(). When FALLOC_FL_KEEP_SIZE is
specified for an falloc request going beyond the end of the file,
the requested blocks get preallocated without changing the apparent
size of the file. This is is a commonly recommended use of fallocate()
for workloads performing append writes.
This patch modifies the fallocate option from a boolean option
to a string option accepting none/posix/keep/0/1. 'keep' is only
made available on systems where FALLOC_FL_KEEP_SIZE is available
(i.e., Linux at this time). If specified, fallocate() is used
with FALLOC_FL_KEEP_SIZE set. 'none' disables pre-allocation while
'posix' uses posix_fallocate(). The default behavior remains unchaned,
i.e., invoking posix_fallocate. The settings '0'/'1' are there to
provide backward compatibility for users who had explicitly set the
boolean option.
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
diff --git a/filesetup.c b/filesetup.c
index 799202f..6d8aa7a 100644
--- a/filesetup.c
+++ b/filesetup.c
@@ -13,6 +13,10 @@
#include "filehash.h"
#include "os/os.h"
+#ifdef FIO_HAVE_LINUX_FALLOCATE
+#include <linux/falloc.h>
+#endif
+
static int root_warn;
static inline void clear_error(struct thread_data *td)
@@ -67,17 +71,41 @@
}
#ifdef FIO_HAVE_FALLOCATE
- if (td->o.fallocate && !td->o.fill_device) {
- dprint(FD_FILE, "fallocate file %s size %llu\n", f->file_name,
- f->real_file_size);
+ if (!td->o.fill_device) {
+ switch (td->o.fallocate_mode) {
+ case FIO_FALLOCATE_NONE:
+ break;
+ case FIO_FALLOCATE_POSIX:
+ dprint(FD_FILE, "posix_fallocate file %s size %llu\n",
+ f->file_name, f->real_file_size);
- r = posix_fallocate(f->fd, 0, f->real_file_size);
- if (r > 0) {
- log_err("fio: posix_fallocate fails: %s\n",
- strerror(r));
+ r = posix_fallocate(f->fd, 0, f->real_file_size);
+ if (r > 0) {
+ log_err("fio: posix_fallocate fails: %s\n",
+ strerror(r));
+ }
+ break;
+#ifdef FIO_HAVE_LINUX_FALLOCATE
+ case FIO_FALLOCATE_KEEP_SIZE:
+ dprint(FD_FILE,
+ "fallocate(FALLOC_FL_KEEP_SIZE) "
+ "file %s size %llu\n",
+ f->file_name, f->real_file_size);
+
+ r = fallocate(f->fd, FALLOC_FL_KEEP_SIZE, 0,
+ f->real_file_size);
+ if (r != 0) {
+ td_verror(td, errno, "fallocate");
+ }
+ break;
+#endif /* FIO_HAVE_LINUX_FALLOCATE */
+ default:
+ log_err("fio: unknown fallocate mode: %d\n",
+ td->o.fallocate_mode);
+ assert(0);
}
}
-#endif
+#endif /* FIO_HAVE_FALLOCATE */
if (!new_layout)
goto done;