Booting UML Successfully


The problem was that we didn't tell UML what its root device was. This is an important special case of a more general property of UMLits hardware is configured on the fly. In contrast to a physical system, whose hardware is fixed, a virtual system can be different every time it is booted. So, it expects to be told, either on the command line or later via the mconsole interface, what hardware it possesses.

Here, we will configure UML on the command line. The first order of business is to give it a proper root device so that it has something it can boot. As I mentioned earlier, UML devices are virtual and constructed from host resources. Specifically, UML's disks are generally (but not always, as we will see later) files in the host's filesystem.

For example, here is the filesystem we will boot:

host% ls -l ~/roots/debian_22 -rw-rw-r--  1 jdike jdike 1074790400 Jan 27 18:31 \       /home/jdike/roots/debian_22


One obvious thing here is that the filesystem image is very large. file will tell us a bit more about it:

host% file ~/roots/debian_22 /home/jdike/roots/debian_22: Linux rev 1.0 ext2 filesystem data


This tells us that the data in this file is an ext2 filesystem image. In other words, we can loopback-mount it and see that it contains a full filesystem:

host# mount ~/roots/debian_22 ~/mnt -o loop host% ls ~/mnt bfs boot    dev floppy initrd lib        mnt  root tmp var bin cdrom   etc home   kernel lost+found proc sbin usr


In fact, when mounting this as its root filesystem, UML will do something very similar to a loopback mount. The UML block driver operates by calling read and write on this file on the host, analogous to a block driver on the host doing reads and writes on a physical disk.

The loopback driver on the host is doing exactly the same thing, except from within the host kernel, rather than from a process, where the UML block driver is.

So, in order to provide this file to UML as its root device, we need to tell the UML block driver (the ubd or UML Block Device driver) to attach itself to it. This is done with this option:

ubda=~/roots/debian_22


This is the easiest way to initialize a UML block device, and it simply says that the first UML block device is to be attached to the file ~/roots/debian_22. Internally, UML tells the kernel initialization code to use the ubda device as its default root device (this can be overridden by specifying a different device with the root= switch, as the panic mes-sage suggested).

I'm going to add one more option to the command line to make the virtual machine's configuration more explicit:

mem=128M


This makes UML believe it has 128MB of physical memory but does not actually allocate 128MB on the host. Rather, this creates a 128MB sparse file on the host. Being sparse, this file will occupy very little space until data starts being written to it. As the UML instance uses its memory, it will start putting data in the memory backed by this file. As that happens, the host will start allocating memory to hold that data. Since the file is fixed in size, the UML instance is limited to that amount of memory. Its memory consumption will approach this limit asymptotically as it reads file data from its own disks and caches it in its memory.

Since the host will be allocating memory for the UML instance dynamically, as needed, the actual consumption will be less than the maximum for a time. This conserves memory, making it possible to run a greater number of not-too-active UML instances than would be possible otherwise.

The host memory consumption will, in this case, be at most 128MB. Even if the UML instance is fully using its memory, the host memory consumption may be less, as it may have swapped out some of the UML memory. The UML instance, like any other process that has been swapped out, will be unaware of this and will use its memory as though it is present in the host's memory. The host kernel is responsible for swapping data back in as needed in order to maintain this illusion.

The UML instance will also swap if its workload exceeds its physical memory. This is entirely independent from the host swapping the UML instance's memory. Each system will swap when it needs more memory, so if the host is short of memory and the UML instance has plenty, the host will swap and the UML instance won't. Conversely, if the UML instance is short of memory and the host isn't, the UML instance will swap and the host won't. The case where both are swapping at the same time is interesting and can lead to pathological performance problems. [4]

[4] Consider the case where both the host and the UML instance are swapping at the same time. They may both choose the same page to swap out. If the host swaps it out first, then when the UML instance swaps it, the host will need to read it back from disk so that the UML instance can write it to its own swap device. This will cause the page to be read and written a total of three times, when only once was desirable. This will increase the I/O load on the host at a time when it is already under stress. Solutions for this sort of situation are under investigation and will be described in Chapter 10.

So, the UML command ends up looking like this:

~/linux mem=128M ubda=/home/jdike/roots/debian_22


Figure 2.3 shows the results.

Figure 2.3. Output from the first successful boot of UML

~/linux/2.6/2.6.10 22849: ./linux mem=128M ubda=/home/jdike/roots/debian_22 Checking for /proc/mm...not found Checking for the skas3 patch in the host...not found Checking PROT_EXEC mmap in /tmp...OK Linux version 2.6.11-rc1-mm1 (jdike@tp.user-mode-linux.org) (gcc version 3.3.2      20031022 (Red Hat Linux 3.3.2-1)) #83 Thu Jan 27 12:16:00 EST 2005 Built 1 zonelists Kernel command line: mem=128M ubda=/home/jdike/roots/debian_22 root=98:0 PID hash table entries: 1024 (order: 10, 16384 bytes) Dentry cache hash table entries: 32768 (order: 5, 131072 bytes) Inode-cache hash table entries: 16384 (order: 4, 65536 bytes) Memory: 126720k available Mount-cache hash table entries: 512 (order: 0, 4096 bytes) Checking for host processor cmov support...Yes Checking for host processor xmm support...No Checking that ptrace can change system call numbers...OK Checking syscall emulation patch for ptrace...missing Checking that host ptys support output SIGIO...Yes Checking that host ptys support SIGIO on close...No, enabling workaround Checking for /dev/anon on the host...Not available (open failed with errno 2) NET: Registered protocol family 16 mconsole (version 2) initialized on /home/jdike/.uml/igpn9r/mconsole VFS: Disk quotas dquot_6.5.1 Dquot-cache hash table entries: 1024 (order 0, 4096 bytes) io scheduler noop registered io scheduler anticipatory registered io scheduler deadline registered io scheduler cfq registered NET: Registered protocol family 2 IP: routing cache hash table of 512 buckets, 4Kbytes TCP established hash table entries: 8192 (order: 4, 65536 bytes) TCP bind hash table entries: 8192 (order: 3, 32768 bytes) TCP: Hash tables configured (established 8192 bind 8192) NET: Registered protocol family 1 NET: Registered protocol family 17 Initialized stdio console driver Console initialized on /dev/tty0 Initializing software serial port version 1  ubda: unknown partition table VFS: Mounted root (ext2 filesystem) readonly. line_ioctl: tty0: ioctl KDSIGACCEPT called INIT: version 2.78 booting Activating swap... Checking root file system... Parallelizing fsck version 1.18 (11-Nov-1999) /dev/ubd0: clean, 9591/131328 files, 64611/262144 blocks Calculating module dependencies... depmod: get_kernel_syms: Function not      implemented done. Loading modules: cat: /etc/modules: No such file or directory modprobe: Can't open dependencies file /lib/modules/2.6.11-rc1-mm1/modules.dep      (No such file or directory) Checking all file systems... Parallelizing fsck version 1.18 (11-Nov-1999) Setting kernel variables. Mounting local filesystems... mount: devpts already mounted on /dev/pts none on /tmp type tmpfs (rw) Setting up IP spoofing protection: rp_filter. Configuring network interfaces: done. Setting the System Clock using the Hardware Clock as reference... line_ioctl: tty1: unknown ioctl: 0x4b50 hwclock is unable to get I/O port access: the iopl(3) call failed. System Clock set. Local time: Thu Jan 27 18:51:28 EST 2005 Cleaning: /tmp /var/lock /var/run. Initializing random number generator... done. Recovering nvi editor sessions... done. INIT: Entering runlevel: 2 Starting system log daemon: syslogd syslogd: /dev/xconsole: No such file or      directory  klogd. Starting portmap daemon: portmap. Starting NFS common utilities: statd lockdlockdsvc: Function not implemented . Starting internet superserver: inetd. Starting MySQL database server: mysqld. Not starting NFS kernel daemon: No exports. Starting OpenBSD Secure Shell server: sshd. Starting web server: apache. /usr/sbin/apachectl start: httpd started Debian GNU/Linux 2.2 usermode tty0 usermode login:

This is much more interesting than the last attempt. We get to see the filesystem booting. Note that it's almost exactly the same as it would be if the same filesystem were booted on the host. The underlying virtual machine shows through in only a couple of places. One is when the root filesystem is checked [5]:

[5] The fsck message refers to /dev/ubd0 rather than /dev/ubda. Devices can be specified with either numbers or letters. Using letters is generally favored since it is similar to current practice with other drivers, such as naming IDE disks hda, hdb, and so on. It also makes the use of multiple ubd devices within UML less confusing. There's less expectation that ubdb on the command line corresponds to minor number 1 inside the UML instance, as the use of ubd1 does. In fact, ubdb has minor number 16 (to allow for partitions on ubda). The one case where numbers are needed is when you are plugging a large number of disks into a UML instance. There is no letter equivalent of ubd512, so you'd have to use a number to describe this device.

/dev/ubd0: clean, 9591/131328 files, 64611/262144 blocks


where we see the UML device name, /dev/ubd0, rather than hda1 or sda1 as on a physical machine.

The other is when the boot scripts try to synchronize the internal kernel clock with the system's hardware clock:

Setting the System Clock using the Hardware Clock as reference... line_ioctl: tty1: unknown ioctl: 0x4b50 hwclock is unable to get I/O port access: the iopl(3) call \       failed.


The UML serial line driver is complaining about an ioctl it doesn't implement, and the hwclock program inside UML is complaining that it tried to execute the iopl instruction and failed. These are both symptoms of hwclock trying different methods of accessing the hardware system clock and failing because the device doesn't exist in UML. The UML kernel does have access to a clock, but it is not one that hwclock will recognize. Rather, it is simply a call to the host's gettimeofday.

After that, you'll notice that a relatively small number of services are started, but they do include such things as NFS, MySQL, and Apache. All of these run just as they would on a physical machine. This boot process took about 5 seconds on my laptop, demonstrating one of the conveniences of UMLthe ability to quickly create and destroy virtual machines.



User Mode Linux
User Mode Linux
ISBN: 0131865056
EAN: 2147483647
Year: N/A
Pages: 116
Authors: Jeff Dike

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net