Compare commits
No commits in common. 'c9-beta' and 'c9' have entirely different histories.
@ -0,0 +1,151 @@
|
|||||||
|
From 476b00bdeeb6c004b3a758bd842b0fa9e4164508 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
Date: Mon, 5 Feb 2024 15:50:29 +0100
|
||||||
|
Subject: [PATCH 1/1] Revert "mdadm: remove container_enough logic"
|
||||||
|
|
||||||
|
Mentioned patch changes way of IMSM member arrays assembling, they are
|
||||||
|
updated by every new drive incremental processes. Previously, member
|
||||||
|
arrays were created and filled once, by last drive incremental process.
|
||||||
|
|
||||||
|
We determined regressions with various impact. Unfortunately, initial
|
||||||
|
testing didn't show them.
|
||||||
|
|
||||||
|
Regressions are connected to drive appearance order and may not be
|
||||||
|
reproducible on every configuration, there are at least two know
|
||||||
|
issues for now:
|
||||||
|
|
||||||
|
- sysfs attributes are filled using old metadata if there is
|
||||||
|
outdated drive and it is enumerated first.
|
||||||
|
|
||||||
|
- rebuild may be aborted and started from beginning after reboot,
|
||||||
|
if drive under rebuild is enumerated as the last one.
|
||||||
|
|
||||||
|
This reverts commit 4dde420fc3e24077ab926f79674eaae1b71de10b. It fixes
|
||||||
|
checkpatch issues and reworks logic to remove empty "if" branch in
|
||||||
|
Incremental.
|
||||||
|
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Incremental.c | 9 +++++++++
|
||||||
|
mdadm.h | 7 +++++++
|
||||||
|
super-ddf.c | 1 +
|
||||||
|
super-intel.c | 32 +++++++++++++++++++++++++++++++-
|
||||||
|
4 files changed, 48 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Incremental.c b/Incremental.c
|
||||||
|
index 6cbc164a27b9..30c07c037028 100644
|
||||||
|
--- a/Incremental.c
|
||||||
|
+++ b/Incremental.c
|
||||||
|
@@ -1467,6 +1467,15 @@ static int Incremental_container(struct supertype *st, char *devname,
|
||||||
|
|
||||||
|
st->ss->getinfo_super(st, &info, NULL);
|
||||||
|
|
||||||
|
+ if (info.container_enough < 0 || (info.container_enough == 0 && c->runstop < 1)) {
|
||||||
|
+ if (c->export)
|
||||||
|
+ printf("MD_STARTED=no\n");
|
||||||
|
+ else if (c->verbose)
|
||||||
|
+ pr_err("Not enough devices to start the container.\n");
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
match = conf_match(st, &info, devname, c->verbose, &rv);
|
||||||
|
if (match == NULL && rv == 2)
|
||||||
|
return rv;
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index 709b6104c401..1f28b3e754be 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -377,6 +377,13 @@ struct mdinfo {
|
||||||
|
int container_member; /* for assembling external-metatdata arrays
|
||||||
|
* This is to be used internally by metadata
|
||||||
|
* handler only */
|
||||||
|
+ /**
|
||||||
|
+ * flag external handlers can set to indicate that subarrays have:
|
||||||
|
+ * - not enough disks to start (-1),
|
||||||
|
+ * - enough disks to start (0),
|
||||||
|
+ * - all expected disks (1).
|
||||||
|
+ */
|
||||||
|
+ int container_enough;
|
||||||
|
char sys_name[32];
|
||||||
|
struct mdinfo *devs;
|
||||||
|
struct mdinfo *next;
|
||||||
|
diff --git a/super-ddf.c b/super-ddf.c
|
||||||
|
index a87e3169d325..7571e3b740c6 100644
|
||||||
|
--- a/super-ddf.c
|
||||||
|
+++ b/super-ddf.c
|
||||||
|
@@ -1975,6 +1975,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
|
||||||
|
info->array.ctime = DECADE + __be32_to_cpu(*cptr);
|
||||||
|
|
||||||
|
info->array.chunk_size = 0;
|
||||||
|
+ info->container_enough = 1;
|
||||||
|
|
||||||
|
info->disk.major = 0;
|
||||||
|
info->disk.minor = 0;
|
||||||
|
diff --git a/super-intel.c b/super-intel.c
|
||||||
|
index 6a664a2e58d3..dbea235dd4bd 100644
|
||||||
|
--- a/super-intel.c
|
||||||
|
+++ b/super-intel.c
|
||||||
|
@@ -3778,6 +3778,7 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||||
|
struct intel_super *super = st->sb;
|
||||||
|
struct imsm_disk *disk;
|
||||||
|
int map_disks = info->array.raid_disks;
|
||||||
|
+ int max_enough = -1;
|
||||||
|
int i;
|
||||||
|
struct imsm_super *mpb;
|
||||||
|
|
||||||
|
@@ -3819,9 +3820,12 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||||
|
|
||||||
|
for (i = 0; i < mpb->num_raid_devs; i++) {
|
||||||
|
struct imsm_dev *dev = get_imsm_dev(super, i);
|
||||||
|
- int j = 0;
|
||||||
|
+ int failed, enough, j, missing = 0;
|
||||||
|
struct imsm_map *map;
|
||||||
|
+ __u8 state;
|
||||||
|
|
||||||
|
+ failed = imsm_count_failed(super, dev, MAP_0);
|
||||||
|
+ state = imsm_check_degraded(super, dev, failed, MAP_0);
|
||||||
|
map = get_imsm_map(dev, MAP_0);
|
||||||
|
|
||||||
|
/* any newly missing disks?
|
||||||
|
@@ -3836,11 +3840,37 @@ static void getinfo_super_imsm(struct supertype *st, struct mdinfo *info, char *
|
||||||
|
|
||||||
|
if (!(ord & IMSM_ORD_REBUILD) &&
|
||||||
|
get_imsm_missing(super, idx)) {
|
||||||
|
+ missing = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ if (state == IMSM_T_STATE_FAILED)
|
||||||
|
+ enough = -1;
|
||||||
|
+ else if (state == IMSM_T_STATE_DEGRADED &&
|
||||||
|
+ (state != map->map_state || missing))
|
||||||
|
+ enough = 0;
|
||||||
|
+ else /* we're normal, or already degraded */
|
||||||
|
+ enough = 1;
|
||||||
|
+ if (is_gen_migration(dev) && missing) {
|
||||||
|
+ /* during general migration we need all disks
|
||||||
|
+ * that process is running on.
|
||||||
|
+ * No new missing disk is allowed.
|
||||||
|
+ */
|
||||||
|
+ max_enough = -1;
|
||||||
|
+ enough = -1;
|
||||||
|
+ /* no more checks necessary
|
||||||
|
+ */
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ /* in the missing/failed disk case check to see
|
||||||
|
+ * if at least one array is runnable
|
||||||
|
+ */
|
||||||
|
+ max_enough = max(max_enough, enough);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ info->container_enough = max_enough;
|
||||||
|
+
|
||||||
|
if (super->disks) {
|
||||||
|
__u32 reserved = imsm_reserved_sectors(super, super->disks);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.32.0 (Apple Git-132)
|
||||||
|
|
@ -0,0 +1,42 @@
|
|||||||
|
From 582945c2d3bbead4a71de521a392e292a4a84e24 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pawel Piatkowski <pawel.piatkowski@intel.com>
|
||||||
|
Date: Wed, 20 Dec 2023 10:32:49 +0100
|
||||||
|
Subject: [PATCH 1/1] manage: adjust checking subarray state in update_subarray
|
||||||
|
|
||||||
|
Only changing bitmap related consistency_policy requires
|
||||||
|
subarray to be inactive.
|
||||||
|
consistency_policy with PPL or NO_PPL value can be changed on
|
||||||
|
active subarray.
|
||||||
|
It fixes regression introduced in commit
|
||||||
|
db10eab68e652f141169 ("Fix --update-subarray on active volume")
|
||||||
|
|
||||||
|
Signed-off-by: Pawel Piatkowski <pawel.piatkowski@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Manage.c | 3 ++-
|
||||||
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Manage.c b/Manage.c
|
||||||
|
index f0d4cb01..91532266 100644
|
||||||
|
--- a/Manage.c
|
||||||
|
+++ b/Manage.c
|
||||||
|
@@ -1749,6 +1749,7 @@ int Update_subarray(char *dev, char *subarray, enum update_opt update,
|
||||||
|
int fd, rv = 2;
|
||||||
|
struct mdinfo *info = NULL;
|
||||||
|
char *update_verb = map_num(update_options, update);
|
||||||
|
+ bool allow_active = update == UOPT_PPL || update == UOPT_NO_PPL;
|
||||||
|
|
||||||
|
memset(st, 0, sizeof(*st));
|
||||||
|
|
||||||
|
@@ -1763,7 +1764,7 @@ int Update_subarray(char *dev, char *subarray, enum update_opt update,
|
||||||
|
goto free_super;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (is_subarray_active(subarray, st->devnm)) {
|
||||||
|
+ if (!allow_active && is_subarray_active(subarray, st->devnm)) {
|
||||||
|
if (verbose >= 0)
|
||||||
|
pr_err("Subarray %s in %s is active, cannot update %s\n",
|
||||||
|
subarray, dev, update_verb);
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
@ -0,0 +1,61 @@
|
|||||||
|
From ea2ca7ed3dbbf881ce08d80fe371f2aaf05011c3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Date: Thu, 18 Jan 2024 11:30:18 +0100
|
||||||
|
Subject: [PATCH 1/1] Grow: Move update_tail assign to Grow_reshape()
|
||||||
|
|
||||||
|
Due to e919fb0af245 ("FIX: Enable metadata updates for raid0") code
|
||||||
|
can't enter super-intel.c:3415, resulting in checkpoint not being
|
||||||
|
saved to metadata for second volume in matrix raid array.
|
||||||
|
This results in checkpoint being stuck at last value for the
|
||||||
|
first volume.
|
||||||
|
|
||||||
|
Move st->update_tail to Grow_reshape() so it is assigned for each
|
||||||
|
volume.
|
||||||
|
|
||||||
|
Signed-off-by: Mateusz Kusiak <mateusz.kusiak@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Grow.c | 13 +++++++------
|
||||||
|
1 file changed, 7 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Grow.c b/Grow.c
|
||||||
|
index f95dae82..5498e54f 100644
|
||||||
|
--- a/Grow.c
|
||||||
|
+++ b/Grow.c
|
||||||
|
@@ -2085,9 +2085,10 @@ 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) &&
|
||||||
|
- st->update_tail == NULL)
|
||||||
|
- st->update_tail = &st->updates;
|
||||||
|
+ if (mdmon_running(st->container_devnm) == false) {
|
||||||
|
+ pr_err("No mdmon found. Grow cannot continue.\n");
|
||||||
|
+ goto release;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->size == MAX_SIZE)
|
||||||
|
@@ -3048,6 +3049,8 @@ static int reshape_array(char *container, int fd, char *devname,
|
||||||
|
dprintf("Cannot get array information.\n");
|
||||||
|
goto release;
|
||||||
|
}
|
||||||
|
+ if (st->update_tail == NULL)
|
||||||
|
+ st->update_tail = &st->updates;
|
||||||
|
if (array.level == 0 && info->component_size == 0) {
|
||||||
|
get_dev_size(fd, NULL, &array_size);
|
||||||
|
info->component_size = array_size / array.raid_disks;
|
||||||
|
@@ -5152,9 +5155,7 @@ int Grow_continue_command(char *devname, int fd,
|
||||||
|
start_mdmon(container);
|
||||||
|
ping_monitor(container);
|
||||||
|
|
||||||
|
- if (mdmon_running(container))
|
||||||
|
- st->update_tail = &st->updates;
|
||||||
|
- else {
|
||||||
|
+ if (mdmon_running(container) == false) {
|
||||||
|
pr_err("No mdmon found. Grow cannot continue.\n");
|
||||||
|
ret_val = 1;
|
||||||
|
goto Grow_continue_command_exit;
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
@ -0,0 +1,55 @@
|
|||||||
|
From b0f4e8e30f38d83f7e3f53d01d72d4cb3b4d42d7 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
|
||||||
|
Date: Tue, 7 May 2024 05:38:55 +0200
|
||||||
|
Subject: [PATCH 1/2] util.c: change devnm to const in mdmon functions
|
||||||
|
|
||||||
|
Devnm shall not be changed inside mdmon_running()
|
||||||
|
and mdmon_pid() functions, change this parameter to const.
|
||||||
|
|
||||||
|
Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
mdadm.h | 4 ++--
|
||||||
|
util.c | 4 ++--
|
||||||
|
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index 2ff3e463..1ba541fc 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -1768,8 +1768,8 @@ extern int is_subarray_active(char *subarray, char *devname);
|
||||||
|
extern int open_subarray(char *dev, char *subarray, struct supertype *st, int quiet);
|
||||||
|
extern struct superswitch *version_to_superswitch(char *vers);
|
||||||
|
|
||||||
|
-extern int mdmon_running(char *devnm);
|
||||||
|
-extern int mdmon_pid(char *devnm);
|
||||||
|
+extern int mdmon_running(const char *devnm);
|
||||||
|
+extern int mdmon_pid(const char *devnm);
|
||||||
|
extern int check_env(char *name);
|
||||||
|
extern __u32 random32(void);
|
||||||
|
extern void random_uuid(__u8 *buf);
|
||||||
|
diff --git a/util.c b/util.c
|
||||||
|
index 4fbf11c4..e2b490e1 100644
|
||||||
|
--- a/util.c
|
||||||
|
+++ b/util.c
|
||||||
|
@@ -1902,7 +1902,7 @@ unsigned long long min_recovery_start(struct mdinfo *array)
|
||||||
|
return recovery_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
-int mdmon_pid(char *devnm)
|
||||||
|
+int mdmon_pid(const char *devnm)
|
||||||
|
{
|
||||||
|
char path[100];
|
||||||
|
char pid[10];
|
||||||
|
@@ -1922,7 +1922,7 @@ int mdmon_pid(char *devnm)
|
||||||
|
return atoi(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
-int mdmon_running(char *devnm)
|
||||||
|
+int mdmon_running(const char *devnm)
|
||||||
|
{
|
||||||
|
int pid = mdmon_pid(devnm);
|
||||||
|
if (pid <= 0)
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
@ -0,0 +1,121 @@
|
|||||||
|
From aa1cc5815d2b14a8b47add18cfaa8264e19c10ce Mon Sep 17 00:00:00 2001
|
||||||
|
From: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
|
||||||
|
Date: Tue, 7 May 2024 05:38:56 +0200
|
||||||
|
Subject: [PATCH 2/2] Wait for mdmon when it is stared via systemd
|
||||||
|
|
||||||
|
When mdmon is being started it may need few seconds to start.
|
||||||
|
For now, we didn't wait for it. Introduce wait_for_mdmon()
|
||||||
|
function, which waits up to 5 seconds for mdmon to start completely.
|
||||||
|
|
||||||
|
Signed-off-by: Kinga Stefaniuk <kinga.stefaniuk@intel.com>
|
||||||
|
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
|
||||||
|
---
|
||||||
|
Assemble.c | 4 ++--
|
||||||
|
Grow.c | 7 ++++---
|
||||||
|
mdadm.h | 2 ++
|
||||||
|
util.c | 29 +++++++++++++++++++++++++++++
|
||||||
|
4 files changed, 37 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/Assemble.c b/Assemble.c
|
||||||
|
index f5e9ab1f..83dced19 100644
|
||||||
|
--- a/Assemble.c
|
||||||
|
+++ b/Assemble.c
|
||||||
|
@@ -2173,8 +2173,8 @@ int assemble_container_content(struct supertype *st, int mdfd,
|
||||||
|
if (!mdmon_running(st->container_devnm))
|
||||||
|
start_mdmon(st->container_devnm);
|
||||||
|
ping_monitor(st->container_devnm);
|
||||||
|
- if (mdmon_running(st->container_devnm) &&
|
||||||
|
- st->update_tail == NULL)
|
||||||
|
+ if (wait_for_mdmon(st->container_devnm) == MDADM_STATUS_SUCCESS &&
|
||||||
|
+ !st->update_tail)
|
||||||
|
st->update_tail = &st->updates;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/Grow.c b/Grow.c
|
||||||
|
index 87ed9214..1923c27c 100644
|
||||||
|
--- a/Grow.c
|
||||||
|
+++ b/Grow.c
|
||||||
|
@@ -2134,7 +2134,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;
|
||||||
|
}
|
||||||
|
@@ -3218,7 +3218,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -5173,7 +5174,7 @@ int Grow_continue_command(char *devname, int fd, struct context *c)
|
||||||
|
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;
|
||||||
|
diff --git a/mdadm.h b/mdadm.h
|
||||||
|
index 1ba541fc..b71d7b32 100644
|
||||||
|
--- a/mdadm.h
|
||||||
|
+++ b/mdadm.h
|
||||||
|
@@ -1770,6 +1770,8 @@ extern struct superswitch *version_to_superswitch(char *vers);
|
||||||
|
|
||||||
|
extern int mdmon_running(const char *devnm);
|
||||||
|
extern int mdmon_pid(const char *devnm);
|
||||||
|
+extern mdadm_status_t wait_for_mdmon(const char *devnm);
|
||||||
|
+
|
||||||
|
extern int check_env(char *name);
|
||||||
|
extern __u32 random32(void);
|
||||||
|
extern void random_uuid(__u8 *buf);
|
||||||
|
diff --git a/util.c b/util.c
|
||||||
|
index e2b490e1..bf79742f 100644
|
||||||
|
--- a/util.c
|
||||||
|
+++ b/util.c
|
||||||
|
@@ -1932,6 +1932,35 @@ int mdmon_running(const char *devnm)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/*
|
||||||
|
+ * wait_for_mdmon() - Waits for mdmon within specified time.
|
||||||
|
+ * @devnm: Device for which mdmon should start.
|
||||||
|
+ *
|
||||||
|
+ * Function waits for mdmon to start. It may need few seconds
|
||||||
|
+ * to start, we set timeout to 5, it should be sufficient.
|
||||||
|
+ * Do not wait if mdmon has been started.
|
||||||
|
+ *
|
||||||
|
+ * Return: MDADM_STATUS_SUCCESS if mdmon is running, error code otherwise.
|
||||||
|
+ */
|
||||||
|
+mdadm_status_t wait_for_mdmon(const char *devnm)
|
||||||
|
+{
|
||||||
|
+ const time_t mdmon_timeout = 5;
|
||||||
|
+ time_t start_time = time(0);
|
||||||
|
+
|
||||||
|
+ if (mdmon_running(devnm))
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+
|
||||||
|
+ pr_info("Waiting for mdmon to start\n");
|
||||||
|
+ while (time(0) - start_time < mdmon_timeout) {
|
||||||
|
+ sleep_for(0, MSEC_TO_NSEC(200), true);
|
||||||
|
+ if (mdmon_running(devnm))
|
||||||
|
+ return MDADM_STATUS_SUCCESS;
|
||||||
|
+ };
|
||||||
|
+
|
||||||
|
+ pr_err("Timeout waiting for mdmon\n");
|
||||||
|
+ return MDADM_STATUS_ERROR;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int start_mdmon(char *devnm)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
Loading…
Reference in new issue