[PATCH V2] discover: Mount with norecovery, avoid rw mount of XFS filesystems

Samuel Mendoza-Jonas sam.mj at au1.ibm.com
Thu Mar 26 11:42:10 AEDT 2015


Journaled filesytems may still write to their disk even if the disk is
mounted read only. Petitboot should avoid modifying any disks
automatically, and in mixed-endian systems this can also cause journal
operations to fail. Use the 'norecovery' option on filesystems that
support it to skip the journal replay.

Additionally, mounting an XFS filesystem as read-write in such a case
will cause the call to mount to hang indefinitely. Avoid this generally
by explicitly unmounting and (re)mounting when mounting read-write.

Signed-off-by: Samuel Mendoza-Jonas <sam.mj at au1.ibm.com>
---
 discover/device-handler.c | 56 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 51 insertions(+), 5 deletions(-)

diff --git a/discover/device-handler.c b/discover/device-handler.c
index 5d9f988..f053713 100644
--- a/discover/device-handler.c
+++ b/discover/device-handler.c
@@ -1082,6 +1082,20 @@ static void device_handler_reinit_sources(struct device_handler *handler)
 			handler->dry_run);
 }
 
+static const char *fs_parameters(unsigned int rw_flags, const char *fstype)
+{
+	if ((rw_flags | MS_RDONLY) != MS_RDONLY)
+		return "";
+
+	/* Avoid writing back to the disk on journaled filesystems */
+	if (!strncmp(fstype, "ext4", strlen("ext4")))
+		return "norecovery";
+	if (!strncmp(fstype, "xfs", strlen("xfs")))
+		return "norecovery";
+
+	return "";
+}
+
 static bool check_existing_mount(struct discover_device *dev)
 {
 	struct stat devstat, mntstat;
@@ -1155,6 +1169,13 @@ static int mount_device(struct discover_device *dev)
 	if (!fstype)
 		return 0;
 
+	/* ext3 treats the norecovery option as an error, so mount the device
+	 * as an ext4 filesystem instead */
+	if (!strncmp(fstype, "ext3", strlen("ext3"))) {
+		pb_debug("Mounting ext3 filesystem as ext4\n");
+		fstype = talloc_asprintf(dev, "ext4");
+	}
+
 	dev->mount_path = join_paths(dev, mount_base(),
 					dev->device_path);
 
@@ -1167,7 +1188,8 @@ static int mount_device(struct discover_device *dev)
 	pb_log("mounting device %s read-only\n", dev->device_path);
 	errno = 0;
 	rc = mount(dev->device_path, dev->mount_path, fstype,
-			MS_RDONLY | MS_SILENT, "");
+			MS_RDONLY | MS_SILENT,
+			fs_parameters(MS_RDONLY, fstype));
 	if (!rc) {
 		dev->mounted = true;
 		dev->mounted_rw = false;
@@ -1209,6 +1231,7 @@ static int umount_device(struct discover_device *dev)
 
 int device_request_write(struct discover_device *dev, bool *release)
 {
+	const char *fstype;
 	int rc;
 
 	*release = false;
@@ -1219,25 +1242,48 @@ int device_request_write(struct discover_device *dev, bool *release)
 	if (dev->mounted_rw)
 		return 0;
 
+	fstype = discover_device_get_param(dev, "ID_FS_TYPE");
+
 	pb_log("remounting device %s read-write\n", dev->device_path);
-	rc = mount(dev->device_path, dev->mount_path, "",
-			MS_REMOUNT | MS_SILENT, "");
-	if (rc)
+
+	rc = umount(dev->mount_path);
+	if (rc) {
+		pb_log("Failed to unmount %s\n", dev->mount_path);
 		return -1;
+	}
+	rc = mount(dev->device_path, dev->mount_path, fstype,
+			MS_SILENT,
+			fs_parameters(MS_REMOUNT, fstype));
+	if (rc)
+		goto mount_ro;
 
 	dev->mounted_rw = true;
 	*release = true;
 	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,
+			MS_RDONLY | MS_SILENT,
+			fs_parameters(MS_RDONLY, fstype));
+	if (rc)
+		pb_log("Unable to recover mount for %s\n", dev->device_path);
+	return -1;
 }
 
 void device_release_write(struct discover_device *dev, bool release)
 {
+	const char *fstype;
+
 	if (!release)
 		return;
 
+	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, "");
+			MS_REMOUNT | MS_RDONLY | MS_SILENT,
+			fs_parameters(MS_RDONLY, fstype));
 	dev->mounted_rw = false;
 }
 
-- 
2.1.0



More information about the Petitboot mailing list