6/13/2012

A bigger slice of Raspberry Pi


A bigger slice of Raspberry Pi

After getting the basics done in Slicing Into the Raspberry Pi prior post, this post addresses other advanced issues like expanding the filesystem to give you more room to store your files, and activating swap, which allows part of your SD card to act as virtual memory.

Expanding the Filesystem

The default layout of the partitions as shown in  Slicing Into the Raspberry Pi, is for a 2GB SDcard.

Below you see this layout for an 8GB device (7822 MB). The initial layout does not use all the space on the device. By default, the swap space isn't even used. See below, if you want to activate a swap space. 

To be able to use all the space, make note of the starting sector for the second partition. In this case it is: 157696, and this will be used as the starting sector for second partition when it is created with a larger size. The new second partition must start at the exact sector of your current partition.

Depending on storage capacity of your SD card, the ending sector for the second partition, the starting sector of the swap partition, and ending sector of the swap partition may vary. The example given is based upon an 8GB card. This simple Python script, suggested name partitions.py, can calculate the starting and ending sectors for your partitions. The following script is available for download at: https://raw.github.com/wrightrocket/PythonOnTheRaspberryPi/master/recommend_partitions.py


#!/usr/bin/python
'''
recommend_partitions.py
This module just does some simple calculations to help determine sectors to
use when updating a Debian image for Raspberry Pi.

Use these calculations at your own risk! Beware that modifying partitions on 
a device may result in a loss of data.
'''
DEFAULT_SWAP_SIZE = 383
BYTES_PER_SECTOR = 512
MIBI_BYTE = 1048576

def makeRecommendation(lastSector, swapMiBiSize=DEFAULT_SWAP_SIZE):
    lastSector -= 1
    swapSectors = swapMiBiSize * MIBI_BYTE / BYTES_PER_SECTOR
    firstSwapSector = lastSector - swapSectors
    lastRootSector = firstSwapSector - 1
    print "\nYou should have made note of the starting sector for partition 2.\n"
    print "The ending sector for partition 2 is: %s\n" % lastRootSector
    print "The starting sector for partition 3 is %s\n" % firstSwapSector
    print "The ending sector for partition 3 is: %s\n" % lastSector
    
def calcCardSize(lastSector):
    cardSize = lastSector * BYTES_PER_SECTOR / MIBI_BYTE
    if cardSize < 2000:
        print "\nYour card appears to be %s MiB which is less than 2000MB" % cardSize
        print "Check the value you entered, as this size cannot be expanded\n" 
        return None
    else:
        print "\nYour card appears to be %s MiB in size\n" % cardSize
        return cardSize
    
def getLastSector():
    print "From the output of fdisk -l enter the ending sector of your SD card"
    lastCardSector = raw_input("Last sector: ")
    if lastCardSector.isdigit():
        lastCardSector = long(lastCardSector)
        if calcCardSize(lastCardSector):
            print "How many MiB for the swap partition, or Enter for default (%s): " % DEFAULT_SWAP_SIZE
            mibiSwap = raw_input("Swap size: ")
            if mibiSwap.isdigit():
                makeRecommendation(lastCardSector, long(mibiSwap))
            elif mibiSwap == '':
                makeRecommendation(lastCardSector)
            else:
                print "The swap size must be entered as a number without commas"
    else:
        print "The last sector must be entered as a number without commas"
        print "From the output of fdisk -l enter the ending sector of your SD card"
            

if __name__ == "__main__":
    print "This program will calculate the sector numbers to use when"
    print "expanding the default Debian image for the Raspberry Pi.\n"
    getLastSector()

Here's what it looks like when your run the script with python recomment_partitions.py:


This program will calculate the sector numbers to use when
expanding the default Debian image for the Raspberry Pi.

From the output of fdisk -l enter the ending sector of your SD card
Last sector: 15278080

Your card appears to be 7460 MiB in size

How many MiB for the swap partition, or Enter for default (383): 
Swap size: 

You should have made note of the starting sector for partition 2.

The ending sector for partition 2 is: 14493694

The starting sector for partition 3 is 14493695

The ending sector for partition 3 is: 15278079


It will be number that you find when you do fdisk -l, or on some systems fdisk -cul, as well as the disk may not be /dev/sdb, but will be something like /dev/sdX. 

Both the second and third partition are about to be deleted and it is critical to note the starting sector of the second partition.
  • Shut down the Raspberry Pi and and insert your SDcard into your computer running Linux.
  • To view the partition table as root, and note the starting sector of the second partition.
    • root@host # fdisk -l # or fdisk -cul if the units are not in sectors by default
    • # #make note of the starting sector of the second partition

Disk /dev/sdb: 7822 MB, 7822376960 bytes
4 heads, 32 sectors/track, 119360 cylinders, total 15278080 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: 0x000ee283

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048      155647       76800    c  W95 FAT32 (LBA)
/dev/sdb2          157696     3414015     1628160   83  Linux
/dev/sdb3         3416064     3807231      195584   82  Linux swap / Solaris


Command (m for help): d
Partition number (1-4): 3

Command (m for help): d
Partition number (1-4): 2

Command (m for help): n
Partition type:
   p   primary (1 primary, 0 extended, 3 free)
   e   extended
Select (default p): p
Partition number (1-4, default 2): 
Using default value 2
First sector (155648-15278079, default 155648): 157696
Last sector, +sectors or +size{K,M,G} (157696-15278079, default 15278079): 14493694 # according

Command (m for help): n
Partition type:
   p   primary (2 primary, 0 extended, 2 free)
   e   extended
Select (default p): 
Partition number (1-4, default 3): 
Using default value 3
First sector (155648-15278079, default 155648): 14493695 # Last sector of previous +1 
Last sector, +sectors or +size{K,M,G} (15200001-15278079, default 15278079): 
Using default value 15278079


Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): 82
Changed system type of partition 3 to 82 (Linux swap / Solaris)

Command (m for help): p

Disk /dev/sdb: 7822 MB, 7822376960 bytes
241 heads, 62 sectors/track, 1022 cylinders, total 15278080 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: 0x000ee283

   Device Boot      Start         End      Blocks   Id  System

/dev/sdb1            2048      155647       76800    c  W95 FAT32 (LBA)
/dev/sdb2          157696    14493694     7167999+  83  Linux
/dev/sdb3        14493695    15278079      392192+  82  Linux swap / Solaris

(If all does not look good like above, then use q to quit without making changes)
Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

[root@rocket debian6-19-04-2012]# resize2fs  /dev/sdb2
resize2fs 1.41.14 (22-Dec-2010)
Resizing the filesystem on /dev/sdb2 to 1880288 (4k) blocks.
The filesystem on /dev/sdb2 is now 1880288 blocks long.

[root@rocket debian6-19-04-2012]# fsck -f /dev/sdb2
fsck from util-linux 2.20.1
e2fsck 1.41.14 (22-Dec-2010)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/sdb2: 65112/454720 files (0.2% non-contiguous), 429458/1880288 blocks
[root@rocket debian6-19-04-2012]# mkswap /dev/sdb3
Setting up swapspace version 1, size = 39032 KiB
no label, UUID=fcc0a8df-4ba3-4c72-83b9-ee9f84c285ee

Enabling the swapping to the SDcard

Mount the root filesystem and modify the /etc/fstab file to enable swap:

[root@rocket debian6-19-04-2012]# mount /dev/sdb2 /mnt
[root@rocket debian6-19-04-2012]# vi /mnt/etc/fstab
remove the # from the beginning of the line containing swap
[root@rocket debian6-19-04-2012]# umount /mnt

Put the card into the Raspberry Pi. After the system has booted, the swap space available and in use can be viewed with:
pi@raspi ~ $ sudo swapon -s

Resizing the Filesystem on the Raspberry Pi itself

It is possible to resize the partitions on the Raspberry Pi without having to move the SD card back to a desktop computer. If you have already resized the partitions by following the procedure above, then it is not necessary to do it again.

As an example of what I did. First, I deleted partitions 3, and 2. Next, I created a new partition with the original first sector of the second partition, and an ending sector appropriate for the size of the SD card (use above program to calculate). Then, I created a swap partition with starting sector sector using the ending sector + 1 of partition 2, and the default value of the end of the card.

pi@raspberrypi:~$ sudo fdisk -cu /dev/mmcblk0

Command (m for help): p

Disk /dev/mmcblk0: 7969 MB, 7969177600 bytes
241 heads, 62 sectors/track, 1022 cylinders, total 15278080 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: 0x000ee283

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            2048      155647       76800    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          157696     3414015     1628160   83  Linux
/dev/mmcblk0p3         3416064     3807231      195584   82  Linux swap / Solaris

Command (m for help): d 
Partition number (1-4): 3

Command (m for help): d
Partition number (1-4): 2

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First sector (155648-15564799, default 155648): 157696
Last sector, +sectors or +size{K,M,G} (157696-15564799, default 15564799): 14493694 

Command (m for help): n
Partition type:
   p   primary (2 primary, 0 extended, 2 free)
   e   extended
Select (default p): p
Partition number (1-4, default 3): 
Using default value 3
First sector (155648-15278079, default 155648): 14493695 # Last sector of previous +1 
Last sector, +sectors or +size{K,M,G} (15200001-15278079, default 15278079): 
Using default value 15278079

Command (m for help): t
Partition number (1-4): 3
Hex code (type L to list codes): 82
Changed system type of partition 3 to 82 (Linux swap / Solaris)


Command (m for help): p

Disk /dev/mmcblk0: 7822 MB, 7822376960 bytes
241 heads, 62 sectors/track, 1022 cylinders, total 15278080 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: 0x000ee283

   Device Boot      Start         End      Blocks   Id  System

/dev/mmcblk0p1       2048      155647       76800    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          157696    14493694     7167999+  83  Linux
/dev/mmcblk0p3        14493695    15278079      392192+  82  Linux swap / Solaris


Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.



  • pi@raspberrypi:~$ sudo reboot

After rebooting and logging in execute:
  • pi@raspberrypi:~$ sudo resize2fs /dev/mmcblk0p2
  • pi@raspberrypi:~$ sudo mkswap /dev/mmcblk0p3
  • pi@raspberrypi:~$ sudo vi /etc/fstab

Modify line containing swap by removing # from  beginning of the line  so the file reads:

/dev/mmcblk0p1  /boot           vfat    defaults        0       0
/dev/mmcblk0p3  none            swap    sw              0       0
  • pi@raspberrypi:~$ sudo reboot
Update: Someone asked me what to do if there partitions were set up with the first being boot, the second being swap, and the third being the root file system. While it would be difficult to adjust the size of the swap, it would be easy to expand the root file system.

First, you would do the sudo fdisk -l command to identify the starting sector of the third partition. Second, you would use sudo fdisk -cu /dev/mmcblk0 command to delete the third partition, and then create a new third partition with the same starting sector, and use the default last sector to use all the available space on the card. After saving changes with w, reboot the system. Finally, the file system would be resized with sudo resize2fs /dev/mmcblk0p3.






2 comments:

simon coleman said...

very handy, thanks for the howto keith. full extent of my 16gb card now available...
cheers
simon

Joshi said...

i would try this, BUT my Swap is just after the boot, and the linux partition is at the end, any suggestion?

About Me - WrightRocket

My photo

I've worked with computers for over 30 years, programming, administering, using and building them from scratch.

I'm an instructor for technical computer courses, an editor and developer of training manuals, and an Android developer.