How to Create a Space-Efficient Disk Image (Excluding Unused Blocks) While Preserving MBR


2 views

When cloning disks for device manufacturing, we often encounter storage inefficiency when using standard dd commands. The traditional approach:

dd if=/dev/sda of=master_image.img

creates an exact byte-for-byte copy including all unused space, resulting in unnecessarily large image files.

From the fdisk -l output, we can see:

Disk /dev/sda: 64.0 GB (64023257088 bytes)
Partition table shows only about 4GB used space
MBR and partition structure must be preserved

Here's the most efficient method to create a bootable image without empty space:

# Calculate total used blocks
BLOCKS=$(blockdev --getsize64 /dev/sda)
BLOCK_SIZE=512

# Create image with only used blocks
dd if=/dev/sda of=compact_image.img bs=$BLOCK_SIZE count=$(($BLOCKS/$BLOCK_SIZE)) conv=sparse

For more advanced control over what gets copied:

# Install partclone if needed
sudo apt-get install partclone

# Create image preserving boot sector
partclone.extfs -c -s /dev/sda -o compressed_image.img

Always verify your image before deployment:

# Check MBR preservation
fdisk -l compact_image.img

# Verify boot capability
qemu-system-x86_64 -hda compact_image.img

For manufacturing environments, consider this automated script:

#!/bin/bash
DISK="/dev/sda"
OUTPUT_FILE="/mnt/fileserver/device_$(date +%Y%m%d).img"

# Calculate optimal block size
BLOCK_SIZE=$(blockdev --getbsz $DISK)
TOTAL_BLOCKS=$(blockdev --getsize $DISK)

# Create sparse image
echo "Creating optimized disk image..."
dd if=$DISK of=$OUTPUT_FILE bs=$BLOCK_SIZE count=$TOTAL_BLOCKS conv=sparse,notrunc

# Verify checksum
echo "Verifying image..."
md5sum $DISK > ${OUTPUT_FILE}.md5
md5sum -c ${OUTPUT_FILE}.md5

When creating disk images for device manufacturing, we often face storage inefficiency when using traditional dd commands. The challenge is to create a compact image that:

  • Preserves the Master Boot Record (MBR)
  • Maintains partition structure
  • Only includes allocated blocks (excluding empty space)
  • Remains bootable after restoration

The best approach combines dd with sparse file creation and proper partition handling:

# Create a sparse image file
dd if=/dev/sda of=disk.img bs=4M conv=sparse

# Alternatively, for more control over sparse allocation
fallocate -l $(blockdev --getsize64 /dev/sda) disk.img
truncate -s $(blockdev --getsize64 /dev/sda) disk.img

For better efficiency when dealing with specific partitions:

# Get partition information
sfdisk -d /dev/sda > partitions.sfdisk

# Create image for each partition
for part in /dev/sda*; do
  partnum=${part##*sda}
  [ "$partnum" = "" ] && continue  # Skip the whole disk device
  
  # Get partition size in bytes
  size=$(blockdev --getsize64 "$part")
  
  # Create sparse image
  dd if="$part" of="part${partnum}.img" bs=4M conv=sparse count=$((size/4096))
done

For ext2/3/4 filesystems, we can optimize further:

# Create compressed image of used blocks only
for part in /dev/sda*; do
  case $(blkid -o value -s TYPE "$part") in
    ext2|ext3|ext4)
      e2image -ra -p "$part" "part-$(basename "$part").img"
      ;;
    *)
      dd if="$part" of="part-$(basename "$part").img" bs=4M conv=sparse
      ;;
  esac
done

To restore the image to a new device:

# Restore MBR and partition table
dd if=disk.img of=/dev/sdb bs=446 count=1
sfdisk /dev/sdb < partitions.sfdisk

# Restore partitions
for img in part*.img; do
  partnum=${img//[^0-9]/}
  dd if="$img" of="/dev/sdb${partnum}" bs=4M
done

Always verify your images:

# Check filesystem integrity
fsck -n /dev/sdb1

# Verify boot capability
file -s /dev/sdb1 | grep -q 'boot sector' && echo "Bootable" || echo "Not bootable"

# Compare checksums
cmp /dev/sda1 /dev/sdb1