Skip to content

Instantly share code, notes, and snippets.

@coderjo
Last active April 7, 2024 02:48
Show Gist options
  • Save coderjo/c8de3ecc31f1d6450254b5e97ea2c595 to your computer and use it in GitHub Desktop.
Save coderjo/c8de3ecc31f1d6450254b5e97ea2c595 to your computer and use it in GitHub Desktop.
access a disk image read-only with a copy-on-write overlay to allow fsck or the like to write changes
#!/bin/bash
# usage: attach_cow_image.sh [imagefile] [cowfile] [devname]
# imagefile: path to the image file you want to load
# cowfile: path to the file to store writes into. If it doesn't exist, a sparse 1GB file will be created.
# devname: the name you want the drive to show up as in /dev/mapper
imgfile="$1"
cowfile="$2"
dmname="$3"
# create COW file if it doesn't exist (otherwise, assume we are using a file from a previous use)
# the if you don't think 1000MiB will be enough, you can create a larger one.
[ -f "$cowfile" ] || dd if=/dev/zero of="$cowfile" bs=1 count=1 seek=1048576000
# attach the files to loop devices (with the image file read-only)
imgdev=`losetup -f -r --show "$imgfile"`
cowdev=`losetup -f --show "$cowfile"`
# get the size of the image device
imgsz=`blockdev --getsz $imgdev`
# create the devmapper table for a copy-on-write device using the two loop devices
# p means persist the snapshot data
# The 4 is the number of sectors to use per COW image chunk
echo 0 $imgsz snapshot $imgdev $cowdev p 4| dmsetup create $dmname
# and now probe the partition table of the new device
partprobe -s /dev/mapper/$dmname
# to detatch everything:
# dmsetup remove $dmname
# losetup -d $cowdev
# losetup -d $imgdev
@jaharkes
Copy link

There are two typos, but this worked perfectly to give me early access while I was recovering a failing drive with ddrescue. I was able to pass the block device of the drive I'm recovering to as 'imgfile', and this made sure I didn't accidentally clobber anything. Thank you!

cowdev=`losetup ...
imgsz=`blockdev --getsz $imgdev`

@coderjo
Copy link
Author

coderjo commented Oct 16, 2020

Oops. I don't know how I missed that. I might have been typing this up from memory and didn't actually run this version until later. I'm glad it was helpful.

@coderjo
Copy link
Author

coderjo commented Oct 16, 2020

Since you are recovering a drive, I have another script that can take the log file output by GNU's ddrescue and output a dm table which forces errors where the original drive had read errors, if you have need for that behavior.

@coderjo
Copy link
Author

coderjo commented Nov 14, 2020

If you're working on recovering a drive, you should probably also make the block device read only so you can't accidentally make changes with any tools.

For example:
# blockdev --setro /dev/sda

@JuniorJPDJ
Copy link

Wow, thanks!
Is there a way to resize new device to larger without changing backing RO one?

@coderjo
Copy link
Author

coderjo commented Jul 3, 2021

You could make a devmapper device with the linear target. You could probably actually append the linear target to this table after the snapshot target. Check out the manpage for dmsetup.

@JuniorJPDJ
Copy link

I did it like that:

# echo "0 $imgsz linear $imgdev 0"$'\n'"$imgsz 204800 zero" | dmsetup create big_xp
# echo "0 $((imgsz+204800)) snapshot /dev/mapper/big_xp $cowdev p 8" | dmsetup create big_xp_rw

man didn't help even a bit, but this gentoo wiki was helpful as hell: https://wiki.gentoo.org/wiki/Device-mapper#Create

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment