[PATCH V2 3/3] discover: Mount snapshots for all eligible disk devices

Samuel Mendoza-Jonas sam.mj at au1.ibm.com
Fri May 22 15:32:23 AEST 2015


Device-mapper snapshots are created for all disk devices prior to
being mounted. If explicit writes are made to the snapshot they are
merged back to the disk once write access is released.

Signed-off-by: Samuel Mendoza-Jonas <sam.mj at au1.ibm.com>
---
 discover/device-handler.c | 81 ++++++++++++++++++++++++++++++++++++-----------
 discover/udev.c           | 20 ++++++++++--
 2 files changed, 80 insertions(+), 21 deletions(-)

diff --git a/discover/device-handler.c b/discover/device-handler.c
index cd16399..31cbcc2 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -26,6 +26,7 @@
 
 #include "device-handler.h"
 #include "discover-server.h"
+#include "devmapper.h"
 #include "user-event.h"
 #include "platform.h"
 #include "event.h"
@@ -1237,14 +1238,22 @@ static const char *fs_parameters(unsigned int rw_flags, const char *fstype)
 	return "";
 }
 
+static inline const char *get_device_path(struct discover_device *dev)
+{
+	return dev->ramdisk ? dev->ramdisk->snapshot : dev->device_path;
+}
+
 static bool check_existing_mount(struct discover_device *dev)
 {
 	struct stat devstat, mntstat;
+	const char *device_path;
 	struct mntent *mnt;
 	FILE *fp;
 	int rc;
 
-	rc = stat(dev->device_path, &devstat);
+	device_path = get_device_path(dev);
+
+	rc = stat(device_path, &devstat);
 	if (rc) {
 		pb_debug("%s: stat failed: %s\n", __func__, strerror(errno));
 		return false;
@@ -1294,7 +1303,7 @@ static bool check_existing_mount(struct discover_device *dev)
 
 static int mount_device(struct discover_device *dev)
 {
-	const char *fstype;
+	const char *fstype, *device_path;
 	int rc;
 
 	if (!dev->device_path)
@@ -1326,9 +1335,11 @@ static int mount_device(struct discover_device *dev)
 		goto err_free;
 	}
 
+	device_path = get_device_path(dev);
+
 	pb_log("mounting device %s read-only\n", dev->device_path);
 	errno = 0;
-	rc = mount(dev->device_path, dev->mount_path, fstype,
+	rc = mount(device_path, dev->mount_path, fstype,
 			MS_RDONLY | MS_SILENT,
 			fs_parameters(MS_RDONLY, fstype));
 	if (!rc) {
@@ -1339,7 +1350,10 @@ static int mount_device(struct discover_device *dev)
 	}
 
 	pb_log("couldn't mount device %s: mount failed: %s\n",
-			dev->device_path, strerror(errno));
+			device_path, strerror(errno));
+
+	/* If mount fails clean up any snapshot */
+	devmapper_destroy_snapshot(dev);
 
 	pb_rmdir_recursive(mount_base(), dev->mount_path);
 err_free:
@@ -1350,17 +1364,21 @@ err_free:
 
 static int umount_device(struct discover_device *dev)
 {
+	const char *device_path;
 	int rc;
 
 	if (!dev->mounted || !dev->unmount)
 		return 0;
 
-	pb_log("unmounting device %s\n", dev->device_path);
+	device_path = get_device_path(dev);
+
+	pb_log("unmounting device %s\n", device_path);
 	rc = umount(dev->mount_path);
 	if (rc)
 		return -1;
 
 	dev->mounted = false;
+	devmapper_destroy_snapshot(dev);
 
 	pb_rmdir_recursive(mount_base(), dev->mount_path);
 
@@ -1372,7 +1390,7 @@ static int umount_device(struct discover_device *dev)
 
 int device_request_write(struct discover_device *dev, bool *release)
 {
-	const char *fstype;
+	const char *fstype, *device_path;
 	int rc;
 
 	*release = false;
@@ -1385,14 +1403,18 @@ int device_request_write(struct discover_device *dev, bool *release)
 
 	fstype = discover_device_get_param(dev, "ID_FS_TYPE");
 
-	pb_log("remounting device %s read-write\n", dev->device_path);
+	device_path = get_device_path(dev);
+
+	pb_log("remounting device %s read-write\n", device_path);
 
 	rc = umount(dev->mount_path);
 	if (rc) {
-		pb_log("Failed to unmount %s\n", dev->mount_path);
+		pb_log("Failed to unmount %s: %s\n",
+		       dev->mount_path, strerror(errno));
 		return -1;
 	}
-	rc = mount(dev->device_path, dev->mount_path, fstype,
+
+	rc = mount(device_path, dev->mount_path, fstype,
 			MS_SILENT,
 			fs_parameters(MS_REMOUNT, fstype));
 	if (rc)
@@ -1403,29 +1425,50 @@ int device_request_write(struct discover_device *dev, bool *release)
 	return 0;
 
 mount_ro:
-	pb_log("Unable to remount device %s read-write\n", dev->device_path);
-	rc = mount(dev->device_path, dev->mount_path, fstype,
+	pb_log("Unable to remount device %s read-write: %s\n",
+	       device_path, strerror(errno));
+	if (mount(device_path, dev->mount_path, fstype,
 			MS_RDONLY | MS_SILENT,
-			fs_parameters(MS_RDONLY, fstype));
-	if (rc)
-		pb_log("Unable to recover mount for %s\n", dev->device_path);
+			fs_parameters(MS_RDONLY, fstype)))
+		pb_log("Unable to recover mount for %s: %s\n",
+		       device_path, strerror(errno));
 	return -1;
 }
 
 void device_release_write(struct discover_device *dev, bool release)
 {
-	const char *fstype;
+	const char *fstype, *device_path;
+	int rc = 0;
 
 	if (!release)
 		return;
 
+	device_path = get_device_path(dev);
+
 	fstype = discover_device_get_param(dev, "ID_FS_TYPE");
 
-	pb_log("remounting device %s read-only\n", dev->device_path);
-	mount(dev->device_path, dev->mount_path, "",
-			MS_REMOUNT | MS_RDONLY | MS_SILENT,
+	pb_log("remounting device %s read-only\n", device_path);
+
+	if (umount(dev->mount_path)) {
+		pb_log("Failed to unmount %s\n", dev->mount_path);
+		return;
+	}
+	dev->mounted_rw = dev->mounted = false;
+
+	if (dev->ramdisk) {
+		devmapper_merge_snapshot(dev);
+		/* device_path becomes stale after merge */
+		device_path = get_device_path(dev);
+	}
+
+	mount(device_path, dev->mount_path, fstype,
+			MS_RDONLY | MS_SILENT,
 			fs_parameters(MS_RDONLY, fstype));
-	dev->mounted_rw = false;
+	if (rc)
+		pb_log("Failed to remount %s read-only: %s\n",
+		       device_path, strerror(errno));
+	else
+		dev->mounted = true;
 }
 
 #else
diff --git a/discover/udev.c b/discover/udev.c
index 6ccb8d4..a030d0c 100644
--- a/discover/udev.c
+++ b/discover/udev.c
@@ -25,6 +25,7 @@
 #include "pb-discover.h"
 #include "device-handler.h"
 #include "cdrom.h"
+#include "devmapper.h"
 
 /* We set a default monitor buffer size, as we may not process monitor
  * events while performing device discvoery. systemd uses a 128M buffer, so
@@ -94,12 +95,16 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
 
 	node = udev_device_get_devnode(dev);
 	path = udev_device_get_devpath(dev);
-	if (path && (strstr(path, "virtual/block/loop")
-			|| strstr(path, "virtual/block/ram"))) {
+	if (path && strstr(path, "virtual/block/loop")) {
 		pb_log("SKIP: %s: ignored (path=%s)\n", name, path);
 		return 0;
 	}
 
+	if (path && strstr(path, "virtual/block/ram")) {
+		device_handler_add_ramdisk(udev->handler, node);
+		return 0;
+	}
+
 	cdrom = node && !!udev_device_get_property_value(dev, "ID_CDROM");
 	if (cdrom) {
 		/* CDROMs require a little initialisation, to get
@@ -111,6 +116,14 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
 		}
 	}
 
+	/* dm-snapshots don't appear as udev events currently, but catch this
+	 * in case udev/libdm are updated in Petitboot's environment */
+	const char *devname = udev_device_get_property_value(dev, "DM_NAME");
+	if (devname) {
+		pb_log("SKIP: dm-snapshot %s\n", devname);
+		return 0;
+	}
+
 	type = udev_device_get_property_value(dev, "ID_FS_TYPE");
 	if (!type) {
 		pb_log("SKIP: %s: no ID_FS_TYPE property\n", name);
@@ -142,6 +155,9 @@ static int udev_handle_block_add(struct pb_udev *udev, struct udev_device *dev,
 
 	udev_setup_device_params(dev, ddev);
 
+	if (ddev->device->type == DEVICE_TYPE_DISK)
+		devmapper_init_snapshot(udev->handler, ddev);
+
 	device_handler_discover(udev->handler, ddev);
 
 	return 0;
-- 
2.1.0



More information about the Petitboot mailing list