Since NBD_CMD_CACHE is already advisory, let's use an advisory kernel
interface to implement it ;) When posix_fadvise() is not present, it
is likely that nbdkit's fallback to .pread will actually have a
similar benefit in populating the filesystem cache, since we aren't
using O_DIRECT to avoid that cache.
Signed-off-by: Eric Blake <eblake(a)redhat.com>
---
configure.ac | 3 ++-
plugins/file/file.c | 22 ++++++++++++++++++++++
plugins/split/split.c | 37 ++++++++++++++++++++++++++++++++++++-
3 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index 58031f3..06124c5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -195,7 +195,8 @@ dnl Check for functions in libc, all optional.
AC_CHECK_FUNCS([\
fdatasync \
get_current_dir_name \
- mkostemp])
+ mkostemp \
+ posix_fadvise])
dnl Check whether printf("%m") works
AC_CACHE_CHECK([whether the printf family supports %m],
diff --git a/plugins/file/file.c b/plugins/file/file.c
index f0ac23b..85b033b 100644
--- a/plugins/file/file.c
+++ b/plugins/file/file.c
@@ -608,6 +608,25 @@ file_extents (void *handle, uint32_t count, uint64_t offset,
}
#endif /* SEEK_HOLE */
+#if HAVE_POSIX_FADVISE
+/* Caching. */
+static int
+file_cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
+{
+ struct handle *h = handle;
+ int r;
+
+ /* Cache is advisory, we don't care if this fails */
+ r = posix_fadvise (h->fd, offset, count, POSIX_FADV_WILLNEED);
+ if (r) {
+ errno = r;
+ nbdkit_error ("posix_fadvise: %m");
+ return -1;
+ }
+ return 0;
+}
+#endif /* HAVE_POSIX_FADVISE */
+
static struct nbdkit_plugin plugin = {
.name = "file",
.longname = "nbdkit file plugin",
@@ -632,6 +651,9 @@ static struct nbdkit_plugin plugin = {
#ifdef SEEK_HOLE
.can_extents = file_can_extents,
.extents = file_extents,
+#endif
+#if HAVE_POSIX_FADVISE
+ .cache = file_cache,
#endif
.errno_is_preserved = 1,
};
diff --git a/plugins/split/split.c b/plugins/split/split.c
index cf2b2c7..cef2d51 100644
--- a/plugins/split/split.c
+++ b/plugins/split/split.c
@@ -1,5 +1,5 @@
/* nbdkit
- * Copyright (C) 2017-2018 Red Hat Inc.
+ * Copyright (C) 2017-2019 Red Hat Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -277,6 +277,38 @@ split_pwrite (void *handle, const void *buf, uint32_t count, uint64_t
offset)
return 0;
}
+#if HAVE_POSIX_FADVISE
+/* Caching. */
+static int
+split_cache (void *handle, uint32_t count, uint64_t offset, uint32_t flags)
+{
+ struct handle *h = handle;
+
+ /* Cache is advisory, we don't care if this fails */
+ while (count > 0) {
+ struct file *file = get_file (h, offset);
+ uint64_t foffs = offset - file->offset;
+ uint64_t max;
+ int r;
+
+ max = file->size - foffs;
+ if (max > count)
+ max = count;
+
+ r = posix_fadvise (file->fd, offset, max, POSIX_FADV_WILLNEED);
+ if (r) {
+ errno = r;
+ nbdkit_error ("posix_fadvise: %m");
+ return -1;
+ }
+ count -= r;
+ offset += r;
+ }
+
+ return 0;
+}
+#endif /* HAVE_POSIX_FADVISE */
+
static struct nbdkit_plugin plugin = {
.name = "split",
.version = PACKAGE_VERSION,
@@ -289,6 +321,9 @@ static struct nbdkit_plugin plugin = {
.get_size = split_get_size,
.pread = split_pread,
.pwrite = split_pwrite,
+#if HAVE_POSIX_FADVISE
+ .cache = split_cache,
+#endif
/* In this plugin, errno is preserved properly along error return
* paths from failed system calls.
*/
--
2.20.1