diff --git a/discover/device-handler.c b/discover/device-handler.c
index 682a4e9..c31fcea 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -1581,6 +1581,41 @@ void device_release_write(struct discover_device *dev, bool release)
 		dev->mounted = true;
 }
 
+void device_sync_snapshots(struct device_handler *handler, const char *device)
+{
+	struct discover_device *dev = NULL;
+	unsigned int i;
+
+	if (device) {
+		/* Find matching device and sync */
+		dev = device_lookup_by_name(handler, device);
+		if (!dev) {
+			pb_log("%s: device name '%s' unrecognised\n",
+				__func__, device);
+			return;
+		}
+		if (dev->ramdisk)
+			device_release_write(dev, true);
+		else
+			pb_log("%s has no snapshot to merge, skipping\n",
+				dev->device->id);
+		return;
+	}
+
+	/* Otherwise sync all relevant devices */
+	for (i = 0; i < handler->n_devices; i++) {
+		dev = handler->devices[i];
+		if (dev->device->type != DEVICE_TYPE_DISK &&
+			dev->device->type != DEVICE_TYPE_USB)
+			continue;
+		if (dev->ramdisk)
+			device_release_write(dev, true);
+		else
+			pb_log("%s has no snapshot to merge, skipping\n",
+				dev->device->id);
+	}
+}
+
 #else
 
 void device_handler_discover_context_commit(
@@ -1628,4 +1663,10 @@ void device_release_write(struct discover_device *dev __attribute__((unused)),
 {
 }
 
+void device_sync_snapshots(
+		struct device_handler *handler __attribute__((unused)),
+		const char *device __attribute__((unused)))
+{
+}
+
 #endif
diff --git a/discover/device-handler.h b/discover/device-handler.h
index 6b1a757..b6f9fd5 100644
--- a/discover/device-handler.h
+++ b/discover/device-handler.h
@@ -142,5 +142,6 @@ void device_handler_reinit(struct device_handler *handler);
 
 int device_request_write(struct discover_device *dev, bool *release);
 void device_release_write(struct discover_device *dev, bool release);
+void device_sync_snapshots(struct device_handler *handler, const char *device);
 
 #endif /* _DEVICE_HANDLER_H */
diff --git a/discover/event.c b/discover/event.c
index 8b3a1ab..242ae81 100644
--- a/discover/event.c
+++ b/discover/event.c
@@ -55,6 +55,8 @@ static int event_parse_ad_header(char *buf, int len, enum event_action *action,
 		*action = EVENT_ACTION_DHCP;
 	else if (streq(buf, "boot"))
 		*action = EVENT_ACTION_BOOT;
+	else if (streq(buf, "sync"))
+		*action = EVENT_ACTION_SYNC;
 	else {
 		pb_log("%s: unknown action: %s\n", __func__, buf);
 		return -1;
diff --git a/discover/event.h b/discover/event.h
index 35c0767..a603615 100644
--- a/discover/event.h
+++ b/discover/event.h
@@ -14,6 +14,7 @@ enum event_action {
 	EVENT_ACTION_CONF,
 	EVENT_ACTION_DHCP,
 	EVENT_ACTION_BOOT,
+	EVENT_ACTION_SYNC,
 	EVENT_ACTION_MAX,
 };
 
diff --git a/discover/user-event.c b/discover/user-event.c
index 15d9c87..76a75d9 100644
--- a/discover/user-event.c
+++ b/discover/user-event.c
@@ -464,6 +464,18 @@ static int user_event_boot(struct user_event *uev, struct event *event)
 	return 0;
 }
 
+static int user_event_sync(struct user_event *uev, struct event *event)
+{
+	struct device_handler *handler = uev->handler;
+
+	if (strncasecmp(event->device, "all", strlen("all")) != 0)
+		device_sync_snapshots(handler, event->device);
+	else
+		device_sync_snapshots(handler, NULL);
+
+	return 0;
+}
+
 static void user_event_handle_message(struct user_event *uev, char *buf,
 	int len)
 {
@@ -499,6 +511,9 @@ static void user_event_handle_message(struct user_event *uev, char *buf,
 	case EVENT_ACTION_BOOT:
 		result = user_event_boot(uev, event);
 		break;
+	case EVENT_ACTION_SYNC:
+		result = user_event_sync(uev, event);
+		break;
 	default:
 		break;
 	}
diff --git a/utils/pb-event.c b/utils/pb-event.c
index 572eb16..10bf4f5 100644
--- a/utils/pb-event.c
+++ b/utils/pb-event.c
@@ -55,7 +55,7 @@ static void print_usage(void)
 "       Events can be read from stdin, or provided on the command line.\n"
 "       User events must have the following format:\n"
 "\n"
-"         (add|remove|boot)@device-id [name=value] [image=value] [args=value]\n"
+"         (add|remove|boot|sync)@device-id [name=value] [image=value] [args=value]\n"
 "\n"
 "       When read from stdin, components are separated by NUL chars\n"
 "\n"
