Testing With Loopback Devices

Loopback devices are really cool.

The concept is simple enough: take a file, and mount it like it was a block device. What good is that? Let me tell you a story.

I'm writing a small web application that accepts file uploads. The web server layer handles incoming uploads by storing them on-disk, in a temporary area, like /tmp. The application verifies some pieces of the request (mostly related to database state and API headers) and then tries to move the uploaded file out of /tmp and into /srv/data/foo/bar

Works great in my local development environment. Fails miserably in production.

Turns out, the last bit of the process uses a UNIX hard link (the kind you get when you forget the -s in ln -s). My dev environment only has one filesystem on one device, so hard-linking from /tmp to to /srv is no big deal. Not so in production.

Since I'm not about to re-partition my dev environment, I need a way of testing cross-device uploads. Enter Loopback Devices.

To get started, build out a blank file using the venerable dd utility:

$ dd if=/dev/zero of=disk.dev bs=4096 count=10240

Now, we need to bind a loopback device to our device file. First find out if there are any loopback devices in use already:

$ sudo losetup -f
/dev/loop0
$ sudo losetup /dev/loop0 disk.dev
$ sudo losetup /dev/loop0
/dev/loop0: [0802]:3300012 (/path/to/disk.dev)

Note: your output may vary.

Next up, we need to create a filesystem on our loopback device. I use ext3 because it's easy and well-supported, but you can use whatever you want and/or need.

$ sudo mke2fs -j /dev/loop0

Finally, mount it (in this case, to a new directory):

$ sudo mkdir /mnt/vfs
$ sudo mount /dev/loop0 /mnt/vfs

Armed with this new trick, you can emulate any number of different filesystems, cross-device fragmentation, multi-mount environments and more. With a properly outfitted test environment (a little sudo, filesystem sandboxing, etc.) you can even write automated unit tests that take advantage of this.

When you're all done, and want to cleanup, just unmount the device and detach the loopback device:

$ sudo umount /mnt/vfs
$ sudo losetup -d /dev/loop0

Happy Hacking!

James (@iamjameshunt) works on the Internet, spends his weekends developing new and interesting bits of software and his nights trying to make sense of research papers.

Currently working on Rook.