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,
};
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;
}
/*
struct discover_boot_option *opt)
{
const struct config *config;
- const char *dev_str;
- unsigned int i;
config = config_get();
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;
}
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);
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;
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);
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;
int device_request_write(struct discover_device *dev, bool *release)
{
+ const char *fstype;
int rc;
*release = false;
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;
}