164 lines
5.5 KiB
Diff
164 lines
5.5 KiB
Diff
From 8dce43a3ea7a529bc37cbe5607a8d52186cc8169 Mon Sep 17 00:00:00 2001
|
|
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
Date: Tue, 28 Jun 2022 18:27:58 +0100
|
|
Subject: [PATCH] copy: Store the preferred block size in the operations struct
|
|
|
|
This will be used in a subsequent commit. At the moment the preferred
|
|
block size for all sources / destinations is simply calculated and
|
|
stored.
|
|
|
|
(cherry picked from commit e6c42f8b2d447bbcc659d6dd33be67335834b2e5)
|
|
---
|
|
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 ab37875..34f08e5 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 cc379e9..19ec384 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 3bc26ba..0988634 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 19797df..9438cce 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 1218a62..99cc9a7 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 3c8b6c2..3815f82 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.31.1
|
|
|