Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
M
mtd-utils
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
pkg
mtd-utils
Merge requests
!2
Wip/martyn/t7336 speed up ubihealthd shutdown
Code
Review changes
Check out branch
Download
Patches
Plain diff
Merged
Wip/martyn/t7336 speed up ubihealthd shutdown
wip/martyn/T7336-Speed-up-ubihealthd-shutdown
into
apertis/v2021dev3
Overview
0
Commits
2
Pipelines
1
Changes
3
Merged
Martyn Welch
requested to merge
wip/martyn/T7336-Speed-up-ubihealthd-shutdown
into
apertis/v2021dev3
4 years ago
Overview
0
Commits
2
Pipelines
1
Changes
3
Expand
0
0
Merge request reports
Compare
apertis/v2021dev3
apertis/v2021dev3 (base)
and
latest version
latest version
64188fb8
2 commits,
4 years ago
3 files
+
183
−
0
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
Files
3
Search (e.g. *.vue) (Ctrl+P)
debian/patches/0011-ubihealthd-Updated-ubihealthd-to-handle-large-UBI-vo.patch
0 → 100644
+
172
−
0
Options
From: Govindaraji Sivanantham <Govindaraji.Sivanantham@in.bosch.com>
Date: Tue, 25 Aug 2020 11:23:57 +0000
Subject: ubihealthd : Updated ubihealthd to handle large UBI volumes and fix
some issues
This patch updates ubihealthd for the following things,
1) Do statistic updates in chunk of 500 erase blocks.
2) Updated logic to read stats from the pre-existing stat file.
3) Checked shutdown flag before doing read or scrub work
4) Fixed incorrect value of peb number passing to read_peb and scrub_peb.
Note : This is an update to the work which Richard did in past
(https://lwn.net/Articles/663751/). Without these changes, ubihealthd
will cause heavy CPU load and won't respond to user signals when running
with large UBI volumes. I have tested these changes on target HW
where UBI volume size is greater than 60 GB.
Signed-off-by: Ronak Desai <ronak.desai@rockwellcollins.com>
[Govindaraji Sivanantham: Removed nanosleep calls]
Signed-off-by: Govindaraji Sivanantham <Govindaraji.Sivanantham@in.bosch.com>
[Martyn Welch: Reformatted commit message, added description of Govindaraji's changes]
Signed-off-by: Martyn Welch <martyn.welch@collabora.com>
---
ubi-utils/ubihealthd.c | 65 +++++++++++++++++++++++++++++++++++++++-----------
1 file changed, 51 insertions(+), 14 deletions(-)
diff --git a/ubi-utils/ubihealthd.c b/ubi-utils/ubihealthd.c
index 97ffbac..b46a6fa 100644
--- a/ubi-utils/ubihealthd.c
+++ b/ubi-utils/ubihealthd.c
@@ -35,6 +35,9 @@
#define log_info(M, ...) _log(3, "[INFO]" M, ##__VA_ARGS__);
#define log_debug(M, ...) _log(4, "[DEBUG]" M, ##__VA_ARGS__);
+#define STAT_PEB_CHUNK (500)
+static int peb_start;
+static int peb_end;
int log_level;
@@ -275,8 +278,23 @@
static int update_stats(int fd, struct peb_list *head, int pnum)
return -1;
}
log_debug("Kernel reported stats for %d PEBs", err);
+
+ /* Divide the total number of PEBs in a small chunk(STAT_PEB_CHUNK) for
+ * statistic updates so that statistic updates can be done in parts.
+ */
+ if (err > STAT_PEB_CHUNK)
+ {
+ if ((peb_start + STAT_PEB_CHUNK) < err)
+ peb_end = (peb_start + STAT_PEB_CHUNK);
+ else
+ peb_end = err;
+ }
+ else
+ peb_end = err;
+
+ log_debug("--> peb_start = %d, peb_end = %d PEBs", peb_start, peb_end);
time_t now = time(NULL);
- for (i = 0; i < err; i++) {
+ for (i = peb_start; i < peb_end; i++) {
struct ubi_stats_entry *s = &req->stats[i];
struct peb_list *p = NULL;
struct peb_info *peb = NULL;
@@ -299,6 +317,18 @@
static int update_stats(int fd, struct peb_list *head, int pnum)
peb->prev_read_cnt = peb->read_cnt;
peb->last_stat_update = now;
}
+
+ if (err > STAT_PEB_CHUNK)
+ {
+ if (peb_end == err)
+ {
+ peb_start = 0;
+ peb_end = 0;
+ }
+ else
+ peb_start += STAT_PEB_CHUNK;
+ }
+
free(req);
return 0;
}
@@ -306,8 +336,9 @@
static int update_stats(int fd, struct peb_list *head, int pnum)
static int read_peb(int fd, struct peb_info *peb)
{
time_t now = time(NULL);
+ int32_t peb_num = (int32_t)peb->peb_num;
log_debug("Reading PEB %"PRIu64 , peb->peb_num);
- int err = ioctl(fd, UBI_IOCRPEB, &peb->peb_num);
+ int err = ioctl(fd, UBI_IOCRPEB, &peb_num);
if (err < 0) {
log_err("Error while reading PEB %" PRIu64, peb->peb_num);
return -1;
@@ -319,8 +350,9 @@
static int read_peb(int fd, struct peb_info *peb)
static int scrub_peb(int fd, struct peb_info *peb)
{
time_t now = time(NULL);
+ int32_t peb_num = (int32_t)peb->peb_num;
log_debug("Scrubbing PEB %"PRIu64, peb->peb_num);
- int err = ioctl (fd, UBI_IOCSPEB, &peb->peb_num);
+ int err = ioctl (fd, UBI_IOCSPEB, &peb_num);
if (err < 0) {
log_err("Error while scrubbing PEB %" PRIu64, peb->peb_num);
return -1;
@@ -418,19 +450,18 @@
static int read_stats_file(const char *filename, struct peb_list *peb_head, stru
fread(&num_pebs, sizeof(num_pebs), 1, file);
fread(&next_read_peb, sizeof(next_read_peb), 1, file);
fread(&next_scrub_peb, sizeof(next_scrub_peb), 1, file);
- for (i = 0; i < num_pebs; i++) {
+
+ struct peb_list *q = NULL;
+ list_for_each_entry(q, &peb_head->list, list) {
struct peb_info *peb = malloc(sizeof(struct peb_info));
if (!peb) {
log_err("Could not allocate peb_info");
return -1;
}
- struct peb_list *p = NULL;
fread(peb, sizeof(struct peb_info), 1, file);
- list_for_each_entry(p, &peb_head->list, list) {
- if (p->peb && (p->peb->peb_num == peb->peb_num)) {
- free(p->peb);
- p->peb = peb;
- }
+ if (q->peb && (q->peb->peb_num == peb->peb_num)) {
+ free(q->peb);
+ q->peb = peb;
}
}
/* init read and scrub lists */
@@ -632,7 +663,7 @@
int main(int argc, char **argv)
}
}
/* stats timer */
- if (pfd[1].revents & POLLIN) {
+ if ((pfd[1].revents & POLLIN) && !shutdown) {
uint64_t tmp;
read(stats_timer, &tmp, sizeof(tmp));
/* update stats */
@@ -651,13 +682,19 @@
int main(int argc, char **argv)
/* read whole PEB if number of reads since last check is above threshold */
if (read_stats >= read_threshold) {
log_info("Too many reads for PEB %" PRIu64 " between stats updates, scheduling READ", peb->peb_num);
- read_peb(fd, peb);
+ if (!read_peb(fd, peb))
+ {
+ /* No need to wait to update previous read count as
+ * read is performed successfully.
+ */
+ peb->prev_read_cnt = peb->read_cnt;
+ }
}
}
}
/* read_peb_timer */
- if (pfd[2].revents & POLLIN) {
+ if ((pfd[2].revents & POLLIN) && !shutdown) {
uint64_t tmp;
read(pfd[2].fd, &tmp, sizeof(tmp));
/* do next peb read */
@@ -667,7 +704,7 @@
int main(int argc, char **argv)
}
/* scrub pebs */
- if (pfd[3].revents & POLLIN) {
+ if ((pfd[3].revents & POLLIN) && !shutdown) {
uint64_t tmp;
read(pfd[3].fd, &tmp, sizeof(tmp));
/* do next peb scrub */
Loading