[Libguestfs] [nbdkit PATCH 9/9] blocksize: Implement .cache rounding

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


Rely on .can_cache passthrough to imply that our .cache won't be
called unless the plugin also has .cache. [Technically, that won't
happen until a later patch flips the default in filters.c].  Round the
cache request out, to cache the same range as would otherwise be
passed to the plugin's .pread if we had set .can_cache to
false. Fortunately, when maxlen is larger than maxblock, and the
plugin supports .cache, this results in a lot fewer calls into the
plugin than the .pread fallback.

Oddly enough, a client can submit an unaligned request for just under
4G of caching where our rounding would overflow a 32-bit integer, so
our rounding has to use a 64-bit temporary.

Signed-off-by: Eric Blake <eblake at redhat.com>
---
 filters/blocksize/blocksize.c | 31 ++++++++++++++++++++++++++++++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/filters/blocksize/blocksize.c b/filters/blocksize/blocksize.c
index 4f3e9a3..2d28222 100644
--- a/filters/blocksize/blocksize.c
+++ b/filters/blocksize/blocksize.c
@@ -1,5 +1,5 @@
 /* nbdkit
- * Copyright (C) 2018 Red Hat Inc.
+ * Copyright (C) 2018-2019 Red Hat Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -389,6 +389,34 @@ blocksize_extents (struct nbdkit_next_ops *next_ops, void *nxdata,
                             flags, extents, err);
 }

+static int
+blocksize_cache (struct nbdkit_next_ops *next_ops, void *nxdata,
+                 void *handle, uint32_t count, uint64_t offs, uint32_t flags,
+                 int *err)
+{
+  uint32_t limit;
+  uint64_t remaining = count; /* Rounding out could exceed 32 bits */
+
+  /* Unaligned head */
+  limit = offs & (minblock - 1);
+  remaining += limit;
+  offs -= limit;
+
+  /* Unaligned tail */
+  remaining = ROUND_UP (remaining, minblock);
+
+  /* Aligned body */
+  while (remaining) {
+    limit = MIN (maxdata, remaining);
+    if (next_ops->cache (nxdata, limit, offs, flags, err) == -1)
+      return -1;
+    offs += limit;
+    remaining -= limit;
+  }
+
+  return 0;
+}
+
 static struct nbdkit_filter filter = {
   .name              = "blocksize",
   .longname          = "nbdkit blocksize filter",
@@ -404,6 +432,7 @@ static struct nbdkit_filter filter = {
   .trim              = blocksize_trim,
   .zero              = blocksize_zero,
   .extents           = blocksize_extents,
+  .cache             = blocksize_cache,
 };

 NBDKIT_REGISTER_FILTER(filter)
-- 
2.20.1




More information about the Libguestfs mailing list