[Libguestfs] [nbdkit PATCH 3/9] file, split: Implement .cache with posix_fadvise

Eric Blake eblake at redhat.com
Fri May 10 03:03:36 UTC 2019


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 at 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




More information about the Libguestfs mailing list