[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [linux-lvm] converting a filesystem to a logical volume



Bert Hubert writes:
> I was wondering.. I think it should be fairly easy to convert a filesystem
> into a logical volume - 'in place'.
> 
> Do people think that this is possible? If shifting a filesystem a bit is
> enough, I'll start writing it.

Lennert Buytenhek and I were discussing this a bit, and it shouldn't be
_too_ hard to do with the existing ext2resize code (although ext2resize
isn't currently designed to move the start of a filesystem, only the end).
This would be useful not only for LVM, but also for partition modification,
which the parted folks are working on.  It may be that they even have
some of this working already, but I haven't looked at their code yet.

What needs to be done is:

0) figure out the number of disk blocks, N, needed at the start of a
   partition for the LVM data structures (N should be an even multiple
   of 8 filesystem blocks to make this easy, as the block bitmaps are
   packed into bytes and it would be extra work to re-map the block
   bitmaps, although not impossible).

   if N < 3+num_inode_blocks+num_group_desc_blocks
      this would be a lot of work, maybe you should backup/restore instead?
      exit 1

1) shrink existing filesystem by N blocks (easily done with existing code)

2) mark data blocks, n, where n < N, for relocation
   for each group in the ext2 filesystem
      for each metadata block, m..num_metadata_blocks, in group
         mark data block (m+N) for relocation
   relocate all marked blocks (easily done with existing code)

Now for the new part for moving the start of the filesystem:

3) for each group, g, in the ext2 filesystem
      if group has superblock
         copy superblock, s, to s+N
	 for each group descriptor in desc block d..d+num_group_desc_blocks
	    copy descriptor to block d+s and subtract N from
	       inode/block bitmap and inode table pointers
      copy inode bitmap, i, to i+N
      copy block bitmap g bytes [N/8,end) to new bitmap g [0,end-N/8)
      copy block bitmap g+1 bytes* [0,N/8) to new bitmap g [end-N/8,end)
         mark old metadata blocks from group g+1 as free in block bitmap g
      mark new metadata blocks from group g as used in block bitmap g

* when g+1 is past the last group, copy zeros to the block bitmap, since you
  freed N blocks at the end of the filesystem in step (1).

      for each inode in inode block i..i+num_inode_blocks
         copy inode to block (i+N), subtract N from data block numbers
	 for each (single/double/triple) indirect block in old inode
	    allocate new free** block as indirect block, store in new inode
	    copy old indirect block to new indirect block and
	       subtract N from each data block number
	    mark old indirect block free in new block bitmap g

** make sure the new indirect block is not one of the old metadata blocks

Basically, you have created a full new set of filesystem metadata while
leaving the old metadata untouched.  You probably need less than 5% free
space in the filesystem (enough for a copy of the metadata, which is fixed
for a given filesystem, plus any indirect blocks, which depend on the size
of the files in the filesystem, but usually there are not a huge number).

By making new copies of the indirect blocks, there is never a time when
the old filesystem is not valid - this is a very good thing so you don't
have problems if the program crashed, the machine crashed, you change your
mind, etc.  You could always use the old filesystem until the time you
overwrite the start of the old filesystem with LVM metadata.

If you are really interested in working on this, the ext2resize code is
available via FTP or anonymous CVS from ext2resize.sourceforge.net.  Please
feel free to ask me any questions, etc.

Cheers, Andreas
-- 
Andreas Dilger  \ "If a man ate a pound of pasta and a pound of antipasto,
                 \  would they cancel out, leaving him still hungry?"
http://www-mddsp.enel.ucalgary.ca/People/adilger/               -- Dogbert


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]