Поменять местами содержимое двух HDD (для промежуточного хранения - только ОЗУ)
Модератор: Модераторы разделов
-
rm_
- Сообщения: 3340
- Статус: It's the GNU Age
- ОС: Debian
Поменять местами содержимое двух HDD
Есть два винчестера по 1.5 ТБ, нужно чтобы все данные с первого диска оказались на втором, а со второго - на первом. Для промежуточного хранения данных третий диск не использовать, только оперативку. Такая вот интересная задачка.
Верификация записанного - приветствуется; проприетарщину (всякие акронисы) - не предлагать. Я понимаю, что можно шелл-скрипт написать на базе практически одного только dd, но может уже есть готовый (и оттестированный) инструмент для такой операции?
Верификация записанного - приветствуется; проприетарщину (всякие акронисы) - не предлагать. Я понимаю, что можно шелл-скрипт написать на базе практически одного только dd, но может уже есть готовый (и оттестированный) инструмент для такой операции?
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Можно (если система на третьем HDD) сделать скриптик (а еще проще - на сях программку написать): выделить процентов 90 оперативки (кстати, если в шелле - сделать /dev/shm на 90% оперативки) и гонять sdx->половина выделенной памяти, sdy->другая половина, вторая половина -> sdx, первая -> sdy; и так, пока все не скопируем 
Но, честно говоря, меня эта задача вводит в ступор: ЗАЧЕМ?
Но, честно говоря, меня эта задача вводит в ступор: ЗАЧЕМ?
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
rm_
- Сообщения: 3340
- Статус: It's the GNU Age
- ОС: Debian
Re: Поменять местами содержимое двух HDD
сделать скриптик (а еще проще - на сях программку написать): выделить процентов 90 оперативки (кстати, если в шелле - сделать /dev/shm на 90% оперативки)
Угу. Тем более что её 8 ГБ.
и гонять sdx->половина выделенной памяти, sdy->другая половина, вторая половина -> sdx, первая -> sdy;
Да можно проще:
1) sda -> RAM;
2) sdb -> sda;
3) RAM -> sdb.
Но, честно говоря, меня эта задача вводит в ступор: ЗАЧЕМ?
Винчестеры разных фирм/производительности/вибручести, я подумываю некоторым образом обменять их друг с другом в плане обязанностей.
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Понятно. Так вперед - выйдите в single, перемонтируйте /dev/shm, чтобы его размер был ~7.5Гб, и гоняйте данные...
Только если у вас смещение в lseek задается 32-битным, не забудьте прописать в начале файла
Если хотите обойтись скриптом - придется использовать bc, чтобы вычислять смещение для очередного dd.
Только если у вас смещение в lseek задается 32-битным, не забудьте прописать в начале файла
Код: Выделить всё
#define _FILE_OFFSET_BITS 64
#define _LARGEFILE64_SOURCEЕсли хотите обойтись скриптом - придется использовать bc, чтобы вычислять смещение для очередного dd.
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
drBatty
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
- ОС: Slackware-current
Re: Поменять местами содержимое двух HDD
да вроде и bash может. ((такой конструкцией))
можно считать КС каждого блока, и писать их в два файла. Затем проверить. Вот только если не сойдётся...
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
А баш умеет long long? Не знал, я думал, он 32-битной арифметикой обходится.
Ух ты! Попробовал - и правда, баш, оказывается, с 64-битными числами работает!
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
rm_
- Сообщения: 3340
- Статус: It's the GNU Age
- ОС: Debian
Re: Поменять местами содержимое двух HDD
Там не обязателен long long, смещение для dd задаётся в блоках, а размер блока указывается (bs=) произвольно, и нормальное значение - 1-8-16-32-64 мегабайт. Для простоты расчётов можно даже поставить 100.
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Тьфу ты, а я и забыл. Так можно еще больше упростить задачу: сказать, что размер блока равен, скажем, 7.5Гб 
А не проще ли на сях написать? Хотя, честно говоря, я с такими объемами оперативки не работал. Но, думаю, уже давно есть способ сделать alloc больше, чем на 2Гб. Тогда делаем
и дальше по смыслу...
А не проще ли на сях написать? Хотя, честно говоря, я с такими объемами оперативки не работал. Но, думаю, уже давно есть способ сделать alloc больше, чем на 2Гб. Тогда делаем
Код: Выделить всё
unsigned char *mem = (unsigned char*)malloc(8053063680);
read(/dev/sdx, mem, 8053063680)и дальше по смыслу...
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
rm_
- Сообщения: 3340
- Статус: It's the GNU Age
- ОС: Debian
Re: Поменять местами содержимое двух HDD
сказать, что размер блока равен, скажем, 7.5Гб
Не получится. Исходники не смотрел, но если я правильно прочувствовал его алгоритм (в том числе в процессе экспериментов с большими размерами блоков), dd сначала считывает с источника данные до заполнения буфера (равного тому самому размеру блока) в ОЗУ, потом сливает этот буфер на устройство-пункт назначения. Соотв-но прочитай он в буфер 7.5 ГБ, скинуть их (в ту же самую оперативку) будет уже некуда.
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Тогда пишите на С. Уложитесь максимум в страницу 
У меня, к сожалению, ни дома, ни на работе нет компьютера с ОЗУ>2Гб, поэтому помочь вам не могу. А увеличение оперативки хотя бы до 6Гб у меня планируется только к осени
У меня, к сожалению, ни дома, ни на работе нет компьютера с ОЗУ>2Гб, поэтому помочь вам не могу. А увеличение оперативки хотя бы до 6Гб у меня планируется только к осени
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
NickLion
- Сообщения: 3408
- Статус: аватар-невидимка
- ОС: openSUSE Tumbleweed x86_64
Re: Поменять местами содержимое двух HDD
Не стоит. Так дольше скорее всего будет:
1) sda -> RAM; - sdb простаивает
2) sdb -> sda; - работают оба винта
3) RAM -> sdb. - sda простаивает
А если
1) sda -> RAM0 - 1 и 2 параллельно можно - память быстрее винтов
2) sdb -> RAM1
3) RAM0 -> sdb - опять же параллельно 3 и 4
4) RAM1 -> sda
простоев нет.
-
sciko
- Сообщения: 1744
- Статус: Ъ-участник
- ОС: Debian/Ubuntu/etc
Re: Поменять местами содержимое двух HDD
Меня всегда удивляло на что люди идут лишь бы рейдом не пользоваться.
ИМХО, смысла в такой замене мало. Хотя бы потому, что повышение надёжности сопоставимо со статистической погрешностью.
По задаче рекомендую делать на всякий пожарный ещё и проверку целостности записанного (вероятность ошибки не нулевая).
-
rm_
- Сообщения: 3340
- Статус: It's the GNU Age
- ОС: Debian
Re: Поменять местами содержимое двух HDD
ИМХО, смысла в такой замене мало. Хотя бы потому, что повышение надёжности
Про надёжность тут ничего не говорилось, дело в том, что хочу вынести Samsung, охотно вступающий в резонанс с другими винтами в корзине, в компьютер, где он будет стоять как первый и единственный винчестер.
Но про RAID Вы правы, всерьёз подумываю о том чтоб сделать, только "барьер для входа" получается далеко не нулевой, нужно разом выложить деньги на бочку за как минимум 3*2ТБ (ну либо делать на "полторашках", что может оказаться недальновидным).
-
drBatty
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
- ОС: Slackware-current
Re: Поменять местами содержимое двух HDD
проще всего найти(одолжить) третий винт и не парится.
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Проще, но ведь интереснее написать программку, и использовать ресурсы своего компьютера. Тем более, что время на копирование с использованием в качестве посредника оперативки будет меньше, чем если посредником будет выступать жесткий диск.
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
drBatty
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
- ОС: Slackware-current
Re: Поменять местами содержимое двух HDD
я-бы башскриптом поменял. кусками по 1000Мб. и с проверкой
Код: Выделить всё
sda->mem
sdb->sda
cksum sda
mem->sdb
cksum sdbну и что, что долго? действие одноразовое.
Впрочем - пишите, я себе вашу программку тоже соберу, на всякий случай (:
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Так нет у меня оперативки >2Гб (я уже выше говорил), как проверить, что она работать будет?
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
drBatty
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
- ОС: Slackware-current
Re: Поменять местами содержимое двух HDD
а вы программку задумали исключительно для случая 8Гб? тогда - не надо.
почему нельзя реализовать параметр - размер буфера в мб? У меня сейчас тоже 512Мб.
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Можно. После обеда (если найду время) попробую что-нибудь подобное сделать. А с ОЗУ>2Гб не мешало бы потренироваться, чтобы узнать, может ли malloc выделять очень большие объемы памяти.
Кстати, не знаю, чего это я зацепился за malloc: с тем же успехом можно выделить память и shmget'ом
В общем, попробую и так, и эдак, потестирую на обмене содержимым двух файлов.
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Итак, как и обещал, привожу исходник:
Используем: a.out file1 file2 [size], на блочных устройствах еще не проверял, содержимое обычных файлов местами меняет. Аргумент size - размер выделяемой области оперативки (в мегабайтах). По умолчанию - 100Мб.
Заранее от рута выполните
Где SIZE - размер оперативки, которую вы позволите выделить под буферы (как минимум в 2 раза больше параметра size.
Проверял на файлах разных размеров. Работает. Оперативки, правда, у меня всего лишь 2Гб, так что под буферы выделял по 500Мб.
Да, система у меня 32битная, на 64-битной не знаю, как будет себя вести size_t при чтении/записи, если работать сразу с куском, скажем, 7Гб (если у вас, к примеру, 16Гб оперативки на домашнем компьютере).
Ну, а если на домашнем компьютере оперативки гигов на 128, можно небольшие жесткие диски целыми разделами за "присест" копировать
P.S. если размеры файлов отличаются, излишки данных у более объемного файла так и остаются при нем.
Код: Выделить всё
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char** argv){
int w1, w2, r1, r2, bytes1, bytes2, bytes;
int memsize, id1, id2, Mb = 1024*1024;
key_t key1, key2;
unsigned char *data1, *data2;
if(argc < 3){
printf("\nUsage: %s <file1> <file2> [mem]\n", argv[0]);
printf("\tswaps data in files <file1> & <file2>\n");
printf("mem - shared memory segments size in Mb (by default: 100)\n\n");
exit(1);
}
w1=open(argv[1], O_WRONLY);
r1=open(argv[1], O_RDONLY);
if(w1 < 1 || r1 < 1){
perror("Cant open file1");
exit(1);
}
w2=open(argv[2], O_WRONLY);
r2=open(argv[2], O_RDONLY);
if(w2 < 1 || r2 < 1){
perror("Cant open file2");
exit(1);
}
if(argc == 4) memsize = atoi(argv[3]);
else memsize = 100;
memsize *= Mb;
key1 = ftok(argv[1], 22);
key2 = ftok(argv[2], 22);
id1 = shmget(key1, memsize, IPC_CREAT|0644|SHM_DEST);
id2 = shmget(key2, memsize, IPC_CREAT|0644|SHM_DEST);
if(id1 < 0 || id2 < 0){
perror("Can't get shared memory");
goto ex;
}
data1 = (unsigned char*)shmat(id1, NULL, 0);
data2 = (unsigned char*)shmat(id2, NULL, 0);
if(data1 == ((void*)-1) || data2 == ((void*)-1)){
perror("Can't attach shared memory");
exit(1);
}
do{
bytes1 = read(r1, data1, memsize);
bytes2 = read(r2, data2, memsize);
if(bytes1 < 0 || bytes2 < 0){
perror("Can't read data from files");
goto ex;
}
bytes = (bytes1 > bytes2) ? bytes2:bytes1;
bytes1 = write(w1, data2, bytes);
bytes2 = write(w2, data1, bytes);
if(bytes1 != bytes || bytes2 != bytes){
perror("Can't write data to files");
goto ex;
}
}while(bytes == memsize);
ex:
shmdt(data2);
shmctl(id2, IPC_RMID, NULL);
shmdt(data1);
shmctl(id1, IPC_RMID, NULL);
}Используем: a.out file1 file2 [size], на блочных устройствах еще не проверял, содержимое обычных файлов местами меняет. Аргумент size - размер выделяемой области оперативки (в мегабайтах). По умолчанию - 100Мб.
Заранее от рута выполните
Код: Выделить всё
echo SIZE > /proc/sys/kernel/shmmaxГде SIZE - размер оперативки, которую вы позволите выделить под буферы (как минимум в 2 раза больше параметра size.
Проверял на файлах разных размеров. Работает. Оперативки, правда, у меня всего лишь 2Гб, так что под буферы выделял по 500Мб.
Да, система у меня 32битная, на 64-битной не знаю, как будет себя вести size_t при чтении/записи, если работать сразу с куском, скажем, 7Гб (если у вас, к примеру, 16Гб оперативки на домашнем компьютере).
Ну, а если на домашнем компьютере оперативки гигов на 128, можно небольшие жесткие диски целыми разделами за "присест" копировать
P.S. если размеры файлов отличаются, излишки данных у более объемного файла так и остаются при нем.
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
NickLion
- Сообщения: 3408
- Статус: аватар-невидимка
- ОС: openSUSE Tumbleweed x86_64
Re: Поменять местами содержимое двух HDD
eddy писал(а): ↑21.04.2010 22:53Заранее от рута выполните
Код: Выделить всё
echo SIZE > /proc/sys/kernel/shmmax
Где SIZE - размер оперативки, которую вы позволите выделить под буферы (как минимум в 2 раза больше параметра size.
Зачем? У меня там и так 264-1
Посмотрим, система 64 битная
Потестил. В программе была парочка ошибочек, вот изменённый код (я там расчёт мб изменил заодно
Код: Выделить всё
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
#include <errno.h>
int main( int argc, char** argv ) {
int w1, w2, r1, r2;
int id1, id2;//, Mb = 1024*1024;
size_t memsize;
ssize_t bytes1, bytes2, bytes;
key_t key1, key2;
unsigned char *data1, *data2;
if(argc < 3){
printf("\nUsage: %s <file1> <file2> [mem]\n", argv[0]);
printf("\tswaps data in files <file1> & <file2>\n");
printf("mem - shared memory segments size in Mb (by default: 100)\n\n");
exit(1);
}
w1=open(argv[1], O_WRONLY);
r1=open(argv[1], O_RDONLY);
if(w1 < 1 || r1 < 1){
perror("Cant open file1");
exit(1);
}
w2=open(argv[2], O_WRONLY);
r2=open(argv[2], O_RDONLY);
if(w2 < 1 || r2 < 1){
perror("Cant open file2");
exit(1);
}
if(argc == 4) memsize = atoi(argv[3]);
else memsize = 4608;
//memsize *= Mb;
memsize <<= 20; // (* 2^20) ^_^
key1 = ftok(argv[1], 22);
key2 = ftok(argv[2], 22);
id1 = shmget(key1, memsize, IPC_CREAT|0644|SHM_DEST);
id2 = shmget(key2, memsize, IPC_CREAT|0644|SHM_DEST);
if(id1 < 0 || id2 < 0){
perror("Can't get shared memory");
goto ex;
}
data1 = (unsigned char*)shmat(id1, NULL, 0);
data2 = (unsigned char*)shmat(id2, NULL, 0);
if(data1 == ((void*)-1) || data2 == ((void*)-1)){
perror("Can't attach shared memory");
exit(1);
}
do{
bytes1 = read(r1, data1, memsize);
bytes2 = read(r2, data2, memsize);
if(bytes1 < 0 || bytes2 < 0){
perror("Can't read data from files");
goto ex;
}
bytes = (bytes1 > bytes2) ? bytes2:bytes1;
bytes1 = write(w1, data2, bytes);
bytes2 = write(w2, data1, bytes);
if(bytes1 != bytes || bytes2 != bytes){
perror("Can't write data to files");
goto ex;
}
} while( (size_t) bytes == memsize );
ex:
shmdt(data2);
shmctl(id2, IPC_RMID, NULL);
shmdt(data1);
shmctl(id1, IPC_RMID, NULL);
}Но на тесте оказалось, что в строке:
Код: Выделить всё
bytes1 = read(r1, data1, memsize);При memsize = 4608 << 20; (4.5 Гб)
Всё равно считывает меньше 2 гиг
-
eddy
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Поменять местами содержимое двух HDD
Вот про это я и говорил: мне негде проверить, чему равен размер size_t на 64-битных системах. Оказывается - 32 бита. Поэтому максимум 2Гб он и считывает.
Ну, а раз так, то возможны два варианта: не выделять памяти больше 2Гб на каждый файл, или считывать в цикле кусками по 2Гб (если, скажем, вы выделили по 4Гб на файл).
Если задачу распараллелить (при помощи thread или fork), то придется как-то контролировать, что оба потока или процесса уже заполнили свои буферы. Здесь уже либо вводить flock, либо семафоры, либо отображать память в файл и хранить там данные о завершении, либо в той же разделяемой памяти сделать общую область, куда помещать флаги готовности/неготовности. Еще вариант (если делать fork): обмениваться сигналами, SIG_USR1 и SIG_USR2 вполне на эти задачи хватит. Тогда где-то в два раза скорость обмена возрастет.
Кстати, а у вас что, >10Гб оперативки?
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка
-
NickLion
- Сообщения: 3408
- Статус: аватар-невидимка
- ОС: openSUSE Tumbleweed x86_64
Re: Поменять местами содержимое двух HDD
Нет, memsize да и любая size_t - 64 бита (причём unsigned) (правда у Вас был тип int почему-то, это я поменял). Но вот считывает всё равно только до 2 гиг - т.е. это особенность реализации read/write. Они ведь не гарантируют, что будет считано/записано ровно столько, сколько указано.
Нет, только (