Richard W.M. Jones
2012-Jun-12 17:12 UTC
[Libguestfs] [PATCH] Add virtio-scsi support to febootstrap.
This patch is the minimum possible to add virtio-scsi support to febootstrap. Problem: SCSI devices are detected asynchronously after the Linux kernel module is loaded. The usual solutions to this involve scsi_wait_scan (deprecated apparently) or udev. However febootstrap doesn't use udev, and adding it is a ton of work with a very uncertain outcome. So the minimum possible change is to have libguestfs pass in the appliance device on the Linux command line (eg. root=/dev/sdb) and then busy-wait until it becomes available in the initramfs. Rich.
Richard W.M. Jones
2012-Jun-12 17:12 UTC
[Libguestfs] [PATCH] init: Add 'root=...' parameter to specify the appliance.
From: "Richard W.M. Jones" <rjones at redhat.com> This is required when using virtio-scsi with libguestfs. --- helper/init.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/helper/init.c b/helper/init.c index a1887a0..19e8948 100644 --- a/helper/init.c +++ b/helper/init.c @@ -1,5 +1,5 @@ /* febootstrap-supermin-helper reimplementation in C. - * Copyright (C) 2009-2011 Red Hat Inc. + * Copyright (C) 2009-2012 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,7 @@ #include <errno.h> #include <fcntl.h> #include <dirent.h> +#include <time.h> #include <sys/types.h> #include <sys/mount.h> #include <sys/stat.h> @@ -68,9 +69,11 @@ static const char *moderror(int err) static void mount_proc (void); static void print_uptime (void); +static void read_cmdline (void); static void insmod (const char *filename); static void show_directory (const char *dir); +static char cmdline[1024]; static char line[1024]; int @@ -86,6 +89,8 @@ main () #endif "\n"); + read_cmdline (); + /* Create some fixed directories. */ mkdir ("/dev", 0755); mkdir ("/root", 0755); @@ -121,23 +126,54 @@ main () } fclose (fp); - /* Look for the ext2 filesystem device. It's always the last - * one that was added. - * XXX More than 25 devices? + /* Look for the ext2 filesystem device. It's always the last one + * that was added. Modern versions of libguestfs supply the + * expected name of the root device on the command line + * ("root=/dev/..."). For virtio-scsi this is required, because we + * must wait for the device to appear after the module is loaded. */ - char path[] = "/sys/block/xdx/dev"; - char class[3] = { 'v', 's', 'h' }; - size_t i, j; - fp = NULL; - for (i = 0; i < sizeof class; ++i) { - for (j = 'z'; j >= 'a'; --j) { - path[11] = class[i]; - path[13] = j; + char *root, *path; + size_t len; + root = strstr (cmdline, "root="); + if (root) { + root += 5; + if (strncmp (root, "/dev/", 5) == 0) + root += 5; + len = strcspn (root, " "); + root[len] = '\0'; + + asprintf (&path, "/sys/block/%s/dev", root); + + long delay_ns = 250000; + while (delay_ns <= 2000000000) { fp = fopen (path, "r"); if (fp != NULL) goto found; + + struct timespec t; + t.tv_sec = delay_ns / 1000000000; + t.tv_nsec = delay_ns % 1000000000; + nanosleep (&t, NULL); + delay_ns *= 2; + } + } + else { + path = strdup ("/sys/block/xdx/dev"); + + char class[3] = { 'v', 's', 'h' }; + size_t i, j; + fp = NULL; + for (i = 0; i < sizeof class; ++i) { + for (j = 'z'; j >= 'a'; --j) { + path[11] = class[i]; + path[13] = j; + fp = fopen (path, "r"); + if (fp != NULL) + goto found; + } } } + fprintf (stderr, "febootstrap: no ext2 root device found\n" "Please include FULL verbose output in your bug report.\n"); @@ -313,6 +349,24 @@ print_uptime (void) fprintf (stderr, "febootstrap: uptime: %s", line); } +/* Read /proc/cmdline into cmdline global (or at least the first 1024 + * bytes of it). + */ +static void +read_cmdline (void) +{ + FILE *fp = fopen ("/proc/cmdline", "r"); + if (fp == NULL) { + perror ("/proc/cmdline"); + return; + } + + fgets (cmdline, sizeof cmdline, fp); + fclose (fp); + + fprintf (stderr, "febootstrap: cmdline: %s", cmdline); +} + /* Display a directory on stderr. This is used for debugging only. */ static char dirtype (int dt) -- 1.7.10.1
Apparently Analagous Threads
- [PATCH supermin 0/2] Allow an alternate libc to be used for init.
- [PATCH supermin v2] init: Support root=UUID=... to specify the appliance disk by volume UUID.
- [PATCH supermin 0/3] Require root= parameter, refactor init.
- [PATCH supermin] init: Delete initramfs files before chrooting into the appliance.
- [PATCH 1/3] febootstrap/helper/init: make sure /proc is mounted into chroot.