1
0
Fork 0

Merging upstream version 4.3+20240723.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-14 06:34:47 +01:00
parent 9d4f96bc70
commit aa881a3626
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
70 changed files with 1465 additions and 1206 deletions

169
Grow.c
View file

@ -862,10 +862,7 @@ static void wait_reshape(struct mdinfo *sra)
close(fd);
}
static int reshape_super(struct supertype *st, unsigned long long size,
int level, int layout, int chunksize, int raid_disks,
int delta_disks, char *backup_file, char *dev,
int direction, int verbose)
static int reshape_super(struct supertype *st, struct shape *shape, struct context *c)
{
/* nothing extra to check in the native case */
if (!st->ss->external)
@ -876,9 +873,65 @@ static int reshape_super(struct supertype *st, unsigned long long size,
return 1;
}
return st->ss->reshape_super(st, size, level, layout, chunksize,
raid_disks, delta_disks, backup_file, dev,
direction, verbose);
return st->ss->reshape_super(st, shape, c);
}
/**
* reshape_super_size() - Reshape array, size only.
*
* @st: supertype.
* @devname: device name.
* @size: component size.
* @dir metadata changes direction
* Returns: 0 on success, 1 otherwise.
*
* This function is solely used to change size of the volume.
* Setting size is not valid for container.
* Size is only change that can be rolled back, thus the @dir param.
*/
static int reshape_super_size(struct supertype *st, char *devname,
unsigned long long size, change_dir_t direction,
struct context *c)
{
struct shape shape = {0};
shape.level = UnSet;
shape.layout = UnSet;
shape.delta_disks = UnSet;
shape.dev = devname;
shape.size = size;
shape.direction = direction;
return reshape_super(st, &shape, c);
}
/**
* reshape_super_non_size() - Reshape array, non size changes.
*
* @st: supertype.
* @devname: device name.
* @info: superblock info.
* Returns: 0 on success, 1 otherwise.
*
* This function is used for any external array changes but size.
* It handles both volumes and containers.
* For changes other than size, rollback is not possible.
*/
static int reshape_super_non_size(struct supertype *st, char *devname,
struct mdinfo *info, struct context *c)
{
struct shape shape = {0};
/* Size already set to zero, not updating size */
shape.level = info->new_level;
shape.layout = info->new_layout;
shape.chunk = info->new_chunk;
shape.raiddisks = info->array.raid_disks;
shape.delta_disks = info->delta_disks;
shape.dev = devname;
/* Rollback not possible for non size changes */
shape.direction = APPLY_METADATA_CHANGES;
return reshape_super(st, &shape, c);
}
static void sync_metadata(struct supertype *st)
@ -1170,13 +1223,14 @@ int reshape_open_backup_file(char *backup_file,
* way this will not notice, but it is better than
* nothing.
*/
fstat(*fdlist, &stb);
if (fstat(*fdlist, &stb) != 0)
goto error;
dev = stb.st_dev;
fstat(fd, &stb);
if (fstat(fd, &stb) != 0)
goto error;
if (stb.st_rdev == dev) {
pr_err("backup file must NOT be on the array being reshaped.\n");
close(*fdlist);
return 0;
goto error;
}
memset(buf, 0, 512);
@ -1202,6 +1256,9 @@ int reshape_open_backup_file(char *backup_file,
}
return 1;
error:
close(*fdlist);
return 0;
}
unsigned long compute_backup_blocks(int nchunk, int ochunk,
@ -1764,9 +1821,8 @@ static int reshape_container(char *container, char *devname,
int mdfd,
struct supertype *st,
struct mdinfo *info,
int force,
char *backup_file, int verbose,
int forked, int restart, int freeze_reshape);
struct context *c,
int forked, int restart);
/**
* prepare_external_reshape() - prepares update on external metadata if supported.
@ -1982,9 +2038,8 @@ int Grow_reshape(char *devname, int fd,
}
/* ========= set size =============== */
if (s->size > 0 &&
(s->size == MAX_SIZE || s->size != (unsigned)array.size)) {
unsigned long long orig_size = get_component_size(fd)/2;
if (s->size > 0 && (s->size == MAX_SIZE || s->size != (unsigned)array.size)) {
unsigned long long orig_size = get_component_size(fd) / 2;
unsigned long long min_csize;
struct mdinfo *mdi;
int raid0_takeover = 0;
@ -2004,9 +2059,7 @@ int Grow_reshape(char *devname, int fd,
goto release;
}
if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL,
devname, APPLY_METADATA_CHANGES,
c->verbose > 0)) {
if (reshape_super_size(st, devname, s->size, APPLY_METADATA_CHANGES, c)) {
rv = 1;
goto release;
}
@ -2085,7 +2138,7 @@ int Grow_reshape(char *devname, int fd,
if (!mdmon_running(st->container_devnm))
start_mdmon(st->container_devnm);
ping_monitor(container);
if (mdmon_running(st->container_devnm) == false) {
if (wait_for_mdmon(st->container_devnm) != MDADM_STATUS_SUCCESS) {
pr_err("No mdmon found. Grow cannot continue.\n");
goto release;
}
@ -2124,10 +2177,8 @@ size_change_error:
int err = errno;
/* restore metadata */
if (reshape_super(st, orig_size, UnSet, UnSet, 0, 0,
UnSet, NULL, devname,
ROLLBACK_METADATA_CHANGES,
c->verbose) == 0)
if (reshape_super_size(st, devname, orig_size,
ROLLBACK_METADATA_CHANGES, c) == 0)
sync_metadata(st);
pr_err("Cannot set device size for %s: %s\n",
devname, strerror(err));
@ -2338,8 +2389,7 @@ size_change_error:
*/
close_fd(&fd);
rv = reshape_container(container, devname, -1, st, &info,
c->force, c->backup_file, c->verbose,
0, 0, 0);
c, 0, 0);
frozen = 0;
} else {
/* get spare devices from external metadata
@ -2356,13 +2406,9 @@ size_change_error:
}
/* Impose these changes on a single array. First
* check that the metadata is OK with the change. */
if (reshape_super(st, 0, info.new_level,
info.new_layout, info.new_chunk,
info.array.raid_disks, info.delta_disks,
c->backup_file, devname,
APPLY_METADATA_CHANGES, c->verbose)) {
* check that the metadata is OK with the change.
*/
if (reshape_super_non_size(st, devname, &info, c)) {
rv = 1;
goto release;
}
@ -3176,7 +3222,8 @@ static int reshape_array(char *container, int fd, char *devname,
if (!mdmon_running(container))
start_mdmon(container);
ping_monitor(container);
if (mdmon_running(container) && st->update_tail == NULL)
if (wait_for_mdmon(container) == MDADM_STATUS_SUCCESS &&
!st->update_tail)
st->update_tail = &st->updates;
}
}
@ -3668,23 +3715,15 @@ int reshape_container(char *container, char *devname,
int mdfd,
struct supertype *st,
struct mdinfo *info,
int force,
char *backup_file, int verbose,
int forked, int restart, int freeze_reshape)
struct context *c,
int forked, int restart)
{
struct mdinfo *cc = NULL;
int rv = restart;
char last_devnm[32] = "";
/* component_size is not meaningful for a container,
* so pass '0' meaning 'no change'
*/
if (!restart &&
reshape_super(st, 0, info->new_level,
info->new_layout, info->new_chunk,
info->array.raid_disks, info->delta_disks,
backup_file, devname, APPLY_METADATA_CHANGES,
verbose)) {
/* component_size is not meaningful for a container */
if (!restart && reshape_super_non_size(st, devname, info, c)) {
unfreeze(st);
return 1;
}
@ -3695,7 +3734,7 @@ int reshape_container(char *container, char *devname,
*/
ping_monitor(container);
if (!forked && !freeze_reshape)
if (!forked && !c->freeze_reshape)
if (continue_via_systemd(container, GROW_SERVICE, NULL))
return 0;
@ -3705,7 +3744,7 @@ int reshape_container(char *container, char *devname,
unfreeze(st);
return 1;
default: /* parent */
if (!freeze_reshape)
if (!c->freeze_reshape)
printf("%s: multi-array reshape continues in background\n", Name);
return 0;
case 0: /* child */
@ -3802,12 +3841,12 @@ int reshape_container(char *container, char *devname,
flush_mdmon(container);
rv = reshape_array(container, fd, adev, st,
content, force, NULL, INVALID_SECTORS,
backup_file, verbose, 1, restart,
freeze_reshape);
content, c->force, NULL, INVALID_SECTORS,
c->backup_file, c->verbose, 1, restart,
c->freeze_reshape);
close(fd);
if (freeze_reshape) {
if (c->freeze_reshape) {
sysfs_free(cc);
exit(0);
}
@ -4449,7 +4488,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
*/
char *buf;
int degraded = -1;
unsigned long long speed;
unsigned long long suspend_point, array_size;
unsigned long long backup_point, wait_point;
unsigned long long reshape_completed;
@ -4505,10 +4543,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
if (posix_memalign((void**)&buf, 4096, disks * chunk))
/* Don't start the 'reshape' */
return 0;
if (reshape->before.data_disks == reshape->after.data_disks) {
sysfs_get_ll(sra, NULL, "sync_speed_min", &speed);
sysfs_set_num(sra, NULL, "sync_speed_min", 200000);
}
if (increasing) {
array_size = sra->component_size * reshape->after.data_disks;
@ -4641,8 +4675,6 @@ int child_monitor(int afd, struct mdinfo *sra, struct reshape *reshape,
sysfs_set_num(sra, NULL, "suspend_lo", 0);
sysfs_set_num(sra, NULL, "sync_min", 0);
if (reshape->before.data_disks == reshape->after.data_disks)
sysfs_set_num(sra, NULL, "sync_speed_min", speed);
free(buf);
return done;
}
@ -4970,8 +5002,7 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist,
return 1;
}
int Grow_continue_command(char *devname, int fd,
char *backup_file, int verbose)
int Grow_continue_command(char *devname, int fd, struct context *c)
{
int ret_val = 0;
struct supertype *st = NULL;
@ -5140,7 +5171,7 @@ int Grow_continue_command(char *devname, int fd,
start_mdmon(container);
ping_monitor(container);
if (mdmon_running(container) == false) {
if (wait_for_mdmon(container) != MDADM_STATUS_SUCCESS) {
pr_err("No mdmon found. Grow cannot continue.\n");
ret_val = 1;
goto Grow_continue_command_exit;
@ -5157,7 +5188,7 @@ int Grow_continue_command(char *devname, int fd,
/* continue reshape
*/
ret_val = Grow_continue(fd, st, content, backup_file, 1, 0);
ret_val = Grow_continue(fd, st, content, 1, c);
Grow_continue_command_exit:
if (cfd > -1)
@ -5171,7 +5202,7 @@ Grow_continue_command_exit:
}
int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
char *backup_file, int forked, int freeze_reshape)
int forked, struct context *c)
{
int ret_val = 2;
@ -5187,14 +5218,12 @@ int Grow_continue(int mdfd, struct supertype *st, struct mdinfo *info,
st->ss->load_container(st, cfd, st->container_devnm);
close(cfd);
ret_val = reshape_container(st->container_devnm, NULL, mdfd,
st, info, 0, backup_file, 0,
forked, 1 | info->reshape_active,
freeze_reshape);
st, info, c, forked, 1 | info->reshape_active);
} else
ret_val = reshape_array(NULL, mdfd, "array", st, info, 1,
NULL, INVALID_SECTORS, backup_file,
NULL, INVALID_SECTORS, c->backup_file,
0, forked, 1 | info->reshape_active,
freeze_reshape);
c->freeze_reshape);
return ret_val;
}