Blame SOURCES/0003-guestfs_readdir-minimize-the-number-of-send_file_wri.patch

65aaff
From 62cd6c9d2dd62dd24cc04b16437bfb816a6f4357 Mon Sep 17 00:00:00 2001
65aaff
From: Laszlo Ersek <lersek@redhat.com>
65aaff
Date: Mon, 2 May 2022 10:56:01 +0200
65aaff
Subject: [PATCH] guestfs_readdir(): minimize the number of send_file_write()
65aaff
 calls
65aaff
65aaff
In guestfs_readdir(), the daemon currently sends each XDR-encoded
65aaff
"guestfs_int_dirent" to the library with a separate send_file_write()
65aaff
call.
65aaff
65aaff
Determine the largest encoded size (from the longest filename that a
65aaff
"guestfs_int_dirent" could carry, from readdir()'s "struct dirent"), and
65aaff
batch up the XDR encodings until the next encoding might not fit in
65aaff
GUESTFS_MAX_CHUNK_SIZE. Call send_file_write() only then.
65aaff
65aaff
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1674392
65aaff
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
65aaff
Message-Id: <20220502085601.15012-3-lersek@redhat.com>
65aaff
Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
65aaff
(cherry picked from commit 4864d21cb8eb991f0fc98d03a068173837cba50e)
65aaff
---
65aaff
 daemon/readdir.c | 38 ++++++++++++++++++++++++++++++++------
65aaff
 1 file changed, 32 insertions(+), 6 deletions(-)
65aaff
65aaff
diff --git a/daemon/readdir.c b/daemon/readdir.c
65aaff
index 9ab0b0aec..3084ba939 100644
65aaff
--- a/daemon/readdir.c
65aaff
+++ b/daemon/readdir.c
65aaff
@@ -35,6 +35,9 @@ do_internal_readdir (const char *dir)
65aaff
   DIR *dirstream;
65aaff
   void *xdr_buf;
65aaff
   XDR xdr;
65aaff
+  struct dirent fill;
65aaff
+  guestfs_int_dirent v;
65aaff
+  unsigned max_encoded;
65aaff
 
65aaff
   /* Prepare to fail. */
65aaff
   ret = -1;
65aaff
@@ -55,6 +58,20 @@ do_internal_readdir (const char *dir)
65aaff
   }
65aaff
   xdrmem_create (&xdr, xdr_buf, GUESTFS_MAX_CHUNK_SIZE, XDR_ENCODE);
65aaff
 
65aaff
+  /* Calculate the max number of bytes a "guestfs_int_dirent" can be encoded to.
65aaff
+   */
65aaff
+  memset (fill.d_name, 'a', sizeof fill.d_name - 1);
65aaff
+  fill.d_name[sizeof fill.d_name - 1] = '\0';
65aaff
+  v.ino = INT64_MAX;
65aaff
+  v.ftyp = '?';
65aaff
+  v.name = fill.d_name;
65aaff
+  if (!xdr_guestfs_int_dirent (&xdr, &v)) {
65aaff
+    fprintf (stderr, "xdr_guestfs_int_dirent failed\n");
65aaff
+    goto release_xdr;
65aaff
+  }
65aaff
+  max_encoded = xdr_getpos (&xdr;;
65aaff
+  xdr_setpos (&xdr, 0);
65aaff
+
65aaff
   /* Send an "OK" reply, before starting the file transfer. */
65aaff
   reply (NULL, NULL);
65aaff
 
65aaff
@@ -63,7 +80,6 @@ do_internal_readdir (const char *dir)
65aaff
    */
65aaff
   for (;;) {
65aaff
     struct dirent *d;
65aaff
-    guestfs_int_dirent v;
65aaff
 
65aaff
     errno = 0;
65aaff
     d = readdir (dirstream);
65aaff
@@ -94,22 +110,32 @@ do_internal_readdir (const char *dir)
65aaff
     v.ftyp = 'u';
65aaff
 #endif
65aaff
 
65aaff
+    /* Flush "xdr_buf" if we may not have enough room for encoding "v". */
65aaff
+    if (GUESTFS_MAX_CHUNK_SIZE - xdr_getpos (&xdr) < max_encoded) {
65aaff
+      if (send_file_write (xdr_buf, xdr_getpos (&xdr)) != 0)
65aaff
+        break;
65aaff
+
65aaff
+      xdr_setpos (&xdr, 0);
65aaff
+    }
65aaff
+
65aaff
     if (!xdr_guestfs_int_dirent (&xdr, &v)) {
65aaff
       fprintf (stderr, "xdr_guestfs_int_dirent failed\n");
65aaff
       break;
65aaff
     }
65aaff
-
65aaff
-    if (send_file_write (xdr_buf, xdr_getpos (&xdr)) != 0)
65aaff
-      break;
65aaff
-
65aaff
-    xdr_setpos (&xdr, 0);
65aaff
   }
65aaff
 
65aaff
+  /* Flush "xdr_buf" if the loop completed successfully and "xdr_buf" is not
65aaff
+   * empty. */
65aaff
+  if (ret == 0 && xdr_getpos (&xdr) > 0 &&
65aaff
+      send_file_write (xdr_buf, xdr_getpos (&xdr)) != 0)
65aaff
+    ret = -1;
65aaff
+
65aaff
   /* Finish or cancel the transfer. Note that if (ret == -1) because the library
65aaff
    * canceled, we still need to cancel back!
65aaff
    */
65aaff
   send_file_end (ret == -1);
65aaff
 
65aaff
+release_xdr:
65aaff
   xdr_destroy (&xdr;;
65aaff
   free (xdr_buf);
65aaff
 
65aaff
-- 
65aaff
2.31.1
65aaff