#include <unistd.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
+#include <sys/time.h>
#include <linux/fs.h>
#include <fcntl.h>
#include <limits.h>
static int opt_urandom = 0;
static int opt_bsize = 4;
static int opt_new = 0;
+static int opt_directio = 0;
+static int opt_write_log = 0;
static const char *opt_new_file = NULL;
static const char **action_argv;
char *password;
size_t passwordLen;
int keyslot;
+
+ struct timeval start_time, end_time;
} rnc;
char MAGIC[] = {'L','U','K','S', 0xba, 0xbe};
_log(level, msg, usrptr);
}
+/* The difference in seconds between two times in "timeval" format. */
+double time_diff(struct timeval start, struct timeval end)
+{
+ return (end.tv_sec - start.tv_sec)
+ + (end.tv_usec - start.tv_usec) / 1E6;
+}
+
static int alignment(int fd)
{
int alignment;
static int open_log(void)
{
+ int flags;
struct stat st;
if(stat(rnc.log_file, &st) < 0) {
// FIXME: move that somewhere else
rnc.reencrypt_direction = BACKWARD;
- rnc.log_fd = open(rnc.log_file, O_RDWR|O_CREAT|O_DIRECT, S_IRUSR|S_IWUSR);
+ flags = opt_directio ? O_RDWR|O_CREAT|O_DIRECT : O_RDWR|O_CREAT;
+ rnc.log_fd = open(rnc.log_file, flags, S_IRUSR|S_IWUSR);
if (rnc.log_fd == -1)
return -EINVAL;
if (write_log() < 0)
return -EIO;
} else {
log_dbg("Log file %s exists, restarting.", rnc.log_file);
- rnc.log_fd = open(rnc.log_file, O_RDWR|O_DIRECT);
+ flags = opt_directio ? O_RDWR|O_DIRECT : O_RDWR;
+ rnc.log_fd = open(rnc.log_file, flags);
if (rnc.log_fd == -1)
return -EINVAL;
rnc.in_progress = 1;
return r;
}
-static int copy_data_forward(int fd_old, int fd_new, size_t block_size, void *buf)
+void print_progress(uint64_t bytes, int final)
+{
+ uint64_t mbytes = bytes / 1024 / 1024;
+ struct timeval now_time;
+ double tdiff;
+
+ gettimeofday(&now_time, NULL);
+ if (!final && time_diff(rnc.end_time, now_time) < 0.5)
+ return;
+
+ rnc.end_time = now_time;
+
+ if (opt_batch_mode)
+ return;
+
+ tdiff = time_diff(rnc.start_time, rnc.end_time);
+ if (!tdiff)
+ return;
+
+ log_err("\33[2K\rProgress: %5.1f%%, time elapsed %3.1f seconds, %4"
+ PRIu64 " MB written, speed %5.2f MB/s%s",
+ (double)bytes / rnc.device_size * 100,
+ time_diff(rnc.start_time, rnc.end_time),
+ mbytes, (double)(mbytes) / tdiff,
+ final ? "\n" :"");
+}
+
+static int copy_data_forward(int fd_old, int fd_new, size_t block_size, void *buf, uint64_t *bytes)
{
ssize_t s1, s2;
- int j;
- log_err("Reencrypting [");
- j = 0;
+ *bytes = 0;
while (rnc.device_offset < rnc.device_size) {
s1 = read(fd_old, buf, block_size);
if (s1 < 0 || (s1 != block_size && (rnc.device_offset + s1) != rnc.device_size)) {
return -EIO;
}
rnc.device_offset += s1;
- if (write_log() < 0) {
+ if (opt_write_log && write_log() < 0) {
log_err("Log write error, some data are perhaps lost.\n");
return -EIO;
}
- if (rnc.device_offset > (j * (rnc.device_size / 10))) {
- log_err("-");
- j++;
- }
+ *bytes += (uint64_t)s2;
+ print_progress(*bytes, 0);
}
- log_err("] Done.\n");
return 0;
}
-static int copy_data_backward(int fd_old, int fd_new, size_t block_size, void *buf)
+static int copy_data_backward(int fd_old, int fd_new, size_t block_size, void *buf, uint64_t *bytes)
{
ssize_t s1, s2, working_offset, working_block;
- int j;
-
- log_err("Reencrypting [");
- j = 10;
+ *bytes = 0;
while (rnc.device_offset) {
if (rnc.device_offset < block_size) {
working_offset = 0;
return -EIO;
}
rnc.device_offset -= s1;
- if (write_log() < 0) {
+ if (opt_write_log && write_log() < 0) {
log_err("Log write error, some data are perhaps lost.\n");
return -EIO;
}
- if (rnc.device_offset < (j * (rnc.device_size / 10))) {
- log_err("-");
- j--;
- }
+ *bytes += (uint64_t)s2;
+ print_progress(*bytes, 0);
}
- log_err("] Done.\n");
return 0;
}
int fd_old = -1, fd_new = -1;
int r = -EINVAL;
void *buf = NULL;
+ uint64_t bytes = 0;
- fd_old = open(rnc.crypt_path_org, O_RDONLY | O_DIRECT);
+ fd_old = open(rnc.crypt_path_org, O_RDONLY | (opt_directio ? O_DIRECT : 0));
if (fd_old == -1)
goto out;
- fd_new = open(rnc.crypt_path_new, O_WRONLY | O_DIRECT);
+ fd_new = open(rnc.crypt_path_new, O_WRONLY | (opt_directio ? O_DIRECT : 0));
if (fd_new == -1)
goto out;
if (!rnc.in_progress && rnc.reencrypt_direction == BACKWARD)
rnc.device_offset = rnc.device_size;
+ gettimeofday(&rnc.start_time, NULL);
+
if (rnc.reencrypt_direction == FORWARD)
- r = copy_data_forward(fd_old, fd_new, block_size, buf);
+ r = copy_data_forward(fd_old, fd_new, block_size, buf, &bytes);
else
- r = copy_data_backward(fd_old, fd_new, block_size, buf);
+ r = copy_data_backward(fd_old, fd_new, block_size, buf, &bytes);
+ print_progress(bytes, 1);
if (r < 0)
log_err("ERROR during reencryption.\n");
+
+ if (write_log() < 0)
+ log_err("Log write error, ignored.\n");
+
out:
if (fd_old != -1)
close(fd_old);
if (!(rnc.device = strndup(device, PATH_MAX)))
return -ENOMEM;
-
+/*
if (opt_new_file && !create_uuid()) {
log_err("Cannot create fake header.\n");
return -EINVAL;
}
-
+*/
if (initialize_uuid()) {
log_err("No header found on device.\n");
return -EINVAL;
{ "batch-mode", 'q', POPT_ARG_NONE, &opt_batch_mode, 0, N_("Do not ask for confirmation"), NULL },
{ "use-random", '\0', POPT_ARG_NONE, &opt_random, 0, N_("Use /dev/random for generating volume key."), NULL },
{ "use-urandom", '\0', POPT_ARG_NONE, &opt_urandom, 0, N_("Use /dev/urandom for generating volume key."), NULL },
+ { "use-directio", '\0', POPT_ARG_NONE, &opt_directio, 0, N_("Use direct-io when accesing devices."), NULL },
+ { "write-log", '\0', POPT_ARG_NONE, &opt_write_log, 0, N_("Update log file after every block."), NULL },
POPT_TABLEEND
};
poptContext popt_context;
usage(popt_context, EXIT_FAILURE, _("Only one of --use-[u]random options is allowed."),
poptGetInvocationName(popt_context));
- if (opt_new || !opt_new_file)
+ if (opt_new && !opt_new_file)
usage(popt_context, EXIT_FAILURE, _("You have to use -f with -N."),
poptGetInvocationName(popt_context));