" (dest defaults\n"
" as the filename part of file)\n"
" \"-\" for stdin\n"
+" diff <image-name> [--from-snap <snap-name>] print extents that differ since\n"
+" a previous snap, or image creation\n"
" export-diff <image-name> [--from-snap <snap-name>] <path>\n"
" export an incremental diff to\n"
" path, or \"-\" for stdout\n"
return r;
}
+static int diff_cb(uint64_t ofs, size_t len, bool zero, void *arg)
+{
+ cout << ofs << "\t" << len << "\t"
+ << (zero ? "zero" : "data") << "\n";
+ return 0;
+}
+
+static int do_diff(librbd::Image& image, const char *fromsnapname,
+ const char *endsnapname)
+{
+ int64_t r;
+ librbd::image_info_t info;
+
+ r = image.stat(info, sizeof(info));
+ if (r < 0)
+ return r;
+
+ return image.diff_iterate(fromsnapname, 0, info.size, diff_cb, NULL);
+}
+
static const char *imgname_from_path(const char *path)
{
const char *imgname;
OPT_RM,
OPT_EXPORT,
OPT_EXPORT_DIFF,
+ OPT_DIFF,
OPT_IMPORT,
OPT_IMPORT_DIFF,
OPT_COPY,
return OPT_EXPORT;
if (strcmp(cmd, "export-diff") == 0)
return OPT_EXPORT_DIFF;
+ if (strcmp(cmd, "diff") == 0)
+ return OPT_DIFF;
if (strcmp(cmd, "import") == 0)
return OPT_IMPORT;
if (strcmp(cmd, "import-diff") == 0)
case OPT_MAP:
case OPT_BENCH_WRITE:
case OPT_LOCK_LIST:
+ case OPT_DIFF:
SET_CONF_PARAM(v, &imgname, NULL, NULL);
break;
case OPT_UNMAP:
(char **)&imgname, (char **)&snapname);
if (snapname && opt_cmd != OPT_SNAP_CREATE && opt_cmd != OPT_SNAP_ROLLBACK &&
opt_cmd != OPT_SNAP_REMOVE && opt_cmd != OPT_INFO &&
- opt_cmd != OPT_EXPORT && opt_cmd != OPT_EXPORT_DIFF && opt_cmd != OPT_COPY &&
+ opt_cmd != OPT_EXPORT && opt_cmd != OPT_EXPORT_DIFF && opt_cmd != OPT_DIFF && opt_cmd != OPT_COPY &&
opt_cmd != OPT_MAP && opt_cmd != OPT_CLONE &&
opt_cmd != OPT_SNAP_PROTECT && opt_cmd != OPT_SNAP_UNPROTECT &&
opt_cmd != OPT_CHILDREN) {
opt_cmd == OPT_INFO || opt_cmd == OPT_SNAP_LIST ||
opt_cmd == OPT_IMPORT_DIFF ||
opt_cmd == OPT_EXPORT || opt_cmd == OPT_EXPORT_DIFF || opt_cmd == OPT_COPY ||
+ opt_cmd == OPT_DIFF ||
opt_cmd == OPT_CHILDREN || opt_cmd == OPT_LOCK_LIST)) {
if (opt_cmd == OPT_INFO || opt_cmd == OPT_SNAP_LIST ||
(opt_cmd == OPT_INFO ||
opt_cmd == OPT_EXPORT ||
opt_cmd == OPT_EXPORT_DIFF ||
+ opt_cmd == OPT_DIFF ||
opt_cmd == OPT_COPY ||
opt_cmd == OPT_CHILDREN)) {
r = image.snap_set(snapname);
}
break;
+ case OPT_DIFF:
+ r = do_diff(image, fromsnapname, snapname);
+ if (r < 0) {
+ cerr << "rbd: diff error: " << cpp_strerror(-r) << std::endl;
+ return EXIT_FAILURE;
+ }
+ break;
+
case OPT_EXPORT_DIFF:
if (!path) {
cerr << "rbd: export-diff requires pathname" << std::endl;