--- /dev/null
+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
--- /dev/null
+/* 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);
+ }
+ }
+}