mirror of
https://github.com/systemd/systemd
synced 2024-09-29 21:04:12 +00:00
Merge pull request #33003 from poettering/repart-progress
repart: draw progress bar during CopyBlocks= operation and other tweaks
This commit is contained in:
commit
7f1c31829b
|
@ -362,12 +362,14 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>CopyBlocks=</varname></term>
|
<term><varname>CopyBlocks=</varname></term>
|
||||||
|
|
||||||
<listitem><para>Takes a path to a regular file, block device node or directory, or the special value
|
<listitem><para>Takes a path to a regular file, block device node, char device node or directory, or
|
||||||
<literal>auto</literal>. If specified and the partition is newly created, the data from the specified
|
the special value <literal>auto</literal>. If specified and the partition is newly created, the data
|
||||||
path is written to the newly created partition, on the block level. If a directory is specified, the
|
from the specified path is written to the newly created partition, on the block level. If a directory
|
||||||
backing block device of the file system the directory is on is determined, and the data read directly
|
is specified, the backing block device of the file system the directory is on is determined, and the
|
||||||
from that. This option is useful to efficiently replicate existing file systems onto new partitions
|
data read directly from that. This option is useful to efficiently replicate existing file systems
|
||||||
on the block level — for example to build a simple OS installer or an OS image builder.</para>
|
onto new partitions on the block level — for example to build a simple OS installer or an OS image
|
||||||
|
builder. Specify <filename>/dev/urandom</filename> as value to initialize a partition with random
|
||||||
|
data.</para>
|
||||||
|
|
||||||
<para>If the special value <literal>auto</literal> is specified, the source to copy from is
|
<para>If the special value <literal>auto</literal> is specified, the source to copy from is
|
||||||
automatically picked up from the running system (or the image specified with
|
automatically picked up from the running system (or the image specified with
|
||||||
|
|
|
@ -295,6 +295,7 @@ typedef struct Partition {
|
||||||
int copy_blocks_fd;
|
int copy_blocks_fd;
|
||||||
uint64_t copy_blocks_offset;
|
uint64_t copy_blocks_offset;
|
||||||
uint64_t copy_blocks_size;
|
uint64_t copy_blocks_size;
|
||||||
|
uint64_t copy_blocks_done;
|
||||||
|
|
||||||
char *format;
|
char *format;
|
||||||
char **copy_files;
|
char **copy_files;
|
||||||
|
@ -4499,6 +4500,26 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int progress_bytes(uint64_t n_bytes, void *userdata) {
|
||||||
|
Partition *p = ASSERT_PTR(userdata);
|
||||||
|
_cleanup_free_ char *s = NULL;
|
||||||
|
|
||||||
|
p->copy_blocks_done += n_bytes;
|
||||||
|
|
||||||
|
if (asprintf(&s, "%s %s %s %s/%s ",
|
||||||
|
strna(p->copy_blocks_path),
|
||||||
|
special_glyph(SPECIAL_GLYPH_ARROW_RIGHT),
|
||||||
|
strna(p->definition_path),
|
||||||
|
FORMAT_BYTES(p->copy_blocks_done),
|
||||||
|
FORMAT_BYTES(p->copy_blocks_size)) < 0)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
draw_progress_bar(s,
|
||||||
|
p->copy_blocks_done >= p->copy_blocks_size ? 100.0 : /* catch division be zero */
|
||||||
|
100.0 * (double) p->copy_blocks_done / (double) p->copy_blocks_size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int context_copy_blocks(Context *context) {
|
static int context_copy_blocks(Context *context) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -4522,8 +4543,13 @@ static int context_copy_blocks(Context *context) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
assert(p->new_size != UINT64_MAX);
|
assert(p->new_size != UINT64_MAX);
|
||||||
assert(p->copy_blocks_size != UINT64_MAX);
|
|
||||||
assert(p->new_size >= p->copy_blocks_size + (p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0));
|
size_t extra = p->encrypt != ENCRYPT_OFF ? LUKS2_METADATA_KEEP_FREE : 0;
|
||||||
|
|
||||||
|
if (p->copy_blocks_size == UINT64_MAX)
|
||||||
|
p->copy_blocks_size = LESS_BY(p->new_size, extra);
|
||||||
|
|
||||||
|
assert(p->new_size >= p->copy_blocks_size + extra);
|
||||||
|
|
||||||
usec_t start_timestamp = now(CLOCK_MONOTONIC);
|
usec_t start_timestamp = now(CLOCK_MONOTONIC);
|
||||||
|
|
||||||
|
@ -4550,7 +4576,8 @@ static int context_copy_blocks(Context *context) {
|
||||||
return log_error_errno(errno, "Failed to seek to copy blocks offset in %s: %m", p->copy_blocks_path);
|
return log_error_errno(errno, "Failed to seek to copy blocks offset in %s: %m", p->copy_blocks_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = copy_bytes(p->copy_blocks_fd, partition_target_fd(t), p->copy_blocks_size, COPY_REFLINK);
|
r = copy_bytes_full(p->copy_blocks_fd, partition_target_fd(t), p->copy_blocks_size, COPY_REFLINK, /* ret_remains= */ NULL, /* ret_remains_size= */ NULL, progress_bytes, p);
|
||||||
|
clear_progress_bar(/* prefix= */ NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to copy in data from '%s': %m", p->copy_blocks_path);
|
return log_error_errno(r, "Failed to copy in data from '%s': %m", p->copy_blocks_path);
|
||||||
|
|
||||||
|
@ -6350,13 +6377,17 @@ static int context_open_copy_block_paths(
|
||||||
r = blockdev_get_device_size(source_fd, &size);
|
r = blockdev_get_device_size(source_fd, &size);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to determine size of block device to copy from: %m");
|
return log_error_errno(r, "Failed to determine size of block device to copy from: %m");
|
||||||
} else
|
} else if (S_ISCHR(st.st_mode))
|
||||||
|
size = UINT64_MAX;
|
||||||
|
else
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified path to copy blocks from '%s' is not a regular file, block device or directory, refusing.", opened);
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specified path to copy blocks from '%s' is not a regular file, block device or directory, refusing.", opened);
|
||||||
|
|
||||||
if (size <= 0)
|
if (size != UINT64_MAX) {
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
|
if (size <= 0)
|
||||||
if (size % 512 != 0)
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has zero size, refusing.", opened);
|
||||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
|
if (size % 512 != 0)
|
||||||
|
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "File to copy bytes from '%s' has size that is not multiple of 512, refusing.", opened);
|
||||||
|
}
|
||||||
|
|
||||||
p->copy_blocks_fd = TAKE_FD(source_fd);
|
p->copy_blocks_fd = TAKE_FD(source_fd);
|
||||||
p->copy_blocks_size = size;
|
p->copy_blocks_size = size;
|
||||||
|
|
|
@ -532,7 +532,9 @@ void clear_progress_bar(const char *prefix) {
|
||||||
fputc('\r', stderr);
|
fputc('\r', stderr);
|
||||||
|
|
||||||
if (terminal_is_dumb())
|
if (terminal_is_dumb())
|
||||||
fputs(strrepa(" ", utf8_console_width(prefix) + 4), /* 4: %3.0f%% */
|
fputs(strrepa(" ",
|
||||||
|
prefix ? utf8_console_width(prefix) + 4 :
|
||||||
|
LESS_BY(columns(), 1U)), /* 4: %3.0f%% */
|
||||||
stderr);
|
stderr);
|
||||||
else
|
else
|
||||||
fputs(ANSI_ERASE_TO_END_OF_LINE, stderr);
|
fputs(ANSI_ERASE_TO_END_OF_LINE, stderr);
|
||||||
|
|
|
@ -1287,6 +1287,26 @@ testcase_dropped_partitions() {
|
||||||
[[ "$(sfdisk -q -l "$image" | grep -c "$image")" -eq 2 ]]
|
[[ "$(sfdisk -q -l "$image" | grep -c "$image")" -eq 2 ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testcase_urandom() {
|
||||||
|
local workdir image defs
|
||||||
|
|
||||||
|
workdir="$(mktemp --directory "/tmp/test-repart.urandom.XXXXXXXXXX")"
|
||||||
|
# shellcheck disable=SC2064
|
||||||
|
trap "rm -rf '${workdir:?}'" RETURN
|
||||||
|
|
||||||
|
image="$workdir/image.img"
|
||||||
|
truncate -s 32M "$image"
|
||||||
|
|
||||||
|
defs="$workdir/defs"
|
||||||
|
mkdir "$defs"
|
||||||
|
echo -ne "[Partition]\nType=swap\nCopyBlocks=/dev/urandom\n" >"$defs/10-urandom.conf"
|
||||||
|
|
||||||
|
systemd-repart --empty=force --pretty=yes --dry-run=no --definitions="$defs" "$image"
|
||||||
|
|
||||||
|
sfdisk -q -l "$image"
|
||||||
|
[[ "$(sfdisk -q -l "$image" | grep -c "$image")" -eq 1 ]]
|
||||||
|
}
|
||||||
|
|
||||||
OFFLINE="yes"
|
OFFLINE="yes"
|
||||||
run_testcases
|
run_testcases
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue