]> git.ozlabs.org Git - petitboot/blobdiff - discover/device-handler.c
discover: Display devices currently being parsed
[petitboot] / discover / device-handler.c
index 5d9f98892eb792db789de351fb750bb95cd0e3f9..d95a37cb0c7c41ae420001d4c227cfa012c33b2f 100644 (file)
@@ -40,8 +40,7 @@
 
 enum default_priority {
        DEFAULT_PRIORITY_REMOTE         = 1,
 
 enum default_priority {
        DEFAULT_PRIORITY_REMOTE         = 1,
-       DEFAULT_PRIORITY_LOCAL_UUID     = 2,
-       DEFAULT_PRIORITY_LOCAL_FIRST    = 3,
+       DEFAULT_PRIORITY_LOCAL_FIRST    = 2,
        DEFAULT_PRIORITY_LOCAL_LAST     = 0xfe,
        DEFAULT_PRIORITY_DISABLED       = 0xff,
 };
        DEFAULT_PRIORITY_LOCAL_LAST     = 0xfe,
        DEFAULT_PRIORITY_DISABLED       = 0xff,
 };
@@ -462,11 +461,27 @@ static bool ipmi_device_type_matches(enum ipmi_bootdev ipmi_type,
        return false;
 }
 
        return false;
 }
 
-static bool priority_matches(struct boot_priority *prio,
-               struct discover_boot_option *opt)
+static int autoboot_option_priority(const struct config *config,
+                               struct discover_boot_option *opt)
 {
 {
-       return prio->type == opt->device->device->type ||
-               prio->type == DEVICE_TYPE_ANY;
+       enum device_type type = opt->device->device->type;
+       const char *uuid = opt->device->uuid;
+       struct autoboot_option *auto_opt;
+       unsigned int i;
+
+       for (i = 0; i < config->n_autoboot_opts; i++) {
+               auto_opt = &config->autoboot_opts[i];
+               if (auto_opt->boot_type == BOOT_DEVICE_UUID)
+                       if (!strcmp(auto_opt->uuid, uuid))
+                               return DEFAULT_PRIORITY_LOCAL_FIRST + i;
+
+               if (auto_opt->boot_type == BOOT_DEVICE_TYPE)
+                       if (auto_opt->type == type ||
+                           auto_opt->type == DEVICE_TYPE_ANY)
+                               return DEFAULT_PRIORITY_LOCAL_FIRST + i;
+       }
+
+       return -1;
 }
 
 /*
 }
 
 /*
@@ -478,8 +493,6 @@ static enum default_priority default_option_priority(
                struct discover_boot_option *opt)
 {
        const struct config *config;
                struct discover_boot_option *opt)
 {
        const struct config *config;
-       const char *dev_str;
-       unsigned int i;
 
        config = config_get();
 
 
        config = config_get();
 
@@ -498,25 +511,17 @@ static enum default_priority default_option_priority(
                return DEFAULT_PRIORITY_DISABLED;
        }
 
                return DEFAULT_PRIORITY_DISABLED;
        }
 
-       /* Next, allow matching by device UUID. If we have one set but it
-        * doesn't match, disallow the default entirely */
-       dev_str = config->boot_device;
-       if (dev_str && dev_str[0]) {
-               if (!strcmp(opt->device->uuid, dev_str))
-                       return DEFAULT_PRIORITY_LOCAL_UUID;
-
-               pb_debug("handler: disabled default priority due to "
-                               "non-matching UUID\n");
-               return DEFAULT_PRIORITY_DISABLED;
-       }
-
-       /* Lastly, use the local priorities */
-       for (i = 0; i < config->n_boot_priorities; i++) {
-               struct boot_priority *prio = &config->boot_priorities[i];
-               if (priority_matches(prio, opt))
-                       return DEFAULT_PRIORITY_LOCAL_FIRST + prio->priority;
+       /* Next, try to match the option against the user-defined autoboot
+        * options, either by device UUID or type. */
+       if (config->n_autoboot_opts) {
+               int boot_match = autoboot_option_priority(config, opt);
+               if (boot_match > 0)
+                       return boot_match;
        }
 
        }
 
+       /* If the option didn't match any entry in the array, it is disabled */
+       pb_debug("handler: disabled default priority due to "
+                       "non-matching UUID or type\n");
        return DEFAULT_PRIORITY_DISABLED;
 }
 
        return DEFAULT_PRIORITY_DISABLED;
 }
 
@@ -750,8 +755,16 @@ int device_handler_discover(struct device_handler *handler,
                struct discover_device *dev)
 {
        struct discover_context *ctx;
                struct discover_device *dev)
 {
        struct discover_context *ctx;
+       struct boot_status *status;
        int rc;
 
        int rc;
 
+       status = talloc_zero(handler, struct boot_status);
+       status->type = BOOT_STATUS_INFO;
+       status->message = talloc_asprintf(status, "Processing %s device %s",
+                               device_type_display_name(dev->device->type),
+                               dev->device->id);
+       boot_status(handler, status);
+
        process_boot_option_queue(handler);
 
        /* create our context */
        process_boot_option_queue(handler);
 
        /* create our context */
@@ -772,6 +785,11 @@ int device_handler_discover(struct device_handler *handler,
        device_handler_discover_context_commit(handler, ctx);
 
 out:
        device_handler_discover_context_commit(handler, ctx);
 
 out:
+       status->message = talloc_asprintf(status,"Processing %s complete\n",
+                               dev->device->id);
+       boot_status(handler, status);
+
+       talloc_free(status);
        talloc_free(ctx);
 
        return 0;
        talloc_free(ctx);
 
        return 0;
@@ -782,6 +800,13 @@ int device_handler_dhcp(struct device_handler *handler,
                struct discover_device *dev, struct event *event)
 {
        struct discover_context *ctx;
                struct discover_device *dev, struct event *event)
 {
        struct discover_context *ctx;
+       struct boot_status *status;
+
+       status = talloc_zero(handler, struct boot_status);
+       status->type = BOOT_STATUS_INFO;
+       status->message = talloc_asprintf(status, "Processing dhcp event on %s",
+                               dev->device->id);
+       boot_status(handler, status);
 
        /* create our context */
        ctx = device_handler_discover_context_create(handler, dev);
 
        /* create our context */
        ctx = device_handler_discover_context_create(handler, dev);
@@ -791,6 +816,11 @@ int device_handler_dhcp(struct device_handler *handler,
 
        device_handler_discover_context_commit(handler, ctx);
 
 
        device_handler_discover_context_commit(handler, ctx);
 
+       status->message = talloc_asprintf(status,"Processing %s complete\n",
+                               dev->device->id);
+       boot_status(handler, status);
+
+       talloc_free(status);
        talloc_free(ctx);
 
        return 0;
        talloc_free(ctx);
 
        return 0;
@@ -801,6 +831,12 @@ int device_handler_conf(struct device_handler *handler,
                struct discover_device *dev, struct pb_url *url)
 {
         struct discover_context *ctx;
                struct discover_device *dev, struct pb_url *url)
 {
         struct discover_context *ctx;
+       struct boot_status *status;
+
+       status = talloc_zero(handler, struct boot_status);
+       status->type = BOOT_STATUS_INFO;
+       status->message = talloc_asprintf(status, "Processing user config");
+       boot_status(handler, status);
 
         /* create our context */
         ctx = device_handler_discover_context_create(handler, dev);
 
         /* create our context */
         ctx = device_handler_discover_context_create(handler, dev);
@@ -810,6 +846,11 @@ int device_handler_conf(struct device_handler *handler,
 
         device_handler_discover_context_commit(handler, ctx);
 
 
         device_handler_discover_context_commit(handler, ctx);
 
+       status->message = talloc_asprintf(status,
+                               "Processing user config complete");
+       boot_status(handler, status);
+
+       talloc_free(status);
         talloc_free(ctx);
 
         return 0;
         talloc_free(ctx);
 
         return 0;
@@ -1082,6 +1123,20 @@ static void device_handler_reinit_sources(struct device_handler *handler)
                        handler->dry_run);
 }
 
                        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;
 static bool check_existing_mount(struct discover_device *dev)
 {
        struct stat devstat, mntstat;
@@ -1155,6 +1210,13 @@ static int mount_device(struct discover_device *dev)
        if (!fstype)
                return 0;
 
        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);
 
        dev->mount_path = join_paths(dev, mount_base(),
                                        dev->device_path);
 
@@ -1167,7 +1229,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,
        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;
        if (!rc) {
                dev->mounted = true;
                dev->mounted_rw = false;
@@ -1209,6 +1272,7 @@ static int umount_device(struct discover_device *dev)
 
 int device_request_write(struct discover_device *dev, bool *release)
 {
 
 int device_request_write(struct discover_device *dev, bool *release)
 {
+       const char *fstype;
        int rc;
 
        *release = false;
        int rc;
 
        *release = false;
@@ -1219,25 +1283,48 @@ int device_request_write(struct discover_device *dev, bool *release)
        if (dev->mounted_rw)
                return 0;
 
        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);
        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;
                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;
 
        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)
 {
 }
 
 void device_release_write(struct discover_device *dev, bool release)
 {
+       const char *fstype;
+
        if (!release)
                return;
 
        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, "",
        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;
 }
 
        dev->mounted_rw = false;
 }