[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libguestfs] [PATCH] init: Add 'root=...' parameter to specify the appliance.



From: "Richard W.M. Jones" <rjones 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]