Jun 202012
 

Update : A guide for resizing smaller is now available

So I’ve recently started playing around with my Raspberry Pi. My first distro that I tried ? Raspbian 😀
More on that later though – one of the main things I’ve wanted to do was to flash Hexxeh’s Raspbian image onto a 4 GB SD Card. However, the image itself is for a 2 GB SD Card. I figured that it would be easy enough to make a new image, copy the old image contents onto the new, and voila…but it turned out that it wasn’t so simple.

So, in order to make the image file the right size before I go and flash it onto the SD Card, I created an empty image file with this command –

root@localhost:~ dd bs=1M count=3600 if=/dev/zero of=4graspi.img

This creates an empty file that is approximately 4 gigabytes in size called 4graspi.img, however this must be smaller than the SD card that you will be putting the image onto, or it will cause issues when you try and image the card with the new image.

Next, I mount the image as a loopback device

root@localhost:~ losetup -f --show 4graspi.img

Running this command should output the loopback device that the image is setup as, in this case for me it is /dev/loop0

I also mount the original image as a loopback so I can clone it


root@localhost:~ losetup -f --show raspbian-r3.img

This image is now setup as /dev/loop1

Once both devices are setup as loopback devices, you can now clone the existing contents into the new image with this command

root@localhost:~ dd if=/dev/loop1 of=/dev/loop0

After this command is completed, it will show how much was copied over

3808593+0 records in
3808593+0 records out
1949999616 bytes (1.9 GB) copied, 212.714 s, 9.2 MB/s

Notice it only copied 1.9 GB over from the original image, which means there’s 2 GB of free space left on the new image still.
Running fdisk -l on the new image which is still setup as a loopback device should show this

Disk /dev/loop0: 3984 MB, 3984588800 bytes
4 heads, 32 sectors/track, 60800 cylinders, total 7782400 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/loop0p1 2048 155647 76800 c W95 FAT32 (LBA)
/dev/loop0p2 157696 3414015 1628160 83 Linux
/dev/loop0p3 3416064 3807231 195584 82 Linux swap / Solaris

Now you can use parted to move the partitions around

root@localhost:~ parted /dev/loop0

First thing that I do is move the swap partition to the end of the image

Running the command print shows the current partition setup of the image

(parted) print
Model: (file)
Disk /dev/loop0: 3985MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number Start End Size Type File system Flags
1 1.05MB 79.7MB 78.6MB primary fat32 lba
2 80.7MB 1748MB 1667MB primary ext4
3 1749MB 1949MB 200MB primary linux-swap(v1)

The disk ends at 3985 MB, so that’s where the 200 MB swap partition will end. Then minus 200 off that, to get where the partition starts

(parted) move 3 3785 3985

Then to grow the primary partition, we remove the old partition –

(parted) rm 2

Then create a new larger partition where this one started, and it ends right before the swap partition begins

(parted) mkpart primary 80.7 3785

Now when I use the print command, it should show the new partition layout –

(parted) print
Model: (file)
Disk /dev/loop0: 3985MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos

Number Start End Size Type File system Flags
1 1.05MB 79.7MB 78.6MB primary fat32 lba
2 80.7MB 3784MB 3704MB primary ext4
3 3785MB 3985MB 199MB primary linux-swap(v1)

Once that is done we will need to quit parted and resize the filesystem that is on the primary partition
We need to mount the 2nd partition as another loopback device in order to do that. Running fdisk -l on /dev/loop0 gives us the information we require, which is the starting sector of the partition

root@localhost:~ fdisk -l

Disk /dev/loop0: 3984 MB, 3984588800 bytes
4 heads, 32 sectors/track, 60800 cylinders, total 7782400 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/loop0p1 2048 155647 76800 c W95 FAT32 (LBA)
/dev/loop0p2 157696 7391231 3616768 83 Linux
/dev/loop0p3 7392640 7782271 194816 82 Linux swap / Solaris

The partition we want starts on sector 157696, which we then multiply by the sector size which is 512. This gives us the starting offset that we need to mount using

root@localhost:~ echo '157696 * 512' | bc
80740352

We now have the starting offset, which we now use with losetup’s -o argument to set an offset

root@localhost:~ losetup -f --show -o 80740352 4graspi.img
/dev/loop2

Now we can scan for errors, allow it to create a lost+found and resize the filesystem

root@localhost:~ e2fsck -f /dev/loop2

e2fsck 1.41.14 (22-Dec-2010)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
/lost+found not found. Create? yes

Pass 4: Checking reference counts
Pass 5: Checking group summary information

/dev/loop2: ***** FILE SYSTEM WAS MODIFIED *****
/dev/loop2: 19530/101920 files (0.2% non-contiguous), 121757/407040 blocks

root@localhost:~ resize2fs /dev/loop2
resize2fs 1.41.14 (22-Dec-2010)
Resizing the filesystem on /dev/loop2 to 953088 (4k) blocks.
The filesystem on /dev/loop2 is now 953088 blocks long.

After the resizing is done, the loopback devices are no longer needed so I removed them

root@localhost:~ losetup -d /dev/loop0 /dev/loop1 /dev/loop2

Now to flash it onto my SD card which is detected as sdb in my system, it may differ for everyone.

root@localhost:~ dd bs=1M if=4graspi.img of=/dev/sdb

Resizing the partitions this way was a bit harder than flashing it onto the SD card first and then moving stuff around, but it was a lot faster for me as I have very slow SD cards. It also allows flashing the same image multiple times without having to repartition each individual SD card
*Note*
After flashing to the SD card, I had to re-run the resize to make it smaller again for some reason


If you have found this post useful, please consider donating by pressing on the button below. Donating will help keep this site up and running 🙂




Share

  8 Responses to “How To : Resize Partitions in an Image File”

  1. Thanks for very useful article. I used it to resize ‘original’ image.

  2. Hello. Thanks for your tips, everything is OK but it is important to mention that, by default, fdisk list partition table in cylinders and you should use ‘fdisk -lu /dev/loopX’ instead in order to see the sectors.

    Cheers

  3. As an alternative you could just use gparted…and resize the main partition

    • That is true. However I was trying to do it all from the command line, so this was the easiest way I could do it 🙂

  4. probably good to mention how to mount an image file with multiple partitions.

    https://superuser.com/questions/211338/mounting-a-multi-partition-disk-image-in-linux

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

(required)

(required)

This site uses Akismet to reduce spam. Learn how your comment data is processed.