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
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 🙂
Thanks for very useful article. I used it to resize ‘original’ image.
Thanks for the comment ! Your feedback is very appreciated !
Glad to have helped 🙂
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
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 🙂
[…] Using following links: http://www.raspberrypi.org/phpBB3/vi…p?f=91&t=19468 http://sirlagz.net/2012/06/20/how-to…an-image-file/ http://en.wikipedia.org/wiki/Master_boot_record#PTE I understood how to resize second partition of […]
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
Good idea, thanks for the link.