Use and Abuse of UML Block Devices


First, let's look at ways to copy data into a UML instance from the host without using the network. We will use UML block devices for this, tying them to files containing the data that we want to access inside the instance. Until now, we have used UML block devices only for filesystems. However, like physical disks, block devices can contain any data whatsoever, and that data can be accessed by anything that understands its format. Putting a filesystem on a disk formats the disk's data in a particular way that can be understood by the filesystem that will mount it. However, if you don't need to mount the disk as a filesystem, the data on it can be anything you want.

For example, let's say that we want to copy a directory from the host to the instance. In this example, we will create a tar file on the host containing the directory, attach a UML block device to the file, and untar the directory inside the instance. We saw this in Chapter 3, but I will go into more depth here.

To start, we need the tar file. I will use the host's /etc here:

host% tar cpf etc.tar /etc host% ls -l etc.tar -rw-rw-rw- 1  jdike jdike 25149440 May 13 22:28 etc.tar


I ran tar as a normal user and got a bunch of errors from files I didn't have permission to read. That's fine for an example, but if you really wanted all those files, you would run tar as root to ensure that they all end up in the tar file.

At the end of the previous chapter, we shut down our UML instances, so if you don't have one running now, start one up.

We now have a 25MB file that we will turn into a UML block device, using uml_mconsole:

host% uml_mconsole debian config ubdb=etc.tar OK


This causes a second block device, /dev/ubdb, to come into existence inside our instance. Rather than mounting it as a filesystem, as we have done before, we will treat it as a tape drive. These days, tar is often used to archive data in files and to retrieve files from those files. It used to be more common to use tar to write the data directly to a device, usually a tape drive. We are going to treat our new block device similarly and tar the directory off the device directly.

First, let's go to the UML, see if /dev/ubdb contains something that tar recognizes, and ask it to show us what's on the device:

UML# tar tf /dev/ubdb | head etc/ etc/sysconfig/ etc/sysconfig/network-scripts/ etc/sysconfig/network-scripts/ifdown-aliases etc/sysconfig/network-scripts/ifcfg-lo etc/sysconfig/network-scripts/ifdown etc/sysconfig/network-scripts/ifdown-ipsec etc/sysconfig/network-scripts/ifdown-ippp etc/sysconfig/network-scripts/ifup-aliases etc/sysconfig/network-scripts/ifdown-ipv6


That looks a lot like a /etc, so let's pull it off for real:

UML# tar xpf /dev/ubdb


Now you will see an /etc directory in your current directory. If you run ls on it, you will see that it is, in fact, the same as what you copied on the host.

This should make it clear that the data on a UML block device can be any format and that all you need to pull the data off the device inside the UML instance is a utility that understands the format.

Let's pull the data off in a way that assumes nothing about the format. We will just make a raw copy of the device in a file inside UML and see that it contains what we expect. To start, remove the /etc directory we just made:

UML# rm -rf etc


Now, let's use dd to copy the device into a file:

UML# dd if=/dev/ubdb of=etc.tar 49120+0 records in 49120+0 records out


We can check whether tar still thinks it contains a copy of /etc:

UML# tar xpf etc.tar


That finishes successfully, and you can again check with ls that you extracted the same directory as before.

As a final example using this tar file, we will compress the file before attaching it to a block device, and then uncompress and untar it inside UML. Again, let's remove our copy of /etc :

UML# rm -rf etc


Now, back on the host, we compress the tar file and attach it to UML block device 2:

host% gzip etc.tar host% uml_mconsole debian config ubdc=etc.tar.gz OK


Back inside the UML instance, we now uncompress the compressed tar file to stdout and pipe that into tar, hopefully extracting the same directory that we did before:

UML# gunzip -c < /dev/ubdc | tar xf -


Again, you can check that etc is the same as in the previous examples.

When copying files into UML using this method, you need to be careful about lengths. We are mapping a host file, which can be any length, onto a block device, which is expected to be a multiple of 512 bytes longthe size of a disk sector in Linux. Block devices are expected to contain sectors, with no bytes left over. To see how this affects files copied into UML, let's copy a single, odd-length file through a block device.

Locate a file on the host whose length is not an even multiple of 512 bytes.

On my system, /etc/passwd is suitable:

host% ls -l /etc/passwd -rw-r--r--  1 root root 1575 Dec 10 18:38 /etc/passwd


Let's attach this file to UML:

host% uml_mconsole debian config ubdd=/etc/passwd OK


Here's what we get when we copy it inside UML:

UML# dd if=/dev/ubdd of=passwd 4+0 records in 4+0 records out UML# ls -l passwd -rw-r--r--  1 root root 2048 May 13 23:48 passwd


Notice that the size changed. If you look at the file with a suitable utility, such as od, you will see that the extra bytes are all zeros.

There is a mismatch between a file with no size restrictions being mapped to a device that must be an even number of sectors. The UML block driver has to bridge this gap somehow. When it reaches the end of a host file and has read only a partial sector, it pads the sector with zeros and pretends that it read the entire thing. This is a necessary fiction in order to generally handle the end of a file, but it results in the block driver copying more data than it should.

To deal with this problem, we need to tell dd exactly how much data to copy. The UML block driver will still pad the last sector with zeros, but dd won't copy them.

My /etc/passwd is 1575 bytes long, so this is what we will tell dd to copy:

UML# dd if=/dev/ubdd of=passwd bs=1 count=1575 1575+0 records in 1575+0 records out UML# ls -l passwd -rw-r--r--  1 root root 1575 May 13 23:56 passwd


The bs=1 argument to dd tells it to copy data in units of a single byte, and the count argument tells it to copy 1575 of those units.

Now, the size is what we expect, and if you check the contents, you will see that they are, in fact, the same.

Some file formats are self-documenting in terms of their lengthit is possible to tell whether extra data has been added to the length of the file. tar and bzip files are two examplestar and bunzip2 can tell when they've reached the end of the data they are supposed to process, and bunzip2 will complain about the extra data. If you are copying data from a ubd device that is in one of these formats, you can use the device directly as the data source. You don't need to copy the correct number of bytes from the device into a file in order to recreate the original data.



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