Running the Raspberry Pi via USB

Contents

  1. Introduction
  2. Requirements
  3. Benchmarking
  4. Installation
  5. Modifying the boot record
  6. Verifying boot location
  7. Grow the root filesystem to fill the USB drive

Introduction

Running the Raspberry Pi from a USB storage device has many advantages; mainly speed and reliability.

SD Cards have a limited read and write cycle, so when hosting a site utilising a MySQL database, soon you will begin to experience disk corruptions and failures. USB storage devices provide a cheap and reliable alternative.

Requirements

The Raspberry Pi is not yet capable of booting directly from a USB storage device. You will still need an SD card to store the boot instructions to tell the Raspberry Pi to launch the OS from the USB storage device.

You will need the standard Raspbian OS image and can download this from the official Raspberry Pi website. Alternatively, you can use your own image if you have one.

You will finally require knowledge of SSH and using a terminal connection like Putty and I would recommend reading the article creating a Raspberry Pi web server and more specifically the command line and text editor.

Benchmarking

It does not matter how good your SD card is, chances are that it the will not beat the I/O performance of a USB storage device. Execute the following code for a quick benchmark:

dd if=/dev/zero of=/tmp/out bs=1M count=400

After a short while, it should reveal results similar to the following:

419430400 bytes (419 MB) copied, 94.3303 s, 4.4 MB/s

You can try running the same test after reaching the end of this article and I am sure you will have improved results:

419430400 bytes (419 MB) copied, 29.9851 s, 14.0 MB/s

Installation

The Windows operating system does not have a Terminal connection, therefore I have written this tutorial so that all configuration is executed via the Raspberry Pi.

The article creating a Raspberry Pi web server detailed how to copy the Raspbian image to an SD card. You will still need to do this so that we can boot Raspbian to make all configuration changes. You will want to copy the image you may have created in Creating your own image from following the above mentioned article.

The first step of the process is identical, but instead of copying the image to an SD card you would copy the image to your USB storage device in exactly the same way. eLinux.org details how to install the image using Win32DisIkmager.exe.

Modifying the boot record

This is done using Windows, but the process is identical on any operating system.

Your SD card will have a 60MB FAT32 or FAT partition containing all files required for booting. This is known as the boot partition and is all that is required for booting the Raspberry Pi.

Within this partition, locate the file cmdline.txt and open it in a text editor. This file should contain the following:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

Modify the above code to:

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/sda2 rootfstype=ext4 elevator=deadline rootwait

When writing the Raspbian image to the SD card; the SD card was given the label mmcblk0. The boot partition is labeled mmcblk0p1 and the EXT4 partition was created for the operating system labeled mmcblk0p2 and is known as the root partition.

The change you have made above was to change the boot record to point the root location to the USB storage device. Similar to the SD card; the USB storage device has been given the label sda, the boot partition is labeled sda1 and the root partition is labeled sda2.

Save the file and close your text editor.

Optionally, open the file /etc/fstab and change the device label of the root filesystem to generic /dev/root. Though this step is not required, it keeps things clean.

Insert your SD card and USB storage device into the Raspberry Pi and boot the device.

If all is well, /dev/sda2 should be the location of the USB storage device when the Pi boots, and thus it should attempt to use that location as root. The rootwait parameter is important as it will make the boot process hang until the USB storage device is recognised. Without it, the Pi may complain that the location does not exist.

Troubleshooting

Please note that you will not loose any data if things go wrong, as you simply have to revert file /boot/cmdline.txt on a computer to boot from the SD card again.

Take care if you connect multiple storage devices to the Raspberry PI's USB port, this might mess up the partition labeling. To be on the safe side, remove any USB storage devices other than the flash disk on booting.

If you experience error messages like usb 1-1.3: reset high-speed USB device number ... using dwc_otg, your USB storage device might consume more power than a single USB port of the Raspberry PI might provide.

Verifying boot location

Launch an SSH connection to your Raspberry Pi. The first thing we are going to do is get information for connected storage devices. To do this run the following command:

sudo fdisk -l

This should display something similar to:

Disk /dev/sda: 8086 MB, 8086618112 bytes
249 heads, 62 sectors/track, 1023 cylinders, total 15794176 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00014d34

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/sda2          122880     7741439     3809280   83  Linux

Disk /dev/mmcblk0: 3963 MB, 3963617280 bytes
4 heads, 16 sectors/track, 120960 cylinders, total 7741440 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00014d34

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          122880     7741439     3809280   83  Linux

Alternatively, you could run the command sudo cat /proc/partitions for less detailed partition information:

major minor  #blocks  name

   8        0    7897088 sda
   8        1      57344 sda1
   8        2    3809280 sda2
 179        0    3870720 mmcblk0
 179        1      57344 mmcblk0p1
 179        2    3809280 mmcblk0p2

The list of attached disks will show up with their information. Disk and partition labels should be as described earlier.

Next we're going to unmount the SD card. To get a list of "mounted" devices enter the command mount or sudo cat /proc/mounts:

/dev/root on / type ext4 (rw,noatime,data=ordered)
devtmpfs on /dev type devtmpfs (rw,relatime,size=240516k,nr_inodes=60129,mode=755)
tmpfs on /run type tmpfs (rw,nosuid,noexec,relatime,size=49756k,mode=755)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
tmpfs on /run/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=99500k)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)

The listing shows the device (such as a disk partition), the mount point (where you access the files), the filesystem type and the mount options.

The first line of this example shows the /dev/root partition mounted as /, with the filesystem type ext4. The partition is mounted with two options beyond the scope of this article. You can use the command sudo blkid /dev/sda1 against a partition to return some useful details.

To unmount the SD card partitions, enter the following commands:

sudo umount /dev/mmcblk0p1
sudo umount /dev/mmcblk0p2
sudo umount /dev/mmcblk0

If all is well, your Raspberry Pi should still be working as normal. You can even take out your SD card from the Raspberry Pi, but it will still be required when you need to reboot.

Grow the root filesystem to fill the USB drive

The included script in the rasp-config tries to grow the SD card partition, even though the root partition is now on a USB drive. At least that's what I think it does? This isn't essential, but if you have the extra space on a USB storage device, why not use it all?

Enter the following command to start fdisk:

sudo fdisk /dev/sda

Then press p and enter to see the partitions. There should only be 2.

What we're going to do now is delete the Linux partition, but before we do this, we make a note of the start position for the Linux partition sda2. Press d and then when prompted type 2 and then hit enter. This will delete the partition.

Now we're going to resize the main partition by creating a new partition, and make it large enough for the OS to occupy the full space available on the USB storage device. To do this type n to create a new partition, when prompted to give the partition type, press p for primary. Then it will ask for a partition number, press 2 and hit enter.

You will now be prompted for the first sector for the new partition. Enter the start number from the earlier step (the Linux partition).

Next you will be prompted for the last sector you can just hit enter to accept the default which will utilize the remaining disk space.

Now type w to commit the changes. You will see a message about the Kernel using some table and what not, just ignore this and type sudo reboot to reboot the system.

Once the system has reboot and you are back at the commandline enter the following command to resize the partition:

sudo resize2fs /dev/sda2

Note: this can take a long time (depending on the size and speed of the storage device) be patient and let it finish so you do not mess up the file system and have to start from scratch. Once done, reboot the system again.

You can now verify that the system is using the full capacity of the USB storage device by entering the following command:

df -h

Why This Works?

The real magic here is that you delete the root partition, then recreate it using the original start sector before writing the data to the disk. As a result you don't erase the existing data from the root partition. You then resize (which is safe to run on a mounted disk) the file system to use all the space in the new root partition.

Alternatively fix and use Raspi-config

Try running the following code:

cp /usr/bin/raspi-config ~
sed -i 's/mmcblk0p2/sda2/' ~/raspi-config                                                                             
sed -i 's/mmcblk0/sda/' ~/raspi-config
sudo ~/raspi-config

You could also try reducing the sed to a single invocation:

sed -E 's/mmcblk0p?/sda/'

This version will replace mmcblk0 to sda and mmcblk0p2 to sda2 in one line. It will also replace mmcblk0p1 to sda1 and so on.

Then choose the resize root partition. I have not tested this version.