Копирование томов на СХД через Linux сервер с использованием XCOPY

    Бывает, что нужно получить полную копию тома в рамках одной системы хранения данных (СХД), не снимок, клон, а именно полноценный том. Но не всегда СХД дает это сделать внутри себя собственными средствами. Вроде единственный вариант копировать через сервер, но при этом весь объем данных будет гоняться через сам сервер, сеть до СХД и порты СХД, нагружая все эти компоненты. Но есть SCSI команды, которые могут позволить сделать все в рамках самой СХД и если ваша система поддерживает VAAI от VMware, то практически 100%, что поддерживается команда XCOPY (EXTENDED COPY), которая и говорит массиву что и куда скопировать, не вовлекая в этот процесс сервер и сеть.

    Вроде как все должно быть просто, но так сходу я готовых скриптов не нашел, пришлось изобретать велосипед. Для ОС сервера был выбран Linux, а в качестве средства копирования команда ddpt (http://sg.danny.cz/sg/ddpt.html). Копировать с помощью такой комбинации можно любые тома от любой ОС, поскольку копирование идет поблочно на стороне СХД. Поскольку надо копировать поблочно, а количество блоков надо посчитать, то для подсчета количества таких итераций использовалась команда blockdev. Максимальный размер блока был получен опытным путем, с большим блоком ddpt не работал по факту. В итоге получился следующий довольно простой скрипт:

    #!/bin/bash
    # first parameter = input device
    # second parameter = output device
    # device size must be the same
    # changing bs variable can reduce speed, max speed should be at bs=32768. 32768 is max setting, lower settings should be calculated dividing by 2
    
    set -o nounset
    bs=32768
    s=`blockdev --getsz $1`
    i=0
    while [ $i -le $s ]
    do
    ddpt of=$2 bs=512 oflag=xcopy,direct if=$1 iflag=xcopy,direct count=$bs verbose=-1 skip=$i seek=$i
    i=$(( $i+$bs ))
    done

    Давайте сделаем небольшую проверку! Ну как небольшую, 1ТБ файл создавался и проверялся md5sum небыстро :)

    root@sales-demo-05:/home/vasilyk# blockdev --getsz /dev/mapper/mpathfs
    2516582400
    root@sales-demo-05:/home/vasilyk# blockdev --getsz /dev/mapper/mpathfr
    2516582400
    root@sales-demo-05:/home/vasilyk# mount /dev/mapper/mpathfs /xcopy_source/
    mount: /xcopy_source: wrong fs type, bad option, bad superblock on /dev/mapper/mpathfs, missing codepage or helper program, or other error.
    root@sales-demo-05:/home/vasilyk# mkfs /dev/mapper/mpathfs
    mke2fs 1.44.1 (24-Mar-2018)
    Discarding device blocks: done
    Creating filesystem with 314572800 4k blocks and 78643200 inodes
    Filesystem UUID: bed3ea00-c181-4b4e-b52e-d9bb498be756
    Superblock backups stored on blocks:
            32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
            4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
            102400000, 214990848
    
    Allocating group tables: done
    Writing inode tables: done
    Writing superblocks and filesystem accounting information: done
    
    root@sales-demo-05:/home/vasilyk# mount /dev/mapper/mpathfs /xcopy_source/
    root@sales-demo-05:/home/vasilyk# ls -l /xcopy_source/
    total 16
    drwx------ 2 root root 16384 Aug 19 15:35 lost+found
    root@sales-demo-05:/home/vasilyk# head -c 1T </dev/urandom > /xcopy_source/1TB_file
    root@sales-demo-05:/home/vasilyk# ls -l /xcopy_source/
    total 1074791444
    -rw-r--r-- 1 root root 1099511627776 Aug 19 17:25 1TB_file
    drwx------ 2 root root         16384 Aug 19 15:35 lost+found
    root@sales-demo-05:/home/vasilyk# umount /xcopy_source
    root@sales-demo-05:/home/vasilyk# mount /dev/mapper/mpathfr /xcopy_dest/
    mount: /xcopy_dest: wrong fs type, bad option, bad superblock on /dev/mapper/mpathfr, missing codepage or helper program, or other error.
    root@sales-demo-05:/home/vasilyk# cat xcopy.sh
    #!/bin/bash
    # first parameter = input device
    # second parameter = output device
    # device size must be the same
    # changing bs variable can reduce speed, max speed should be at bs=32768. 32768 is max setting, lower settings should be calculated dividing by 2
    
    bs=32768
    s=`blockdev --getsz $1`
    i=0
    while [ $i -le $s ]
    do
    ddpt of=$2 bs=512 oflag=xcopy,direct if=$1 iflag=xcopy,direct count=$bs verbose=-1 skip=$i seek=$i
    i=$(( $i+$bs ))
    done
    root@sales-demo-05:/home/vasilyk# time ./xcopy.sh /dev/mapper/mpathfs /dev/mapper/mpathfr
    real    11m30.878s
    user    2m3.000s
    sys     1m11.657s

    Что в этот момент происходило на СХД:

    image
    Продолжим с Линуксом.

    root@sales-demo-05:/home/vasilyk# mount /dev/mapper/mpathfr /xcopy_dest/
    root@sales-demo-05:/home/vasilyk# ls -l /xcopy_dest/
    total 1074791444
    -rw-r--r-- 1 root root 1099511627776 Aug 19 17:25 1TB_file
    drwx------ 2 root root         16384 Aug 19 15:35 lost+found
    root@sales-demo-05:/home/vasilyk# mount /dev/mapper/mpathfs /xcopy_source/
    root@sales-demo-05:/home/vasilyk# md5sum /xcopy_source/1TB_file
    53dc6dfdfc89f099c0d5177c652b5764  /xcopy_source/1TB_file
    root@sales-demo-05:/home/vasilyk# md5sum /xcopy_dest/1TB_file
    53dc6dfdfc89f099c0d5177c652b5764  /xcopy_dest/1TB_file
    root@sales-demo-05:/home/vasilyk#


    Все получилось, но тестируйте и используйте на свой страх и риск! Как исходный том лучше брать снепшоты, для начала.
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 4

      0
      Статья о возможностях, которые знать полезно. Но есть несколько вопросов:
      1. какая СХД использовалась
      2. какова скорость копирования без использования xcopy
      3. для копирования используется скрипт который выполняет работу частями — вычисляет размер устройств, вызывает ddpt для копирования 16МБ (32к блоков по 512байт) каждый раз делая seek/skip для уже скопированных данных. Зачем? Почему не убрать count совсем и оставить эту работу ddpt:
      If the 'count=' option is not given then the remaining blocks on both the input and output files are determined (if possible) and if both are found then the minimum of the two counts is used.

      Кстати, исходя из написанного, if и of не обязательно должны иметь одинаковый размер.
      4. Размер блока установлен в 512 байт, это оптимально?
      5. В чем смысл команды tail /xcopy_dest/1TB_file | strings?
        0
        1 и 2 — это не являлось целью исследований, использовалось то, что под рукой (InfiniBox) и скорость копирования без XCOPY не замерялась (можно замерить, но там много параметров будет влиять)
        3 не хотелось отдавать определение количества итераций, а хотелось задать в явном виде, но можно сделать и как вы предлагаете
        4 Ну скажем так, все считают размеры таким блоком, так было проще сделать, если скорость копирования не устраивает, то можно попробовать поиграть тут, но это не тот блок, которым происходит копирование, а указание СХД скопировать некоторое количество таких блоков
        5 для того чтобы понять что файлы получились одинаковые. По идее надо бы чексумму считать, но на 1ТБ файле было как-то уже лень
        Я сейчас может попробую еще поиграться и посмотреть по пунктам 2, 4 и 5
          0
          Кстати, по пункту 4 глянул статистику на СХД, размер блока был 16МБ, то есть запрос от ddpd в 32768 кусочков по 512 байт был собран в один IO запрос, так что наверное я тут с этим играться не буду, на данной СХД сомнительно что будет лучше.
            0
            Ну что же, по пункту 2, если убрать ключ xcopy, то около 100 мегабайт в секунду, если взять dd и увеличить блок, то около 400 мегабайт. Подозреваю, что можно делать в несколько потоков и будет быстрее. Что также касается и XCOPY — если разбить по адресам том на несколько кусков и делать XCOPY параллельно, то тоже может быть быстрее.
            По пункту 5 сделал через md5sum, так и статья стала покороче :)

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое