From 336cc97feabb2409535d2c8c4129de24a9bec707 Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Thu, 6 Apr 2017 13:38:09 +0200 Subject: [PATCH] Some changes --- README.md | 61 +++++++++++++++++++++++++++++++++++++- docs/man/zvault-init.1.md | 2 +- src/cli/args.rs | 4 +-- src/repository/backup.rs | 2 +- src/repository/metadata.rs | 5 ++++ src/repository/tarfile.rs | 2 +- 6 files changed, 70 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 223ee3f..1cfaec2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ZVault Backup solution +# zVault Backup Solution zVault is a highly efficient deduplicating backup solution that supports client-side encryption, compression and remote storage of backup data. @@ -83,6 +83,65 @@ Backups can be mounted as a user-space filesystem to investigate and restore their contents. Once mounted, graphical programs like file managers can be used to work on the backup data and find the needed files. + +## Example usage + +As an example, I am going to backup my projects folder. To do that, I am +initializing an encrypted zVault repository, storing the data on a remote +filesystem which has been mounted on `/mnt/backup`. + + #$> zvault init --encrypt --remote /mnt/backup + public: 2bea1d15... + secret: 3698a88c... + + Bundle size: 25.0 MiB + Chunker: fastcdc/16 + Compression: brotli/3 + Encryption: 2bea1d15... + Hash method: blake2 + +The repository has been created and zVault has generated as new key pair for me. +I should now store this key pair in a safe location before I continue. + +Now I can backup my home directory to the repository. + + #$> zvault backup /home/dswd/projects ::projects1 + info: No reference backup found, doing a full scan instead + Modified: false + Date: Thu, 6 Apr 2017 12:29:52 +0200 + Source: capanord:/home/dswd/projects + Duration: 0:01:59.5 + Entries: 29205 files, 9535 dirs + Total backup size: 5.4 GiB + Modified data size: 5.4 GiB + Deduplicated size: 3.2 GiB, 41.8% saved + Compressed size: 1.1 GiB in 48 bundles, 63.9% saved + Chunk count: 220410, avg size: 15.0 KiB + +The backup run took about 2 minutes and by looking at the data, I see that +deduplication saved over 40% and compression again saved over 60% so that in the +end my backup only uses 1.1 GiB out of 5.4 GiB. + +After some work, I create another backup. + + #$> zvault backup /home/dswd/projects ::projects2 + info: Using backup projekte1 as reference + Modified: false + Date: Thu, 6 Apr 2017 13:28:54 +0200 + Source: capanord:/home/dswd/projects + Duration: 0:00:07.9 + Entries: 29205 files, 9535 dirs + Total backup size: 5.4 GiB + Modified data size: 24.9 MiB + Deduplicated size: 10.6 MiB, 57.3% saved + Compressed size: 4.7 MiB in 2 bundles, 55.7% saved + Chunk count: 35507, avg size: 313 Bytes + +This time, the backup run only took about 8 seconds as zVault skipped most of +the folder because it was unchanged. The backup only stored 4.7 MiB of data. +This shows the true potential of deduplication. + + ### Semantic Versioning zVault sticks to the semantic versioning scheme. In its current pre-1.0 stage this has the following implications: diff --git a/docs/man/zvault-init.1.md b/docs/man/zvault-init.1.md index 9c6b88b..78bb451 100644 --- a/docs/man/zvault-init.1.md +++ b/docs/man/zvault-init.1.md @@ -45,7 +45,7 @@ configuration can be changed by _zvault-config(1)_ later. values. - * `-e`, `--encryption`: + * `-e`, `--encrypt`: Generate a keypair and enable encryption. Please see _zvault(1)_ for more information on *encryption*. diff --git a/src/cli/args.rs b/src/cli/args.rs index d947c1c..57967b2 100644 --- a/src/cli/args.rs +++ b/src/cli/args.rs @@ -241,7 +241,7 @@ pub fn parse() -> Result { .arg(Arg::from_usage("bundle_size --bundle-size [SIZE] 'Set the target bundle size in MiB (default: 25)'")) .arg(Arg::from_usage("--chunker [CHUNKER] 'Set the chunker algorithm and target chunk size (default: fastcdc/16)'")) .arg(Arg::from_usage("-c --compression [COMPRESSION] 'Set the compression method and level (default: brotli/3)'")) - .arg(Arg::from_usage("-e --encryption 'Generate a keypair and enable encryption'")) + .arg(Arg::from_usage("-e --encrypt 'Generate a keypair and enable encryption'")) .arg(Arg::from_usage("--hash [HASH] 'Set the hash method (default: blake2)'")) .arg(Arg::from_usage("-r --remote 'Set the path to the mounted remote storage'")) .arg(Arg::from_usage("[REPO] 'The path for the new repository'"))) @@ -327,7 +327,7 @@ pub fn parse() -> Result { bundle_size: (try!(parse_num(args.value_of("bundle_size").unwrap_or(&DEFAULT_BUNDLE_SIZE.to_string()), "Bundle size")) * 1024 * 1024) as usize, chunker: try!(parse_chunker(args.value_of("chunker").unwrap_or(DEFAULT_CHUNKER))), compression: try!(parse_compression(args.value_of("compression").unwrap_or(DEFAULT_COMPRESSION))), - encryption: args.is_present("encryption"), + encryption: args.is_present("encrypt"), hash: try!(parse_hash(args.value_of("hash").unwrap_or(DEFAULT_HASH))), repo_path: repository.to_string(), remote_path: args.value_of("remote").unwrap().to_string() diff --git a/src/repository/backup.rs b/src/repository/backup.rs index 4f956b7..a575ba5 100644 --- a/src/repository/backup.rs +++ b/src/repository/backup.rs @@ -153,7 +153,7 @@ impl Repository { ) -> Result { let path = path.as_ref(); let mut inode = try!(self.create_inode(path, reference)); - let meta_size = 1000; // add 1000 for encoded metadata + let meta_size = inode.estimate_meta_size(); inode.cum_size = inode.size + meta_size; if let Some(ref_inode) = reference { if !ref_inode.is_same_meta_quick(&inode) { diff --git a/src/repository/metadata.rs b/src/repository/metadata.rs index 572506a..4e5e853 100644 --- a/src/repository/metadata.rs +++ b/src/repository/metadata.rs @@ -265,6 +265,11 @@ impl Inode { pub fn decode(data: &[u8]) -> Result { Ok(try!(msgpack::decode(&data))) } + + #[inline] + pub fn estimate_meta_size(&self) -> u64 { + 1000 + } } diff --git a/src/repository/tarfile.rs b/src/repository/tarfile.rs index 72ba6d7..9cd198f 100644 --- a/src/repository/tarfile.rs +++ b/src/repository/tarfile.rs @@ -68,7 +68,7 @@ impl Repository { let path = try!(entry.path()).to_path_buf(); match self.import_tar_entry(&mut entry) { Ok(mut inode) => { - inode.cum_size = inode.size + 1000; + inode.cum_size = inode.size + inode.estimate_meta_size(); if inode.file_type == FileType::Directory { inode.cum_dirs = 1; } else {