[Libguestfs] [PATCH libnbd v4 1/2] copy: Store the preferred block size in the operations struct

Richard W.M. Jones rjones at redhat.com
Thu Jun 30 16:43:56 UTC 2022


This will be used in a subsequent commit.  At the moment the preferred
block size for all sources / destinations is simply calculated and
stored.
---
 copy/file-ops.c |  4 +++-
 copy/main.c     | 29 +++++++++++++++++++++++------
 copy/nbd-ops.c  | 10 ++++++++++
 copy/nbdcopy.h  |  4 +++-
 copy/null-ops.c |  1 +
 copy/pipe-ops.c |  1 +
 6 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/copy/file-ops.c b/copy/file-ops.c
index ab3787545c..34f08e58c7 100644
--- a/copy/file-ops.c
+++ b/copy/file-ops.c
@@ -241,13 +241,15 @@ seek_hole_supported (int fd)
 
 struct rw *
 file_create (const char *name, int fd,
-             off_t st_size, bool is_block, direction d)
+             off_t st_size, uint64_t preferred,
+             bool is_block, direction d)
 {
   struct rw_file *rwf = calloc (1, sizeof *rwf);
   if (rwf == NULL) { perror ("calloc"); exit (EXIT_FAILURE); }
 
   rwf->rw.ops = &file_ops;
   rwf->rw.name = name;
+  rwf->rw.preferred = preferred;
   rwf->fd = fd;
   rwf->is_block = is_block;
 
diff --git a/copy/main.c b/copy/main.c
index cc379e98bc..19ec384d78 100644
--- a/copy/main.c
+++ b/copy/main.c
@@ -512,10 +512,26 @@ open_local (const char *filename, direction d)
     fprintf (stderr, "%s: %s: %m\n", prog, filename);
     exit (EXIT_FAILURE);
   }
-  if (S_ISBLK (stat.st_mode) || S_ISREG (stat.st_mode))
-    return file_create (filename, fd, stat.st_size, S_ISBLK (stat.st_mode), d);
-  else {
-    /* Probably stdin/stdout, a pipe or a socket. */
+  if (S_ISREG (stat.st_mode))   /* Regular file. */
+    return file_create (filename, fd,
+                        stat.st_size, (uint64_t) stat.st_blksize, false, d);
+  else if (S_ISBLK (stat.st_mode)) { /* Block device. */
+    unsigned int blkioopt;
+
+#ifdef BLKIOOPT
+    if (ioctl (fd, BLKIOOPT, &blkioopt) == -1) {
+      fprintf (stderr, "warning: cannot get optimal I/O size: %s: %m",
+               filename);
+      blkioopt = 4096;
+    }
+#else
+    blkioopt = 4096;
+#endif
+
+    return file_create (filename, fd,
+                        stat.st_size, (uint64_t) blkioopt, true, d);
+  }
+  else {              /* Probably stdin/stdout, a pipe or a socket. */
     synchronous = true;        /* Force synchronous mode for pipes. */
     return pipe_create (filename, fd);
   }
@@ -528,8 +544,9 @@ print_rw (struct rw *rw, const char *prefix, FILE *fp)
   char buf[HUMAN_SIZE_LONGEST];
 
   fprintf (fp, "%s: %s \"%s\"\n", prefix, rw->ops->ops_name, rw->name);
-  fprintf (fp, "%s: size=%" PRIi64 " (%s)\n",
-           prefix, rw->size, human_size (buf, rw->size, NULL));
+  fprintf (fp, "%s: size=%" PRIi64 " (%s), preferred block size=%" PRIu64 "\n",
+           prefix, rw->size, human_size (buf, rw->size, NULL),
+           rw->preferred);
 }
 
 /* Default implementation of rw->ops->get_extents for backends which
diff --git a/copy/nbd-ops.c b/copy/nbd-ops.c
index 3bc26ba613..098863453f 100644
--- a/copy/nbd-ops.c
+++ b/copy/nbd-ops.c
@@ -112,12 +112,22 @@ open_one_nbd_handle (struct rw_nbd *rwn)
    * the same way.
    */
   if (rwn->handles.len == 0) {
+    int64_t block_size;
+
     rwn->can_zero = nbd_can_zero (nbd) > 0;
+
     rwn->rw.size = nbd_get_size (nbd);
     if (rwn->rw.size == -1) {
       fprintf (stderr, "%s: %s: %s\n", prog, rwn->rw.name, nbd_get_error ());
       exit (EXIT_FAILURE);
     }
+
+    block_size = nbd_get_block_size (nbd, LIBNBD_SIZE_PREFERRED);
+    if (block_size == -1) {
+      fprintf (stderr, "%s: %s: %s\n", prog, rwn->rw.name, nbd_get_error ());
+      exit (EXIT_FAILURE);
+    }
+    rwn->rw.preferred = block_size == 0 ? 4096 : block_size;
   }
 
   if (handles_append (&rwn->handles, nbd) == -1) {
diff --git a/copy/nbdcopy.h b/copy/nbdcopy.h
index 19797dfd66..9438cce417 100644
--- a/copy/nbdcopy.h
+++ b/copy/nbdcopy.h
@@ -43,6 +43,7 @@ struct rw {
   struct rw_ops *ops;           /* Operations. */
   const char *name;             /* Printable name, for error messages etc. */
   int64_t size;                 /* May be -1 for streams. */
+  uint64_t preferred;           /* Preferred block size. */
   /* Followed by private data for the particular subtype. */
 };
 
@@ -53,7 +54,8 @@ typedef enum { READING, WRITING } direction;
 
 /* Create subtypes. */
 extern struct rw *file_create (const char *name, int fd,
-                               off_t st_size, bool is_block, direction d);
+                               off_t st_size, uint64_t preferred,
+                               bool is_block, direction d);
 extern struct rw *nbd_rw_create_uri (const char *name,
                                      const char *uri, direction d);
 extern struct rw *nbd_rw_create_subprocess (const char **argv, size_t argc,
diff --git a/copy/null-ops.c b/copy/null-ops.c
index 1218a623e2..99cc9a73fe 100644
--- a/copy/null-ops.c
+++ b/copy/null-ops.c
@@ -45,6 +45,7 @@ null_create (const char *name)
   rw->rw.ops = &null_ops;
   rw->rw.name = name;
   rw->rw.size = INT64_MAX;
+  rw->rw.preferred = 4096;
   return &rw->rw;
 }
 
diff --git a/copy/pipe-ops.c b/copy/pipe-ops.c
index 3c8b6c2b39..3815f824fc 100644
--- a/copy/pipe-ops.c
+++ b/copy/pipe-ops.c
@@ -43,6 +43,7 @@ pipe_create (const char *name, int fd)
   rwp->rw.ops = &pipe_ops;
   rwp->rw.name = name;
   rwp->rw.size = -1;
+  rwp->rw.preferred = 4096;
   rwp->fd = fd;
   return &rwp->rw;
 }
-- 
2.37.0.rc2



More information about the Libguestfs mailing list