discover: Allow fs recovery if snapshot available
authorSamuel Mendoza-Jonas <sam.mj@au1.ibm.com>
Tue, 25 Aug 2015 00:33:14 +0000 (10:33 +1000)
committerSamuel Mendoza-Jonas <sam.mj@au1.ibm.com>
Thu, 10 Sep 2015 05:49:23 +0000 (15:49 +1000)
If we have a device-mapper snapshot available we can now guarantee
filesystem recovery will not write back to a read-only mounted disk.
Allow recovery on those devices with the notable exception of XFS which
may fail to mount if the filesystem is the opposite endian of Petitboot.

Signed-off-by: Samuel Mendoza-Jonas <sam.mj@au1.ibm.com>
discover/device-handler.c

index 9246f0dd865ea3218f6bb5d6869553a64295e1ba..4e25e079ca18185e21ec187e57a5cd09f9315e0f 100644 (file)
@@ -1225,16 +1225,26 @@ 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)
+static const char *fs_parameters(struct discover_device *dev,
+                                unsigned int rw_flags)
 {
+       const char *fstype = discover_device_get_param(dev, "ID_FS_TYPE");
+
+       /* XFS journals are not cross-endian compatible; don't try recovery
+        * even if we have a snapshot */
+       if (!strncmp(fstype, "xfs", strlen("xfs")))
+               return "norecovery";
+
+       /* If we have a snapshot available allow touching the filesystem */
+       if (dev->ramdisk)
+               return "";
+
        if ((rw_flags | MS_RDONLY) != MS_RDONLY)
                return "";
 
-       /* Avoid writing back to the disk on journaled filesystems */
+       /* Avoid writes due to journal replay if we don't have a snapshot */
        if (!strncmp(fstype, "ext4", strlen("ext4")))
                return "norecovery";
-       if (!strncmp(fstype, "xfs", strlen("xfs")))
-               return "norecovery";
 
        return "";
 }
@@ -1342,7 +1352,7 @@ static int mount_device(struct discover_device *dev)
        errno = 0;
        rc = mount(device_path, dev->mount_path, fstype,
                        MS_RDONLY | MS_SILENT,
-                       fs_parameters(MS_RDONLY, fstype));
+                       fs_parameters(dev, MS_RDONLY));
        if (!rc) {
                dev->mounted = true;
                dev->mounted_rw = false;
@@ -1422,7 +1432,7 @@ int device_request_write(struct discover_device *dev, bool *release)
 
        rc = mount(device_path, dev->mount_path, fstype,
                        MS_SILENT,
-                       fs_parameters(MS_REMOUNT, fstype));
+                       fs_parameters(dev, MS_REMOUNT));
        if (rc)
                goto mount_ro;
 
@@ -1435,7 +1445,7 @@ mount_ro:
               device_path, strerror(errno));
        if (mount(device_path, dev->mount_path, fstype,
                        MS_RDONLY | MS_SILENT,
-                       fs_parameters(MS_RDONLY, fstype)))
+                       fs_parameters(dev, MS_RDONLY)))
                pb_log("Unable to recover mount for %s: %s\n",
                       device_path, strerror(errno));
        return -1;
@@ -1469,7 +1479,7 @@ void device_release_write(struct discover_device *dev, bool release)
 
        mount(device_path, dev->mount_path, fstype,
                        MS_RDONLY | MS_SILENT,
-                       fs_parameters(MS_RDONLY, fstype));
+                       fs_parameters(dev, MS_RDONLY));
        if (rc)
                pb_log("Failed to remount %s read-only: %s\n",
                       device_path, strerror(errno));