DISCLAIMER. English language used here only for compatibility (ASCII only), so any suggestions about my bad grammar (and not only it) will be greatly appreciated.

четверг, 4 августа 2011 г.

LVM snapshots and corresponding DM tables

Here is just a few illustrations (with some text) for chapter about snapshot
and snapshot-origin device mapper's targets from
RedHat's Logical Volume Manager Administration Guide.
Also, here i make some assumptions about how this works, which seems logical,
but unproved since i don't check LVM's sources.
When you create snapshot with lvm, four Device Mapper devices will be used:

    1. Create snapshot device ('snapshot' target).
    2. Create Copy-On-Write (COW) device (usually, 'linear' target) for
       snapshot (created at 1). All data blocks changed in snapshot will be
       written to this device instead of the snapshot origin. Also, all data
       blocks changed in original device will backed up here (see below).
    3. Recreate original device (snapshot origin) using new table with
       'snapshot-origin' target and using old device number.
    4. Create new device using old original device's table (usually, 'linear')
       and use this device as origin for snapshot (created at 1) and COW
       device for new original device (created at 3).

Details explained below on example.

There was LV 'shilvana_sys/usr' with dm table

    root@shilvana:~# dmsetup table | grep usr
    shilvana_sys-usr: 0 20971520 linear 8:3 264

and corresponding device

    root@shilvana:~# ls -lL /dev/mapper/shilvana_sys-usr 
    brw-rw---- 1 root disk 254, 7 Aug  3 20:18 /dev/mapper/shilvana_sys-usr

And now i create snapshot 'snap_usr' of 'shilvana_sys/usr'

    root@shilvana:~# lvcreate -v -L 100M --snapshot -n usr_snap /dev/shilvana_sys/usr 

and here is how tables and devices will look now

    root@shilvana:~# dmsetup table | grep usr
    shilvana_sys-usr-real: 0 20971520 linear 8:3 264
    shilvana_sys-usr_snap-cow: 0 204800 linear 8:3 99614984
    shilvana_sys-usr: 0 20971520 snapshot-origin 254:8
    shilvana_sys-usr_snap: 0 20971520 snapshot 254:8 254:9 P 8

    root@shilvana:~# ls -lL /dev/mapper/shilvana_sys-usr*
    brw-rw---- 1 root disk 254, 7 Aug  3 20:20 /dev/mapper/shilvana_sys-usr
    brw-rw---- 1 root disk 254, 8 Aug  3 20:20 /dev/mapper/shilvana_sys-usr-real
    brw-rw---- 1 root disk 254, 6 Aug  3 20:20 /dev/mapper/shilvana_sys-usr_snap
    brw-rw---- 1 root disk 254, 9 Aug  3 20:20 /dev/mapper/shilvana_sys-usr_snap-cow

How it works?

From now on (until snaphsot 'usr_snap' will be removed) both 'usr' and
'usr_snap' will behave like snapshots. Device 'usr-real' is snapshot's origin
(it uses original (linear) mapping of old 'usr') and at the same time it is
COW (Copy-on-Write) device for new 'usr'. Device 'usr_snap-cow' is COW device
for 'usr_snap'.  Normally, to use two snapshots we need five devices:
snapshot's origin (must be unchanged), snap-1, COW device for snap-1, snap-2
and COW device for snap-2.  But here we have only four: origin is at the same
time COW device for one of the snapshots ('usr'). Hence, 'usr-real' as COW for
'usr' will work as usual (when we write to 'usr', data block will be written
to 'usr-real'), but COW 'usr_snap-cow' will be used in two situations:
    - when data is written to 'usr_snap' (normal usage), changed data block
      will be written to 'usr_snap-cow' instead of to origin ('usr-real');
    - when data is written to 'usr' and hence to 'usr-real', _original_ data
      block will be backed up from 'usr-real' to 'usr_snap-cow' in order to
      preserve it for 'usr_snap' (if this data block is not already changed in
      'usr_snap', and, hence, already written to 'usr_snap-cow');


And here is some pictures.


Before snapshot creation.

          0              20971520
254:7     |... usr ..........|                                                  (linear)
          |
          |
          |
8:3 .....................................................
    ----->|
     264


After snapshot creation.

          0              20971520
 (254:6)  |... usr-snap .....|                                                 (snapshot)
          |                  |
          |                  |


          0              20971520                     0               204800
 (254:8)  |... usr-real .....|               (254:9)  |.. usr_snap-cow ..|       (linear)
          |                                           |
          |                                           |
          |                                           |
8:3 .........................|.. other LVs ...........|.. free space ....|.....      (PV)
    ----->|
     264
     ------------------------------------------------>|
                    99614984

          |                  |
          |                  |
 (254:7)  |... usr ..........|                                          (snapshot-origin)
          |                  |
          0             20971520

Note, that space for snapshot's COW device 'usr_snap-cow' allocated from free
space in VG's Physical Volumes.


Read unchanged block from 'usr' and 'usr_snap' respectively:

  (original block)                   (original block)

        ^                                 ^
        | (read)                          | (read)
        |                                 |
       usr                             usr_snap

        ^                                 ^
        |                                 |
     usr-real                          usr-real

        ^                                 ^
        |                                 |
       PV                                PV
  (original block)                   (original block)


Change block in usr (write):

  (changed block)
        |
        | (write)
        v

       usr
        |
        v

     usr-real ---(save original)---> usr_snap-cow
        |                                 |
        v                                 v

       PV                                PV
  (changed block)                   (original block)


Read block changed in usr (but not changed in 'usr_snap'):

  (changed block)                   (original block)

        ^                                 ^
        | (read)                          | (read)
        |                                 |
       usr                             usr_snap

        ^                                 ^
        |                                 |
     usr-real                        usr_snap-cow

        ^                                 ^
        |                                 |
       PV                                PV
  (changed block)                   (original block)


Change block in usr_snap (write):

                                    (changed block)
                                          |
                                          | (write)
                                          v

       usr                             usr_snap
                                          |
                                          v

     usr-real                        usr_snap-cow
                                          |
                                          v

       PV                                PV
  (original block)                  (changed block)


Read block changed in usr_snap (but not changed in 'usr'):

  (original block)                   (changed block)

        ^                                 ^
        | (read)                          | (read)
        |                                 |
       usr                             usr_snap

        ^                                 ^
        |                                 |
     usr-real                        usr_snap-cow

        ^                                 ^
        |                                 |
       PV                                PV
  (original block)                   (changed block)


Комментариев нет:

Отправить комментарий