| From aa11d788b935a8b86976ffaa822e4ccdea9cf09f Mon Sep 17 00:00:00 2001 |
| From: Bryan Yu <yuholong@google.com> |
| Date: Wed, 19 Oct 2022 13:31:24 +0900 |
| Subject: [PATCH] CHROMIUM: Reland of add implementation of MGLRU in sysfs |
| |
| This is a reland of CL:3839069 fixing the memcg bug and snprintf buffer |
| overflow. |
| Tested on ARM device with both memcg on and off. |
| This cherry-pick also contains the changes in CL:4004384. |
| |
| BUG=b:254153610 |
| TEST=Manual testing on DUT |
| |
| Signed-off-by: Bryan Yu <yuholong@google.com> |
| Change-Id: I7dcd354fadda7b4a28c787f6b28dfbce3d1c2f87 |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3965160 |
| Reviewed-by: Suleiman Souhlal <suleiman@chromium.org> |
| Commit-Queue: Alexandre Marciano Gimenez <raging@google.com> |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3998276 |
| Reviewed-by: Alexandre Marciano Gimenez <raging@google.com> |
| Commit-Queue: Koki Ryu <kokiryu@chromium.org> |
| Tested-by: Koki Ryu <kokiryu@chromium.org> |
| Reviewed-by: Koki Ryu <kokiryu@chromium.org> |
| |
| [rebase61(tzungbi): |
| Squashed: |
| FIXUP: CHROMIUM: Reland of add implementation of MGLRU in sysfs |
| ] |
| Signed-off-by: Tzung-Bi Shih <tzungbi@chromium.org> |
| --- |
| mm/vmscan.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| 1 file changed, 159 insertions(+) |
| |
| diff --git a/mm/vmscan.c b/mm/vmscan.c |
| index 9129a0c93f55412f441e05af84db91097f7468d4..d0e86bf3c7c8ca57ccd70cdbe78c117c46431c01 100644 |
| --- a/mm/vmscan.c |
| +++ b/mm/vmscan.c |
| @@ -5751,6 +5751,15 @@ static void lru_gen_change_state(bool enabled) |
| * sysfs interface |
| ******************************************************************************/ |
| |
| +static int run_aging(struct lruvec *lruvec, unsigned long seq, struct scan_control *sc, |
| + bool can_swap, bool force_scan); |
| + |
| +static int run_eviction(struct lruvec *lruvec, unsigned long seq, struct scan_control *sc, |
| + int swappiness, unsigned long nr_to_reclaim); |
| + |
| +static int run_cmd(char cmd, int memcg_id, int nid, unsigned long seq, |
| + struct scan_control *sc, int swappiness, unsigned long opt); |
| + |
| static ssize_t min_ttl_ms_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) |
| { |
| return sysfs_emit(buf, "%u\n", jiffies_to_msecs(READ_ONCE(lru_gen_min_ttl))); |
| @@ -5818,9 +5827,159 @@ static ssize_t enabled_store(struct kobject *kobj, struct kobj_attribute *attr, |
| |
| static struct kobj_attribute lru_gen_enabled_attr = __ATTR_RW(enabled); |
| |
| +static int print_node_mglru(struct lruvec *lruvec, char *buf, int orig_pos) |
| +{ |
| + unsigned long seq; |
| + struct lru_gen_struct *lrugen = &lruvec->lrugen; |
| + |
| + DEFINE_MAX_SEQ(lruvec); |
| + DEFINE_MIN_SEQ(lruvec); |
| + |
| + int print_pos = orig_pos; |
| + |
| + seq = min(min_seq[0], min_seq[1]); |
| + |
| + for (; seq <= max_seq; seq++) { |
| + int gen, type, zone; |
| + unsigned int msecs; |
| + |
| + gen = lru_gen_from_seq(seq); |
| + msecs = jiffies_to_msecs(jiffies - READ_ONCE(lrugen->timestamps[gen])); |
| + |
| + print_pos += snprintf(buf + print_pos, PAGE_SIZE - print_pos, |
| + " %10lu %10u", seq, msecs); |
| + |
| + for (type = 0; type < ANON_AND_FILE; type++) { |
| + long size = 0; |
| + |
| + if (seq < min_seq[type]) { |
| + print_pos += snprintf(buf + print_pos, |
| + PAGE_SIZE - print_pos, " -0 "); |
| + continue; |
| + } |
| + |
| + for (zone = 0; zone < MAX_NR_ZONES; zone++) |
| + size += READ_ONCE(lrugen->nr_pages[gen][type][zone]); |
| + |
| + print_pos += snprintf(buf + print_pos, |
| + PAGE_SIZE - print_pos, " %10lu ", max(size, 0L)); |
| + } |
| + |
| + print_pos += snprintf(buf + print_pos, PAGE_SIZE - print_pos, "\n"); |
| + |
| + } |
| + |
| + return print_pos - orig_pos; |
| +} |
| + |
| +static ssize_t show_lru_gen_admin(struct kobject *kobj, struct kobj_attribute *attr, char *buf) |
| +{ |
| + struct lruvec *lruvec; |
| + struct mem_cgroup *memcg; |
| + |
| + char *path = kvmalloc(PATH_MAX, GFP_KERNEL); |
| + int buf_len = 0; |
| + |
| + if (!path) |
| + return -EINVAL; |
| + path[0] = 0; |
| + buf[0] = 0; |
| + memcg = mem_cgroup_iter(NULL, NULL, NULL); |
| + do { |
| + int nid; |
| + |
| + for_each_node_state(nid, N_MEMORY) { |
| + lruvec = mem_cgroup_lruvec(memcg, NODE_DATA(nid)); |
| + if (lruvec) { |
| + if (nid == first_memory_node) { |
| +#ifdef CONFIG_MEMCG |
| + if (memcg) |
| + cgroup_path(memcg->css.cgroup, path, PATH_MAX); |
| + else |
| + path[0] = 0; |
| +#endif |
| + buf_len += snprintf(buf + buf_len, PAGE_SIZE - buf_len, |
| + "memcg %5hu %s\n", mem_cgroup_id(memcg), path); |
| + } |
| + |
| + buf_len += snprintf(buf + buf_len, PAGE_SIZE - buf_len, |
| + " node %5d\n", nid); |
| + buf_len += print_node_mglru(lruvec, buf, buf_len); |
| + } |
| + } |
| + } while ((memcg = mem_cgroup_iter(NULL, memcg, NULL))); |
| + |
| + if (buf_len >= PAGE_SIZE) |
| + buf_len = PAGE_SIZE - 1; |
| + buf[buf_len] = 0; |
| + |
| + kvfree(path); |
| + |
| + return buf_len; |
| +} |
| + |
| +static ssize_t store_lru_gen_admin(struct kobject *kobj, struct kobj_attribute *attr, |
| + const char *src, size_t len) |
| +{ |
| + void *buf; |
| + char *cur, *next; |
| + int err = 0; |
| + struct scan_control sc = { |
| + .may_writepage = true, |
| + .may_unmap = true, |
| + .may_swap = true, |
| + .reclaim_idx = MAX_NR_ZONES - 1, |
| + .gfp_mask = GFP_KERNEL, |
| + }; |
| + |
| + buf = kvmalloc(len + 1, GFP_USER); |
| + if (!buf) |
| + return -ENOMEM; |
| + |
| + memcpy(buf, src, len); |
| + |
| + next = buf; |
| + next[len] = '\0'; |
| + |
| + while ((cur = strsep(&next, ",;\n"))) { |
| + int n; |
| + int end; |
| + char cmd; |
| + unsigned int memcg_id; |
| + unsigned int nid; |
| + unsigned long seq; |
| + unsigned int swappiness = -1; |
| + unsigned long nr_to_reclaim = -1; |
| + |
| + cur = skip_spaces(cur); |
| + if (!*cur) |
| + continue; |
| + |
| + n = sscanf(cur, "%c %u %u %lu %n %u %n %lu %n", &cmd, &memcg_id, &nid, |
| + &seq, &end, &swappiness, &end, &nr_to_reclaim, &end); |
| + if (n < 4 || cur[end]) { |
| + err = -EINVAL; |
| + break; |
| + } |
| + |
| + err = run_cmd(cmd, memcg_id, nid, seq, &sc, swappiness, nr_to_reclaim); |
| + if (err) |
| + break; |
| + } |
| + |
| + kvfree(buf); |
| + |
| + return err ? : len; |
| +} |
| + |
| +static struct kobj_attribute lru_gen_admin_attr = __ATTR( |
| + admin, 0644, show_lru_gen_admin, store_lru_gen_admin |
| +); |
| + |
| static struct attribute *lru_gen_attrs[] = { |
| &lru_gen_min_ttl_attr.attr, |
| &lru_gen_enabled_attr.attr, |
| + &lru_gen_admin_attr.attr, |
| NULL |
| }; |
| |
| -- |
| 2.38.3 |
| |