Skip to content

Instantly share code, notes, and snippets.

@abbbi
Last active October 17, 2023 15:45
Show Gist options
  • Save abbbi/d69e5eaa841f99f16cb37d172cd080af to your computer and use it in GitHub Desktop.
Save abbbi/d69e5eaa841f99f16cb37d172cd080af to your computer and use it in GitHub Desktop.
nbdcopy
diff --git a/copy/main.c b/copy/main.c
index c0c9421..5da91bd 100644
--- a/copy/main.c
+++ b/copy/main.c
@@ -46,6 +46,8 @@
bool allocated; /* --allocated flag */
unsigned connections = 4; /* --connections */
+char* context = "base:allocation"; /* -- context */
+bool use_bitmap = false;
bool target_is_zero; /* --target-is-zero flag */
bool extents = true; /* ! --no-extents flag */
bool flush; /* --flush flag */
@@ -73,7 +75,7 @@ usage (FILE *fp, int exitcode)
"\n"
"Copy to and from an NBD server:\n"
"\n"
-" nbdcopy [--allocated] [-C N|--connections=N]\n"
+" nbdcopy [--allocated] [-C N|--connections=N] [-c N|--context=BITMAP_CTX]\n"
" [--destination-is-zero|--target-is-zero] [--flush]\n"
" [--no-extents] [-p|--progress|--progress=FD]\n"
" [--queue-size=N] [--request-size=N] [-R N|--requests=N]\n"
@@ -117,11 +119,12 @@ main (int argc, char *argv[])
REQUEST_SIZE_OPTION,
SYNCHRONOUS_OPTION,
};
- const char *short_options = "C:pR:S:T:vV";
+ const char *short_options = "c:C:pR:S:T:vV";
const struct option long_options[] = {
{ "help", no_argument, NULL, HELP_OPTION },
{ "long-options", no_argument, NULL, LONG_OPTIONS },
{ "allocated", no_argument, NULL, ALLOCATED_OPTION },
+ { "context", required_argument, NULL, 'c' },
{ "connections", required_argument, NULL, 'C' },
{ "destination-is-zero", no_argument, NULL, TARGET_IS_ZERO_OPTION },
{ "flush", no_argument, NULL, FLUSH_OPTION },
@@ -200,6 +203,11 @@ main (int argc, char *argv[])
}
break;
+ case 'c':
+ context = optarg;
+ use_bitmap = true;
+ break;
+
case 'p':
progress = true;
if (optarg) {
@@ -460,9 +468,14 @@ main (int argc, char *argv[])
/* If the source is NBD and we couldn't negotiate meta
* base:allocation then turn off extents.
*/
- if (! src->ops->can_extents (src))
+ if (!src->ops->can_extents (src))
extents = false;
+ if ( use_bitmap == true && !src->ops->can_extents(src)) {
+ fprintf(stderr, "error: specified context %s not exposed by ndb server.\n", context);
+ exit(EXIT_FAILURE);
+ }
+
/* Always set the progress bar to 0% at the start of the copy. */
progress_bar (0, 1);
diff --git a/copy/nbd-ops.c b/copy/nbd-ops.c
index 71ee0a3..e7358ba 100644
--- a/copy/nbd-ops.c
+++ b/copy/nbd-ops.c
@@ -84,7 +84,7 @@ open_one_nbd_handle (struct rw_nbd *rwn)
}
if (extents && rwn->d == READING &&
- nbd_add_meta_context (nbd, "base:allocation") == -1) {
+ nbd_add_meta_context (nbd, context) == -1) {
fprintf (stderr, "%s: %s\n", prog, nbd_get_error ());
exit (EXIT_FAILURE);
}
@@ -236,7 +236,7 @@ nbd_ops_can_extents (struct rw *rw)
struct rw_nbd *rwn = (struct rw_nbd *)rw;
if (rwn->handles.len > 0)
- return nbd_can_meta_context (rwn->handles.ptr[0], "base:allocation");
+ return nbd_can_meta_context (rwn->handles.ptr[0], context);
else
return false;
}
@@ -502,9 +502,6 @@ add_extent (void *vp, const char *metacontext,
extent_list *ret = vp;
size_t i;
- if (strcmp (metacontext, "base:allocation") != 0 || *error)
- return 0;
-
for (i = 0; i < nr_entries; i++) {
struct extent e;
@@ -517,6 +514,7 @@ add_extent (void *vp, const char *metacontext,
* arguments.
*/
e.zero = (entries[i].flags & LIBNBD_STATE_ZERO) != 0;
+ e.dirty = (entries[i].flags & LIBNBD_STATE_DIRTY) != 0;
if (extent_list_append (ret, e) == -1) {
perror ("realloc");
diff --git a/copy/nbdcopy.h b/copy/nbdcopy.h
index 465b705..6cd5535 100644
--- a/copy/nbdcopy.h
+++ b/copy/nbdcopy.h
@@ -115,6 +115,7 @@ struct extent {
uint64_t offset;
uint64_t length;
bool zero;
+ bool dirty;
};
DEFINE_VECTOR_TYPE (extent_list, struct extent);
@@ -228,6 +229,8 @@ extern void asynch_notify_read_write_not_supported (struct rw *rw,
extern bool allocated;
extern unsigned connections;
+extern char *context;
+extern bool use_bitmap;
extern bool target_is_zero;
extern bool extents;
extern bool flush;
diff --git a/copy/synch-copying.c b/copy/synch-copying.c
index 38888e3..508370c 100644
--- a/copy/synch-copying.c
+++ b/copy/synch-copying.c
@@ -85,6 +85,13 @@ synch_copying (void)
offset += exts.ptr[i].length;
}
else /* data */ {
+ /* in case data for a specified context, ignore clean extents */
+ if (use_bitmap == true) {
+ if( ! exts.ptr[i].dirty) {
+ offset += exts.ptr[i].length;
+ continue;
+ }
+ }
r = src->ops->synch_read (src, buf, exts.ptr[i].length, offset);
/* These cases should never happen unless the file is
@abbbi
Copy link
Author

abbbi commented Oct 17, 2023

$ ./nbdcopy  --synchronous 'nbd+unix:///vdf?socket=/var/tmp/vircpt.83239'  full.img
$ qemu-img info full.img 
image: full.img
file format: raw
virtual size: 2 MiB (2097152 bytes)
disk size: 388 KiB
$ ./nbdcopy  --synchronous -c qemu:dirty-bitmap:TEST  'nbd+unix:///vdf?socket=/var/tmp/vircpt.83239'  inc.img
$ qemu-img info inc.img 
image: inc.img
file format: raw
virtual size: 2 MiB (2097152 bytes)
disk size: 192 KiB

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment