Tomas Dalebjork
2014-11-24 12:18:04 UTC
Hi,
I have a need to copy only changed block back to its origin from the
snapshot, but keep the snapshot device; similar to "lvconvert --merge".
Are there a way to do this?
Or can I use the below C code to perform this?
https://fbo.no-ip.org/svn/fbo/lvmsync+/lvmdiff.c
https://fbo.no-ip.org/svn/fbo/lvmsync+/lvmdiff.c
But instead of copying data from the /dev/mapper/vg-lv-real device to an
incremental file; by reading its <exception> data from the
/dev/mapper/vg-lv-cow; do this in like in reverse order.
Eg reading exception data from /dev/mapper/vg-lv-cow, read snapshot data
from /dev/mappper/vg-lv-cow and write its content to /dev/mapper/vg-lv or
/dev/mapper/vg-lv-real
..
while ( progress ) {
// process a single metadata chunk
for(i=0;i<(chunksize/16);i++) {
// Read a single chunk-pointer pair
read(difffd,&ofs_origin,sizeof(ofs_origin));
read(difffd,&ofs_snap,sizeof(ofs_snap));
// this is the end of the chain
if ( ofs_snap == 0 ) {
progress=0;
break;
}
ofs_realposition=ofs_origin * chunksize;
// Read changed chunk from ref-device
if ( lseek(reffd,ofs_realposition,SEEK_SET) != ofs_realposition ) {
fprintf(stderr,"E: Seek on reference device '%s' at 0x%016llX
failed, aborting.\n",refdev,(long long)ofs_realposition);
close(reffd);close(difffd);return 0;
}
if ( result=blockread(difffd,buffer,chunksize) != chunksize ) {
fprintf(stderr,"E: Unable to read all the data of block '%016llX'
(got %i of %i), aborting.\n",(long
long)ofs_realposition,result,chunksize);
close(difffd);close(reffd);return 0;
}
if ( result=blockwrite(refffd,buffer,chunksize) != chunksize ) {
fprintf(stderr,"E: Unable to write all the data of block
'%016llX', aborting (wrote %i of %i).\n",(long
long)ofs_realposition,result,chunksize);
close(difffd);close(reffd);return 0;
}
}
stat_metadatachunks++;
}
if ( VERBOSE ) {
fprintf(stderr,"I: Number of blocks: %li (%li
Bytes)\n",stat_chunks,stat_chunks*chunksize);
}
close(difffd);
close(reffd);
return 1;
}
int blockwrite(int fd,char *buffer,size_t size) {
int done=0;
int result;
while ( done != size ) {
result=write(fd,&buffer[done],size-done);
if ( result <= 0 ) {
return -1;
} else {
done += result;
}
}
return size;
}
int blockread(int fd,char *buffer,size_t size) {
int done=0;
int result;
while ( done != size ) {
result=read(fd,&buffer[done],size-done);
if ( result > 0 ) {
done += result;
} else {
if ( done == 0 ) {
return -1;
} else {
return done;
}
}
}
return size;
}
I have a need to copy only changed block back to its origin from the
snapshot, but keep the snapshot device; similar to "lvconvert --merge".
Are there a way to do this?
Or can I use the below C code to perform this?
https://fbo.no-ip.org/svn/fbo/lvmsync+/lvmdiff.c
https://fbo.no-ip.org/svn/fbo/lvmsync+/lvmdiff.c
But instead of copying data from the /dev/mapper/vg-lv-real device to an
incremental file; by reading its <exception> data from the
/dev/mapper/vg-lv-cow; do this in like in reverse order.
Eg reading exception data from /dev/mapper/vg-lv-cow, read snapshot data
from /dev/mappper/vg-lv-cow and write its content to /dev/mapper/vg-lv or
/dev/mapper/vg-lv-real
..
while ( progress ) {
// process a single metadata chunk
for(i=0;i<(chunksize/16);i++) {
// Read a single chunk-pointer pair
read(difffd,&ofs_origin,sizeof(ofs_origin));
read(difffd,&ofs_snap,sizeof(ofs_snap));
// this is the end of the chain
if ( ofs_snap == 0 ) {
progress=0;
break;
}
ofs_realposition=ofs_origin * chunksize;
// Read changed chunk from ref-device
if ( lseek(reffd,ofs_realposition,SEEK_SET) != ofs_realposition ) {
fprintf(stderr,"E: Seek on reference device '%s' at 0x%016llX
failed, aborting.\n",refdev,(long long)ofs_realposition);
close(reffd);close(difffd);return 0;
}
if ( result=blockread(difffd,buffer,chunksize) != chunksize ) {
fprintf(stderr,"E: Unable to read all the data of block '%016llX'
(got %i of %i), aborting.\n",(long
long)ofs_realposition,result,chunksize);
close(difffd);close(reffd);return 0;
}
if ( result=blockwrite(refffd,buffer,chunksize) != chunksize ) {
fprintf(stderr,"E: Unable to write all the data of block
'%016llX', aborting (wrote %i of %i).\n",(long
long)ofs_realposition,result,chunksize);
close(difffd);close(reffd);return 0;
}
}
stat_metadatachunks++;
}
if ( VERBOSE ) {
fprintf(stderr,"I: Number of blocks: %li (%li
Bytes)\n",stat_chunks,stat_chunks*chunksize);
}
close(difffd);
close(reffd);
return 1;
}
int blockwrite(int fd,char *buffer,size_t size) {
int done=0;
int result;
while ( done != size ) {
result=write(fd,&buffer[done],size-done);
if ( result <= 0 ) {
return -1;
} else {
done += result;
}
}
return size;
}
int blockread(int fd,char *buffer,size_t size) {
int done=0;
int result;
while ( done != size ) {
result=read(fd,&buffer[done],size-done);
if ( result > 0 ) {
done += result;
} else {
if ( done == 0 ) {
return -1;
} else {
return done;
}
}
}
return size;
}