X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=discover%2Fdevice-handler.c;h=d95a37cb0c7c41ae420001d4c227cfa012c33b2f;hp=fd6f1d3091618f64e1a309817b7c2e28923c0b38;hb=120855d64d783aa3b3b0af23923da0169319c338;hpb=d3e95283e69d3099fe9f36e56be1f645f565c843 diff --git a/discover/device-handler.c b/discover/device-handler.c index fd6f1d3..d95a37c 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -40,8 +40,7 @@ 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, }; @@ -462,11 +461,27 @@ static bool ipmi_device_type_matches(enum ipmi_bootdev ipmi_type, 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; - const char *dev_str; - unsigned int i; config = config_get(); @@ -498,25 +511,17 @@ static enum default_priority default_option_priority( 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; } @@ -750,8 +755,16 @@ int device_handler_discover(struct device_handler *handler, struct discover_device *dev) { struct discover_context *ctx; + struct boot_status *status; 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 */ @@ -772,6 +785,11 @@ int device_handler_discover(struct device_handler *handler, 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; @@ -782,6 +800,13 @@ int device_handler_dhcp(struct device_handler *handler, 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); @@ -791,6 +816,11 @@ int device_handler_dhcp(struct device_handler *handler, 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; @@ -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 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); @@ -810,6 +846,11 @@ int device_handler_conf(struct device_handler *handler, 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; @@ -843,7 +884,7 @@ void device_handler_boot(struct device_handler *handler, if (handler->pending_boot) boot_cancel(handler->pending_boot); - platform_finalise_config(); + platform_pre_boot(); handler->pending_boot = boot(handler, opt, cmd, handler->dry_run, boot_status, handler); @@ -1082,6 +1123,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 +1210,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 +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, - MS_RDONLY | MS_SILENT, ""); + MS_RDONLY | MS_SILENT, + fs_parameters(MS_RDONLY, fstype)); 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) { + const char *fstype; int rc; *release = false; @@ -1219,25 +1283,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; }