1

I have a Raid 5 setup using devices rather than partitions. I recently converted the ext4 fs on the md device to btrfs. I was initially happy with btrfs, but to be short, it's eating up CPU cycles and I want to go back. Unfortunately i had already removed the initial ext4 snapshot, so a revert is not possible. Luckily the data is using significantly less than half of the md device. I've successfully shrunk the btrfs to less than half of the total space, but i'm having issues with utilities seeing /dev/md/5 properly. fdisk shows that it doesn't have a proper partition table, and gparted (which i'm much more comfortable with) only sees /dev/md/5 after shrinking, however it shows it as unreadable, and also consuming the entire device.

You've probably guessed by now that what i'd like to do is shrink the btrfs to less than half of the total space, create an ext4 fs alongside it, and copy the data over. once this is done i could remove the btrfs and expand the ext4 fs to fill the device.

Is this possible? it seems that maybe doing the fs directly to the md device may have been a bad idea (in this case.)

I would really appreciate any help. I really don't want to fork out the money for an external drive just to revert my fs.

Thanks in advance!

5
  • So to clarify, dmsetup will be able to see the device as half full after a resize of the btrfs? – jteal Mar 10 '15 at 0:49
  • Could you (at the very least) let me know what the pertinent parts of the dmsetup man page I should look at are? Pardon my grammar...this is all new territory for me... – jteal Mar 10 '15 at 3:43
  • We assume the number of sectors are even so that <n> is the same number? Other wise it would be <n> and <n +/- 1> correct? One is an offset and the other is the size? – jteal Mar 10 '15 at 22:33
  • Let us continue this discussion in chat. – jteal Mar 10 '15 at 22:37
  • I had decided not to write an answer before because it's such a long and dangerous and risky procedure and I really don't recommend it but in the end I did write it up as an answer. I'm deleting all my other comments in this space since they're now obsolete. – Celada Mar 11 '15 at 3:14
1

It is possible to shuffle the data around the disk to achieve what you want, but it is an expert procedure with lots of steps and lots of opportunity to make a mistake even for an experienced person. There is no safety net and no forgiveness. If you make a mistake, you will lose your data. Personally, I would be reluctant to attempt this without backups available. (And if you have good backups, you arguably might as well reformat the whole thing and restore from backup.) Still, it's your decision to make, which you will make depending on factors like value of the data, time you have available to spend on this, etc...

First off, a comment: you mention that /dev/md/5 does not contain a partition table, but that's quite normal. MD devices typically are used in one of two configurations: (1) put a filesystem directly on the MD device as you have done, or (2) use the MD device as an LVM physical volume (PV) which is then a member of a volume group (VG), on which you then create any desired number of logical volumes (LV) which you use for filesystems, swap devices, VM images, etc... The latter sounds like lots of stacked layers but it's really just the normal LVM architecture. Placing a partition table on an MD device is not something I have ever seen. It would let you break the MD device into multiple pieces just like creating multiple LVs, but you might as well just use LVM instead. Also, I'm not even sure if placing a partition table directly on an MD device works automatically: you might need to use a tool like kpartx to make it works, which uses device-mapper technology just like LVM, so, again, you might as well just use LVM.

Introduction

Since you are actually using less than half of the available size of /dev/md/5, the procedure involves splitting the device in 2 halves, moving the data from the first half to the second half, creating the new type of filesystem you want in the first half, moving the data back to the first half, then getting rid of the split into 2 halves.

At the end, you'd have the data in the first half, in the format that you want it. Finally you can grow this half to occupy the whole device.

We will use device-mapper to create two virtual block devices that represent each half of the large /dev/md/5 device.

device-mapper is the same technology that LVM uses to map different chunks and pieces of physical volumes (PV) as logical volumes (LV). For the mapping type known as linear, this is done by specifying a source device, source offset, and target length. (device-mapper has other types of mappings too, which we will not talk about.) The difference is that LVM manages and tracks these mappings automatically and it stores them persistently in metadata that is stored as a header on the PV. It also chooses the placement information (offsets and sizes, multiple chunks, ...) automatically and transparently. Here we cannot use LVM to do the job because we need to strictly control the offsets and sizes manually, and also because we have no room at the beginning of /dev/md/5 to insert a PV metadata header. So we will use device-mapper directly through the dmsetup command.

Disclaimer

I have not attempted this procedure. It should work in principle, but I might have made a mistake. If I have made a mistake or if you make a mistake then YOU WILL LOSE YOUR DATA.

Procedure

  1. Resize the Btrfs filesystem on /dev/md/5 so that it occupies no more than half the device. Use blockdev --getsize64 /dev/md/5 to find out exactly how many bytes the device contains, and make the Btrfs filesystem smaller than half that. Err on the side of making it smaller rather than larger. It's okay if it occupies substantially less than half the device, but it is not OK if it exceeds even by 1 bytes.

    btrfs filesystem resize <devid>:<half>
    

    <devid> is the ID of the Btrfs member device to resize. You can see devids with btrfs filesystem show /mountpoint. I expect that, for this procedure, you are using a Btrfs filesystem with only one member device.

    half is half the number of bytes reported by blockdev --getsize64 /dev/md/5. Round down and subtract even more just to be sure.

    This command will take time. I'm not sure if it will return immediately and run in the background or if it will run in the foreground. My Btrfs experience sugests that it will run in the foreground. Either way, check kernel logs to see if there is an indication that the operation is complete.

  2. Double check the size of the Btrfs filesystem

    btrfs filesystem show /mountpoint
    

    Make sure the size is less than half of /dev/md/5. That command will probably show you the size in gigabytes with 2 decimal places only and I am not sure if it rounds down or up so that's why you want to subtract some margin in the previous step in order to be really sure that the value shown here is less than half the size of the device.

  3. Now we have the following situation:

    |*********---------| /dev/md/5
    

    where * is space used and - is space unused and |--| shows the span of the block device.

    Calculate the number of the first sector in the second half of the device.

    Start with the output of blockdev --getsize64 /dev/md/5 and divide by 512 because device-mapper sectors are 512 bytes. This is the number of sectors in /dev/md/5.

    Divide that number in 2. Round down. Call this number <half>.

    Create virtual block devices to map the first and second half separately:

    dmsetup create half2 --table '0 <half> linear /dev/md/5 <half>'
    

    Now you have this:

    |*********---------| /dev/md/5
              |--------| /dev/mapper/half2
    
  4. Create a temporary filesystem on /dev/mapper/half2

    mkdir /mnt/tmp
    mkfs.ext4 /dev/mapper/half2
    mount /dev/mapper/half2 /mnt/tmp
    
  5. Copy everything over

    rsync -avXSH /btrfs-mountpoint/ /mnt/tmp
    

    (use your favorite copy tool. Plain cp will work too.)

  6. Now it's time to get rid of the Btrfs filesystem

    umount /btrfs-mountpoint
    
  7. Create another device-mapper mapping

    dmsetup create half1 --table '0 <half> linear /dev/md/5 0'
    

    Now you have this:

    |---------*********| /dev/md/5
    |--------|           /dev/mapper/half1
              |********| /dev/mapper/half2
    

    where * is space used and - is space that was used before but we just freed it up by moving it to the second half and we are about to overwrite it.

  8. Create the final configuration that you would like to have in /dev/mapper/half1. You can create an ext4 filesystem directly but I recommend LVM.

    Direct:

    mkfs -t ext4 /dev/mapper/half1
    

    LVM:

    pvcreate /dev/mapper/half1
    vgcreate volume-group-name /dev/mapper/half1
    lvcreate -n logical-volume-name -L<size> volume-group-name
    mkfs -t ext4 /dev/volume-group-name/logical-volume-name
    
  9. Mount it and copy everything over

    mount /dev/volume-group-name/logical-volume-name /new-mountpoint
    # or
    mount /dev/mapper/half1 /new-mountpoint
    
    rsync -avXSH /mnt/tmp/ /new-mountpoint
    
  10. Get rid of all the temporary stuff

    umount /mnt/tmp
    dmsetup clear /dev/mapper/half2
    umount /new-mountpoint
    
    # If using LVM
    lvchange -a n /dev/volume-group-name/logical-volume-name
    vgchange -a n volume-group-name
    
    dmsetup clear /dev/mapper/half1
    

    If the device-mapper mappings fail to clear then you can either fix the problem or just reboot.

    You are back to this:

    |*********---------| /dev/md/5
    
  11. Now remount using the full /dev/md/5 device

    # If using LVM
    vgscan
    mount /dev/volume-group-name/logical-volume-name /new-mountpoint
    
    # otherwise
    mount /dev/md/5 /new-mountpoint
    
  12. Now you can expand the thing into the full device:

    # If using LVM
    pvresize /dev/md/5
    # Optionally, enlarge the LV
    
    # otherwise
    resize2fs /dev/md/5
    

whew!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.