This patch provides a generic device-mapper compression device. Originally written by Shaohua Li. https://www.redhat.com/archives/dm-devel/2013-December/msg00143.html I have optimized and hardened the code. I have not received any negative comments till now. Feel confident with the code. Please consider merging the code upstream. Testing: ------- This compression block device is tested in the following scenarios a) backing a ext4/xfs/btrfs filesystem b) backing swap Ran 'badblocks' test on the compressed block device. Thoroughly stress tested on PPC64 and x86 system. I have included a test-script that I used to test the block device. Version v5: Modified the parameter list format to use token=value. Fixed a coding issue noted by Julia Lawall. Fixed data corruption issue when compressed size was same as the original data. Modified the allowed maximum I/O size to be as large as two pages, without which larger size I/O need larger size buffers to temporarily hold compressed data. This can lead to inability to satisfy memory allocation requests. Version v4: fixed kbuild errors; hopefully they are all taken care off. - no reference to zero_page - convert all divide and mod operations to bit operations Version v3: Fixed sector alignment bugs exposed while testing on x86. Explicitly set the maximum request size to 128K. Without which range locking failed, causing I/Os to stamp each other. Fixed an occasional data corruption caused by wrong size of the compression buffer. Added a parameter while creation of the block device, to not sleep during memory allocations. This can be useful if the device is used as a swap device. Version v2: All patches are merged into a single patch. Major code re-arrangement. Data and metablocks allocated based on the length of the device map rather than the size of the backing device. Size of each entry in the bitmap array is explicitly set to 32bits. Attempt to reuse the provided bio buffer space instead of allocating a new one. Version v1: Comments from Alasdair have been incorporated. https://www.redhat.com/archives/dm-devel/2013-December/msg00144.html Ram Pai (1): From: Shaohua Li <shli@xxxxxxxxxx> Documentation/device-mapper/dm-inplace-compress.txt | 174 + drivers/md/Kconfig | 6 drivers/md/Makefile | 2 drivers/md/dm-inplace-compress.c | 2295 ++++++++++++++++++++ drivers/md/dm-inplace-compress.h | 194 + 5 files changed, 2671 insertions(+) ---------- Test script ------------- #!/bin/bash # a test program to verify the correctness of # the dm-inplace-compression target # - Ram Pai compdevname="__compdev" usage() { echo echo echo "$1: -d <device path> [ -h ] [ -c <compdevicename> ]" echo "-d <device path> path to the block device to " echo " back the compression device" echo "-c <compdevicename> some unique name of the compress" echo " device name to be used. Defaults to $compdevname" echo "-h help" echo echo return } getsize() { #the target will spew out the maximum size that #it can accommodate for the device. So start with #insane number and let it fail. insane=999999999999999999990009 dmsetup create $2 --table \ "0 $insane inplacecompress device=$1, \ writethrough,compressor=lzo" 2>/dev/null echo $(dmesg | \ grep 'dm-inplace-compress: This device can accommodate at most'\ | tail -1 | awk '{print $(NF-1)}') } MYNAME=$(basename $0) OPTIND=0 while getopts "d:c:h" args $OPTIONS do case "$args" in d) device=$OPTARG ;; c) compdevname=$OPTARG ;; *) usage $MYNAME exit 1 ;; esac done if [ -z "$device" ] then usage $MYNAME exit 1; fi if [ ! -b "$device" ] then usage $MYNAME echo ERROR: $device is not a block device exit 1; fi if [ -b "/dev/mapper/$compdevname" ] then echo "WARNING: $compdevname already exist" usage $MYNAME fi echo -n "ANY DATA ON $device WILL BE LOST. Continue using $device?: y/n:" read yesorno if [ "$yesorno" != "y" ] then echo "Ok, exiting" exit 1; fi dmsetup targets | grep inplacecompress > /dev/null if [ $? -ne 0 ] then echo "Please enable dminplacecompress target in the kernel" echo "Try modprobe dm-inplace-compress.ko" exit 1 fi #clean and init the device dd if=/dev/zero of=$device count=100 2> /dev/null dmsetup remove $compdevname 2> /dev/null size=$(getsize $device $compdevname) if [ ! -n $size ] then echo "FAILURE: determining the maximum possible size of the device" exit 1 fi ret=0 for mode in writethrough writeback=2 do for i in lzo 842 do cat /proc/crypto | grep -w "$i$" > /dev/null if [ $? -ne 0 ] then continue fi echo "Testing: $i $mode....:" #generate the device dmsetup create $compdevname --table "0 $size inplacecompress device=$device, $mode ,compressor=$i" if [ $? -ne 0 ] then echo "FAILURE: creating the device" exit 1 fi badblocks -wsv /dev/mapper/$compdevname if [ $? -ne 0 ] then echo "FAILURE:" ret=1 fi ## ## ## ADD MORE TESTS HERE ## ## echo "PASS" dmsetup remove $compdevname done done if [ $ret -eq 0 ] then echo CONGRATS IT WORKS exit 0 else echo FAIL exit 0 fi ------------------------ -- dm-devel mailing list dm-devel@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/dm-devel