Initial commit.
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 30 Jan 2015 10:58:52 +0000 (10:58 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 30 Jan 2015 10:58:52 +0000 (10:58 +0000)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
init.c [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..4348522
--- /dev/null
@@ -0,0 +1,7 @@
+*~
+*.ko
+
+/dev
+/init
+/initrd
+/sd*.img
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..a232ee6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,52 @@
+kver    = 3.19.0-0.rc5.git2.1.fc22.aarch64
+modules = virtio.ko virtio_ring.ko virtio_mmio.ko virtio_scsi.ko
+disks   = sda.img sdb.img sdc.img sdd.img sde.img sdf.img
+
+all:   initrd $(disks)
+
+initrd:        dev init $(modules)
+       ls -1d $^ | cpio -o -H newc | gzip -9 > $@
+
+dev:
+       rm -rf $@
+       mkdir $@
+
+%.ko:
+       find /lib/modules/$(kver) -name $@ -exec cp {} . \;
+
+init:  init.c
+       gcc -Wall -Werror -static $< -o $@
+
+%.img:
+       rm -f $@
+       truncate -s 1G $@
+
+clean:
+       rm -f $(disks) $(modules) init initrd
+
+kernel  = /boot/vmlinuz-$(kver)
+qemu    = qemu-system-aarch64
+
+run:   initrd $(disks)
+       $(qemu) \
+         -nodefconfig -nodefaults -display none \
+         -machine virt,accel=kvm \
+         -no-reboot \
+         -cpu host \
+         -m 1024 \
+         -kernel $(kernel) -initrd initrd \
+         -append 'panic=1 earlyprintk=pl011,0x9000000 ignore_loglevel console=ttyAMA0 no_timer_check printk.time=1' \
+         -serial stdio \
+         -device virtio-scsi-device,id=scsi \
+         -drive file=sda.img,cache=writeback,format=raw,if=none,id=sda \
+         -device scsi-hd,drive=sda \
+         -drive file=sdb.img,cache=writeback,format=raw,if=none,id=sdb \
+         -device scsi-hd,drive=sdb \
+         -drive file=sdc.img,cache=writeback,format=raw,if=none,id=sdc \
+         -device scsi-hd,drive=sdc \
+         -drive file=sdd.img,cache=writeback,format=raw,if=none,id=sdd \
+         -device scsi-hd,drive=sdd \
+         -drive file=sde.img,cache=writeback,format=raw,if=none,id=sde \
+         -device scsi-hd,drive=sde \
+         -drive file=sdf.img,cache=writeback,format=raw,if=none,id=sdf \
+         -device scsi-hd,drive=sdf
diff --git a/init.c b/init.c
new file mode 100644 (file)
index 0000000..4694818
--- /dev/null
+++ b/init.c
@@ -0,0 +1,173 @@
+/* Try to reproduce RHBZ#1184405.
+ * Note: needs to be linked statically.
+ * By Richard W.M. Jones <rjones@redhat.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <linux/fs.h>
+
+extern long init_module (void *, unsigned long, const char *);
+
+/* NB! Must match the number of disks in Makefile. */
+#define NR_SCSI_DISKS 6
+
+/* NB! Must match the module list in Makefile.  Also they must be
+ * in module dependency order.
+ */
+static const char *modules[] = {
+  "virtio.ko",
+  "virtio_ring.ko",
+  "virtio_mmio.ko",
+  "virtio_scsi.ko",
+  NULL
+};
+
+static void load_modules (void);
+static void make_devices (void);
+static void run_test (const char *dev);
+
+int
+main (int argc, char *argv[])
+{
+  int i;
+  char dev[] = "/dev/sda";
+  int child_pids[NR_SCSI_DISKS-1];
+
+  printf ("init: started\n");
+  load_modules ();
+
+  /* Really we should wait for the kernel to probe devices, but bleah. */
+  sleep (2);
+
+  make_devices ();
+
+  for (i = 0; i < NR_SCSI_DISKS-1; ++i) {
+    child_pids[i] = fork ();
+    if (child_pids[i] == -1) {
+      perror ("fork");
+      exit (EXIT_FAILURE);
+    }
+    if (child_pids[i] == 0) {   /* child */
+      dev[7] = 'a' + i + 1;     /* /dev/sd[b..] */
+      run_test (dev);
+      _exit (EXIT_SUCCESS);
+    }
+  }
+
+  run_test (dev);               /* /dev/sda test in parent */
+
+  for (i = 0; i < NR_SCSI_DISKS-1; ++i) {
+    waitpid (child_pids[i], NULL, 0);
+  }
+
+  printf ("init: parent process exiting\n");
+  exit (EXIT_SUCCESS);
+}
+
+static char buffer[BUFSIZ];
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+static void
+run_test (const char *dev)
+{
+  int fd;
+  uint64_t size;
+  ssize_t r;
+
+  printf ("init: testing %s\n", dev);
+  fflush (stdout);
+
+  fd = open (dev, O_RDONLY);
+  if (fd == -1) {
+    perror (dev);
+    _exit (EXIT_FAILURE);
+  }
+  if (ioctl (fd, BLKGETSIZE64, &size) == -1) {
+    perror ("ioctl: BLKGETSIZE64");
+    _exit (EXIT_FAILURE);
+  }
+
+  while (size > 0) {
+    r = read (fd, buffer, MIN (BUFSIZ, size));
+    if (r == -1) {
+      perror ("read");
+      _exit (EXIT_FAILURE);
+    }
+    size -= r;
+  }
+
+  if (close (fd) == -1) {
+    perror ("close");
+    _exit (EXIT_FAILURE);
+  }
+
+  printf ("init: test of %s finished successfully\n", dev);
+  fflush (stdout);
+}
+
+/* Originally taken from supermin's init.c */
+static void
+load_modules (void)
+{
+  size_t i;
+  int fd;
+  struct stat statbuf;
+  size_t size;
+  ssize_t r;
+
+  for (i = 0; modules[i] != NULL; ++i) {
+    printf ("init: loading module %s\n", modules[i]);
+
+    fd = open (modules[i], O_RDONLY);
+    if (fd == -1) {
+      perror (modules[i]);
+      exit (EXIT_FAILURE);
+    }
+    if (fstat (fd, &statbuf) == -1) {
+      perror (modules[i]);
+      exit (EXIT_FAILURE);
+    }
+    char buf[size = statbuf.st_size];
+    while (size > 0) {
+      r = read (fd, buf, size);
+      if (r == -1) {
+        perror ("read");
+        exit (EXIT_FAILURE);
+      }
+      size -= r;
+    }
+    close (fd);
+
+    if (init_module (buf, statbuf.st_size, "") != 0) {
+      fprintf (stderr, "insmod: ");
+      perror (modules[i]);
+      exit (EXIT_FAILURE);
+    }
+  }
+}
+
+/* Much less trouble than udev! */
+static void
+make_devices (void)
+{
+  int i;
+  char dev[] = "/dev/sda";
+
+  printf ("init: creating device nodes\n");
+
+  for (i = 0; i < NR_SCSI_DISKS; ++i) {
+    dev[7] = 'a' + i;
+    if (mknod (dev, S_IFBLK, makedev (8, 16*i)) == -1) {
+      perror (dev);
+      exit (EXIT_FAILURE);
+    }
+  }
+}