From 8dce43a3ea7a529bc37cbe5607a8d52186cc8169 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" 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